You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
6.3 KiB
Python
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)
|
|
|
|
|