diff --git a/playground/xilinx-ise/.gitignore b/playground/xilinx-ise/.gitignore new file mode 100644 index 00000000..a4b9fd51 --- /dev/null +++ b/playground/xilinx-ise/.gitignore @@ -0,0 +1,44 @@ +*~ +*.bgn +*.bit +*.bld +*.drc +*.lso +*.ncd +*.ngc +*.ngd +*.ngr +*.pad +*.par +*.pcf +*.prj +*.ptwx +*.syr +*.twr +*.twx +*.unroutes +*.ut +*.xpi +*.xst +*_bitgen.xwbt +*_map.map +*_map.mrp +*_map.ncd +*_map.ngm +*_map.xrpt +*_ngdbuild.xrpt +*_pad.csv +*_pad.txt +*_par.xrpt +*_summary.xml +*_usage.xml +*_xst.xrpt +_ngo +_xmsgs +c4che +config.log +usage_statistics_webtalk.html +xlnx_auto_0_xdb +xst +webtalk.log + diff --git a/playground/xilinx-ise/src/rs1.ucf b/playground/xilinx-ise/src/rs1.ucf new file mode 100644 index 00000000..3417002e --- /dev/null +++ b/playground/xilinx-ise/src/rs1.ucf @@ -0,0 +1,8 @@ +NET "DLED_2" LOC = "AB5" | IOSTANDARD = LVTTL | DRIVE = 24 ; +NET "DLED_3" LOC = "AA5" | IOSTANDARD = LVTTL | DRIVE = 24 ; +NET "DLED_4" LOC = "AA4" | IOSTANDARD = LVTTL | DRIVE = 24 ; +NET "DLED_5" LOC = "AB4" | IOSTANDARD = LVTTL | DRIVE = 24 ; + +NET "BUTTON_1" LOC = "AA3" | IOSTANDARD = LVTTL | PULLUP ; +NET "BUTTON_2" LOC = "Y4" | IOSTANDARD = LVTTL | PULLUP ; + diff --git a/playground/xilinx-ise/src/top.vhd b/playground/xilinx-ise/src/top.vhd new file mode 100644 index 00000000..cb8d895b --- /dev/null +++ b/playground/xilinx-ise/src/top.vhd @@ -0,0 +1,34 @@ +--+-------------------------------------------------------------------------------------------------+ +--| +--| VHDL example for waf build automation tool +--| +--+-------------------------------------------------------------------------------------------------+ + +library ieee; +use ieee.std_logic_1164.all; + +entity waf_demo is +port ( + -- buttons + BUTTON_1 : in std_logic; + BUTTON_2 : in std_logic; + + -- leds + DLED_2 : out std_logic; + DLED_3 : out std_logic; + DLED_4 : out std_logic; + DLED_5 : out std_logic +); +end waf_demo; + +architecture inside of waf_demo is + +begin + + DLED_5 <= '1'; + DLED_4 <= BUTTON_2; + DLED_3 <= '0'; + DLED_2 <= not BUTTON_1; + +end inside; + diff --git a/playground/xilinx-ise/waf_demo.xise b/playground/xilinx-ise/waf_demo.xise new file mode 100644 index 00000000..c2fd3703 --- /dev/null +++ b/playground/xilinx-ise/waf_demo.xise @@ -0,0 +1,372 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/playground/xilinx-ise/wscript b/playground/xilinx-ise/wscript new file mode 100644 index 00000000..f4dd94e9 --- /dev/null +++ b/playground/xilinx-ise/wscript @@ -0,0 +1,282 @@ +#!/usr/bin/env python +# encoding: utf-8 +# waf example, builds a Xilinx FPGA bitstream + +__copyright__ = '(c) Jérôme Carretero 2012' +__license__ = 'DWTFYWPL' + +""" +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): + with open(self.outputs[0].abspath(), "w") as f: + f.write("\n".join(prj)) + + def make_xst(self): + with open(self.outputs[0].abspath(), "w") as f: + fn, device, speed, package + f.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): + with open(self.outputs[0].abspath(), "w") as f: + fn, device, speed, package + f.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], + ) + + for tgen in bld.get_all_task_gen(): + tgen.update_outputs=True + + 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.unlink(tgt) + for x in ( + 'usage_statistics_webtalk.html', + 'webtalk_pn.xml', + 'webtalk.log', + ): + if os.path.exists(x): + os.unlink(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_') or fn.startswith(".lock-w") \ + or fn in (Context.DBFILE, 'config.log') \ + or fn == 'c4che': + if os.path.isdir(fn): + shutil.rmtree(fn) + else: + os.unlink(fn) + +