waf/playground/xilinx-ise/wscript

274 lines
6.3 KiB
Python

#!/usr/bin/env python
# encoding: utf-8
# waf example, builds a Xilinx FPGA bitstream
__copyright__ = '(c) Jérôme Carretero <cJ-waf@zougloub.eu> 2012'
"""
This script builds an FPGA bitstream in an automated fashion.
The Xilinx ISE IDE does the same thing, but needs mouse interaction.
Notes:
- this is quite sad, but the Xilinx toolchain tools want to operate
in the source folder, so top==out
- Xilinx toolchain tools generate file with timestamps,
so an unsignificant change can still trigger domino cascade
of compilations.
- a "xilinx" wrapper is used; this file performs set up of the
PATH for Xilinx tools (not done yet by the wscript)
TODO:
- make a tool
- remove hard-coded .xst / .ut data (ISE generates that from the .xise)
- CPLD toolchain (only works for FPGA)
"""
top = out = "." # mandatory
import os
import shutil
import waflib
from lxml import etree
def options(opt):
pass
def configure(cfg):
pass
def build(bld):
if not os.path.exists("xst/projnav.tmp"):
os.makedirs("xst/projnav.tmp")
nsmap={"pn": "http://www.xilinx.com/XMLSchema"}
xise = "waf_demo.xise"
fn = "waf_demo"
xml = etree.parse(xise)
def get(txt):
try: return xml.xpath('//pn:property[@pn:name = "%s"]/@pn:value' % txt, namespaces=nsmap)[0]
except: pass
device = get("Device") # or "xc3s1500"
package = get("Package") # or "fg456"
speed = get("Speed Grade") # or "-4"
# Set .prj file contents and collect HDL sources
hdl = []
prj = []
for x in xml.xpath('//pn:files/pn:file[@pn:type = "FILE_VHDL"]/@pn:name', namespaces=nsmap):
prj.append('vhdl work "%s"' % x)
hdl.append(x)
for x in xml.xpath('//pn:files/pn:file[@pn:type = "FILE_VERILOG"]/@pn:name', namespaces=nsmap):
prj.append('verilog work "%s"' % x)
hdl.append(x)
ucf = xml.xpath('//pn:files/pn:file[@pn:type = "FILE_UCF"]/@pn:name', namespaces=nsmap)[0] or "src/pci_7seg.ucf"
def make_prj(self):
self.outputs[0].write("\n".join(prj))
def make_xst(self):
self.outputs[0].write("""
set -tmpdir "xst/projnav.tmp"
set -xsthdpdir "xst"
run
-ifn %(fn)s.prj
-ifmt mixed
-ofn %(fn)s
-ofmt NGC
-p %(device)s%(speed)s-%(package)s
-top %(fn)s
-opt_mode Speed
-opt_level 1
-iuc NO
-keep_hierarchy No
-netlist_hierarchy As_Optimized
-rtlview Yes
-glob_opt AllClockNets
-read_cores YES
-write_timing_constraints NO
-cross_clock_analysis NO
-hierarchy_separator /
-bus_delimiter <>
-case Maintain
-slice_utilization_ratio 100
-bram_utilization_ratio 100
-verilog2001 YES
-fsm_extract YES -fsm_encoding Auto
-safe_implementation No
-fsm_style LUT
-ram_extract Yes
-ram_style Auto
-rom_extract Yes
-mux_style Auto
-decoder_extract YES
-priority_extract Yes
-shreg_extract YES
-shift_extract YES
-xor_collapse YES
-rom_style Auto
-auto_bram_packing NO
-mux_extract Yes
-resource_sharing YES
-async_to_sync NO
-mult_style Auto
-iobuf YES
-max_fanout 500
-bufg 8
-register_duplication YES
-register_balancing No
-slice_packing YES
-optimize_primitives NO
-use_clock_enable Yes
-use_sync_set Yes
-use_sync_reset Yes
-iob Auto
-equivalent_register_removal YES
-slice_utilization_ratio_maxmargin 5
""" % locals())
def make_ut(self):
self.outputs[0].write("""
-w
-g DebugBitstream:No
-g Binary:no
-g CRC:Enable
-g ConfigRate:6
-g CclkPin:PullUp
-g M0Pin:PullUp
-g M1Pin:PullUp
-g M2Pin:PullUp
-g ProgPin:PullUp
-g DonePin:PullUp
-g HswapenPin:PullUp
-g TckPin:PullUp
-g TdiPin:PullUp
-g TdoPin:PullUp
-g TmsPin:PullUp
-g UnusedPin:PullDown
-g UserID:0xFFFFFFFF
-g DCMShutdown:Disable
-g DCIUpdateMode:AsRequired
-g StartUpClk:CClk
-g DONE_cycle:4
-g GTS_cycle:5
-g GWE_cycle:6
-g LCK_cycle:NoWait
-g Match_cycle:Auto
-g Security:None
-g DonePipe:No
-g DriveDone:No""")
bld(
name='prj',
target="%s.prj" % fn,
rule=make_prj,
source=[xise],
)
bld(
name='xst',
target='%s.xst' % fn,
rule=make_xst,
source=[xise],
)
bld(
name='ut',
target='%s.ut' % fn,
rule=make_ut,
source=[xise],
)
bld(
name='synth',
target=['%s%s' % (fn, ext) for ext in ('.syr', '.ngc', '.ngr', '.lso', '_xst.xrpt') ],
rule='xilinx xst -intstyle ise -ifn ${SRC[0].abspath()} -ofn ${TGT[0].abspath()}; true',
source=['%s.xst' % fn, '%s.prj' % fn] + hdl,
)
bld(
name='ngdbuild',
target=['%s%s' % (fn, ext) for ext in ('.ngd', '_ngdbuild.xrpt') ],
rule='xilinx ngdbuild -intstyle ise -dd _ngo -nt timestamp -uc ${SRC[1].abspath()} -p %(device)s-%(package)s%(speed)s ${SRC[0].bldpath()} ${TGT[0].bldpath()}' % locals(),
source=['%s.ngc' % fn, ucf],
)
bld(
name='map',
target=['%s%s' % (fn, ext) for ext in ('_map.ncd', '.pcf', '_map.map', '_map.mrp', '_map.ngm', '_map.xrpt', '.bld') ],
rule='xilinx map -intstyle ise -p %(device)s-%(package)s%(speed)s -cm area -ir off -pr b -c 100 -o ${TGT[0].bldpath()} ${SRC[0].bldpath()} ${TGT[1].bldpath()}' % locals(),
source=['%s.ngd' % fn],
)
bld(
name='par',
target=['%s%s' % (fn, ext) for ext in ('.ncd', '.pad', '.par', '.ptwx', '.unroutes', '.xpi', '_pad.csv', '_pad.txt', '_par.xrpt') ],
rule='xilinx par -w -intstyle ise -ol high -t 1 ${SRC[0].bldpath()} ${TGT[0].bldpath()} ${SRC[1].bldpath()}',
source=['%s_map.ncd' % fn, '%s.pcf' % fn],
)
bld(
name='trce',
target=['%s%s' % (fn, ext) for ext in ('.twx', '.twr') ],
rule='xilinx trce -intstyle ise -e 3 -s 4 -n 3 -xml ${TGT[0].bldpath()} ${SRC[0].bldpath()} -o ${TGT[1].bldpath()} ${SRC[1].bldpath()}; true',
source=['%s_map.ncd' % fn, '%s.pcf' % fn],
)
bld(
name='bitgen',
target=['%s%s' % (fn, ext) for ext in ('.bit', '.bgn', '.drc', '_bitgen.xwbt', '_summary.xml', '_usage.xml') ],
rule='xilinx bitgen -intstyle ise -f ${SRC[1].bldpath()} ${SRC[0].bldpath()} ${TGT[0].bldpath()}',
source=['%s.ncd' % fn, '%s.ut' % fn],
)
if bld.cmd == 'clean':
for tgen in bld.get_all_task_gen():
for tgt in waflib.Utils.to_list(tgen.target):
if os.path.exists(tgt):
os.remove(tgt)
for x in (
'usage_statistics_webtalk.html',
'webtalk_pn.xml',
'webtalk.log',
):
if os.path.exists(x):
os.remove(x)
for x in (
'_ngo',
'_xmsgs',
'iseconfig',
'xlnx_auto_0_xdb',
'xst',
):
try:
shutil.rmtree(x)
except:
pass
def distclean(ctx):
import os, shutil
from waflib import Context
for fn in os.listdir('.'):
if fn.startswith(('.conf_check_', ".lock-w")) \
or fn in (Context.DBFILE, 'config.log') \
or fn == 'c4che':
if os.path.isdir(fn):
shutil.rmtree(fn)
else:
os.remove(fn)