<> <> <> <> <<>> 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; primitives: SymTab.Ref _ SymTab.Create[]; -- cell type name to Primitive directionNames: ARRAY InOrOut OF ROPE _ ["I", "O"]; <> seqProp: ATOM = $XilinxIOSeqProp; SeqData: TYPE = REF SeqDataRec; SeqDataRec: TYPE = RECORD [ axis: Axis, startIndex: NAT, orthogonalIndex: NAT, delta: INT]; 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]]]]]; }; <> 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.nameTable _ SymTab.Create[]; 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]; }; trace: BOOL _ FALSE; PruneFlattenedCircuit: PROC [circuit: FlatCircuit] RETURNS [pruned: RefTab.Ref] = { CheckSignal: RefTab.EachPairAction = { signal: Signal _ NARROW[key]; sensed, physical, driven, tristate: BOOL _ FALSE; IF RefTab.Fetch[pruned, signal].found THEN RETURN; [sensed, physical, driven, tristate] _ 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,$Vdd"]; WriteRecord["PWR,0,$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]; }; <> 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]; }; <> NumToLet: PROC [n: NAT] RETURNS [l: CHAR] = { l _ LOOPHOLE[LOOPHOLE['A, NAT] + n]; }; RegisterPrimitive: PUBLIC PROC [coreName: ROPE, proc: TranslateProc, data: REF ANY _ NIL] = { primitive: Primitive _ NEW[PrimitiveRec _ [ translate: proc, data: data]]; [] _ SymTab.Store[primitives, coreName, primitive]; }; PinRecListToPinList: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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: PUBLIC 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 { newFlatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ flatWire^]; signal _ CreateSignal[circuit, SignalName[circuit, root, newFlatWire]]; IF NOT RefTab.Insert[flatWireToSignal, newFlatWire, signal] THEN ERROR; signal.pin _ NARROW[CoreProperties.GetWireProp[flatWire.wire, $Pin]]; }; }; CreateSignal: PUBLIC PROC [circuit: FlatCircuit, name: ROPE _ NIL] RETURNS [signal: Signal] = { signal _ NEW[SignalRec]; IF name=NIL THEN name _ SignalName[circuit, 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]; }; vddName: ROPE _ "Vdd"; gndName: ROPE _ "Gnd"; GlobalDelete: PROC [name: ROPE] RETURNS [yes: BOOL _ FALSE] = { yes _ Rope.Equal[name, vddName] OR Rope.Equal[name, gndName] OR Rope.Equal[name, "RosemaryLogicTime"]; }; <> SignalName: PROC [circuit: FlatCircuit, cellType: Core.CellType, flatWire: CoreFlat.FlatWire] RETURNS [name: ROPE _ NIL] = { <> < />> <> 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[circuit.nameCount]]; circuit.nameCount _ circuit.nameCount + 1; }; IF cellType=NIL OR flatWire=NIL THEN { ManufactureName[]; IF NOT SymTab.Insert[circuit.nameTable, name, $Manufactured] THEN ERROR; } ELSE { old: ROPE _ CoreFlat.WirePathRope[cellType, flatWire^]; shortName: ROPE _ CoreOps.GetShortWireName[flatWire.wire]; IF Rope.Length[old]>7 AND Rope.Equal[Rope.Substr[old, 0, 7], "public."] THEN old _ Rope.Substr[old, 7]; SELECT TRUE FROM Rope.Equal[shortName, vddName] => name _ "$Vdd"; Rope.Equal[shortName, gndName] => name _ "$Gnd"; ENDCASE => [] _ Rope.Map[base: old, action: BuildNew]; IF Rope.Length[name]>16 THEN name _ Rope.Substr[name, Rope.Length[name]-16]; IF NOT SymTab.Insert[circuit.nameTable, name, flatWire] THEN { ManufactureName[]; IF NOT SymTab.Insert[circuit.nameTable, name, flatWire] THEN ERROR; }; }; }; 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: PUBLIC 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]; }; CDCommandOps.RegisterWithMenu[$SpecialMenu, "WriteXNF", "Extract selected cells and write xnf files", $WriteXNF, WriteXNF]; END.