wscript (6407B)
1 #!/usr/bin/env python 2 # encoding: utf-8 3 # waf example, builds a Xilinx FPGA bitstream 4 5 __copyright__ = '(c) Jérôme Carretero <cJ-waf@zougloub.eu> 2012' 6 7 """ 8 This script builds an FPGA bitstream in an automated fashion. 9 The Xilinx ISE IDE does the same thing, but needs mouse interaction. 10 11 Notes: 12 13 - this is quite sad, but the Xilinx toolchain tools want to operate 14 in the source folder, so top==out 15 16 - Xilinx toolchain tools generate file with timestamps, 17 so an unsignificant change can still trigger domino cascade 18 of compilations. 19 20 - a "xilinx" wrapper is used; this file performs set up of the 21 PATH for Xilinx tools (not done yet by the wscript) 22 23 TODO: 24 25 - make a tool 26 - remove hard-coded .xst / .ut data (ISE generates that from the .xise) 27 - CPLD toolchain (only works for FPGA) 28 29 """ 30 31 top = out = "." # mandatory 32 33 import os 34 import shutil 35 import waflib 36 from lxml import etree 37 38 def options(opt): 39 pass 40 41 def configure(cfg): 42 pass 43 44 def build(bld): 45 46 if not os.path.exists("xst/projnav.tmp"): 47 os.makedirs("xst/projnav.tmp") 48 49 nsmap={"pn": "http://www.xilinx.com/XMLSchema"} 50 51 xise = "waf_demo.xise" 52 fn = "waf_demo" 53 xml = etree.parse(xise) 54 55 def get(txt): 56 try: return xml.xpath('//pn:property[@pn:name = "%s"]/@pn:value' % txt, namespaces=nsmap)[0] 57 except: pass 58 59 device = get("Device") # or "xc3s1500" 60 package = get("Package") # or "fg456" 61 speed = get("Speed Grade") # or "-4" 62 63 # Set .prj file contents and collect HDL sources 64 hdl = [] 65 prj = [] 66 for x in xml.xpath('//pn:files/pn:file[@pn:type = "FILE_VHDL"]/@pn:name', namespaces=nsmap): 67 prj.append('vhdl work "%s"' % x) 68 hdl.append(x) 69 for x in xml.xpath('//pn:files/pn:file[@pn:type = "FILE_VERILOG"]/@pn:name', namespaces=nsmap): 70 prj.append('verilog work "%s"' % x) 71 hdl.append(x) 72 73 ucf = xml.xpath('//pn:files/pn:file[@pn:type = "FILE_UCF"]/@pn:name', namespaces=nsmap)[0] or "src/pci_7seg.ucf" 74 75 def make_prj(self): 76 self.outputs[0].write("\n".join(prj)) 77 78 def make_xst(self): 79 self.outputs[0].write(""" 80 set -tmpdir "xst/projnav.tmp" 81 set -xsthdpdir "xst" 82 run 83 -ifn %(fn)s.prj 84 -ifmt mixed 85 -ofn %(fn)s 86 -ofmt NGC 87 -p %(device)s%(speed)s-%(package)s 88 -top %(fn)s 89 -opt_mode Speed 90 -opt_level 1 91 -iuc NO 92 -keep_hierarchy No 93 -netlist_hierarchy As_Optimized 94 -rtlview Yes 95 -glob_opt AllClockNets 96 -read_cores YES 97 -write_timing_constraints NO 98 -cross_clock_analysis NO 99 -hierarchy_separator / 100 -bus_delimiter <> 101 -case Maintain 102 -slice_utilization_ratio 100 103 -bram_utilization_ratio 100 104 -verilog2001 YES 105 -fsm_extract YES -fsm_encoding Auto 106 -safe_implementation No 107 -fsm_style LUT 108 -ram_extract Yes 109 -ram_style Auto 110 -rom_extract Yes 111 -mux_style Auto 112 -decoder_extract YES 113 -priority_extract Yes 114 -shreg_extract YES 115 -shift_extract YES 116 -xor_collapse YES 117 -rom_style Auto 118 -auto_bram_packing NO 119 -mux_extract Yes 120 -resource_sharing YES 121 -async_to_sync NO 122 -mult_style Auto 123 -iobuf YES 124 -max_fanout 500 125 -bufg 8 126 -register_duplication YES 127 -register_balancing No 128 -slice_packing YES 129 -optimize_primitives NO 130 -use_clock_enable Yes 131 -use_sync_set Yes 132 -use_sync_reset Yes 133 -iob Auto 134 -equivalent_register_removal YES 135 -slice_utilization_ratio_maxmargin 5 136 """ % locals()) 137 138 139 140 def make_ut(self): 141 self.outputs[0].write(""" 142 -w 143 -g DebugBitstream:No 144 -g Binary:no 145 -g CRC:Enable 146 -g ConfigRate:6 147 -g CclkPin:PullUp 148 -g M0Pin:PullUp 149 -g M1Pin:PullUp 150 -g M2Pin:PullUp 151 -g ProgPin:PullUp 152 -g DonePin:PullUp 153 -g HswapenPin:PullUp 154 -g TckPin:PullUp 155 -g TdiPin:PullUp 156 -g TdoPin:PullUp 157 -g TmsPin:PullUp 158 -g UnusedPin:PullDown 159 -g UserID:0xFFFFFFFF 160 -g DCMShutdown:Disable 161 -g DCIUpdateMode:AsRequired 162 -g StartUpClk:CClk 163 -g DONE_cycle:4 164 -g GTS_cycle:5 165 -g GWE_cycle:6 166 -g LCK_cycle:NoWait 167 -g Match_cycle:Auto 168 -g Security:None 169 -g DonePipe:No 170 -g DriveDone:No""") 171 172 173 bld( 174 name='prj', 175 target="%s.prj" % fn, 176 rule=make_prj, 177 source=[xise], 178 ) 179 180 bld( 181 name='xst', 182 target='%s.xst' % fn, 183 rule=make_xst, 184 source=[xise], 185 ) 186 bld( 187 name='ut', 188 target='%s.ut' % fn, 189 rule=make_ut, 190 source=[xise], 191 ) 192 193 bld( 194 name='synth', 195 target=['%s%s' % (fn, ext) for ext in ('.syr', '.ngc', '.ngr', '.lso', '_xst.xrpt') ], 196 rule='xilinx xst -intstyle ise -ifn ${SRC[0].abspath()} -ofn ${TGT[0].abspath()}; true', 197 source=['%s.xst' % fn, '%s.prj' % fn] + hdl, 198 ) 199 200 bld( 201 name='ngdbuild', 202 target=['%s%s' % (fn, ext) for ext in ('.ngd', '_ngdbuild.xrpt') ], 203 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(), 204 source=['%s.ngc' % fn, ucf], 205 ) 206 207 bld( 208 name='map', 209 target=['%s%s' % (fn, ext) for ext in ('_map.ncd', '.pcf', '_map.map', '_map.mrp', '_map.ngm', '_map.xrpt', '.bld') ], 210 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(), 211 source=['%s.ngd' % fn], 212 ) 213 214 bld( 215 name='par', 216 target=['%s%s' % (fn, ext) for ext in ('.ncd', '.pad', '.par', '.ptwx', '.unroutes', '.xpi', '_pad.csv', '_pad.txt', '_par.xrpt') ], 217 rule='xilinx par -w -intstyle ise -ol high -t 1 ${SRC[0].bldpath()} ${TGT[0].bldpath()} ${SRC[1].bldpath()}', 218 source=['%s_map.ncd' % fn, '%s.pcf' % fn], 219 ) 220 221 bld( 222 name='trce', 223 target=['%s%s' % (fn, ext) for ext in ('.twx', '.twr') ], 224 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', 225 source=['%s_map.ncd' % fn, '%s.pcf' % fn], 226 ) 227 228 bld( 229 name='bitgen', 230 target=['%s%s' % (fn, ext) for ext in ('.bit', '.bgn', '.drc', '_bitgen.xwbt', '_summary.xml', '_usage.xml') ], 231 rule='xilinx bitgen -intstyle ise -f ${SRC[1].bldpath()} ${SRC[0].bldpath()} ${TGT[0].bldpath()}', 232 source=['%s.ncd' % fn, '%s.ut' % fn], 233 ) 234 235 if bld.cmd == 'clean': 236 for tgen in bld.get_all_task_gen(): 237 for tgt in waflib.Utils.to_list(tgen.target): 238 if os.path.exists(tgt): 239 os.remove(tgt) 240 for x in ( 241 'usage_statistics_webtalk.html', 242 'webtalk_pn.xml', 243 'webtalk.log', 244 ): 245 if os.path.exists(x): 246 os.remove(x) 247 248 for x in ( 249 '_ngo', 250 '_xmsgs', 251 'iseconfig', 252 'xlnx_auto_0_xdb', 253 'xst', 254 ): 255 try: 256 shutil.rmtree(x) 257 except: 258 pass 259 260 def distclean(ctx): 261 import os, shutil 262 from waflib import Context 263 264 for fn in os.listdir('.'): 265 if fn.startswith(('.conf_check_', ".lock-w")) \ 266 or fn in (Context.DBFILE, 'config.log') \ 267 or fn == 'c4che': 268 if os.path.isdir(fn): 269 shutil.rmtree(fn) 270 else: 271 os.remove(fn) 272 273