From 540062c4ed2d96dc945f85ff691bd780cd1466ee Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Fran=C3=A7ois=20Nguyen?= Date: Thu, 6 Jun 2019 13:53:17 +0200 Subject: [PATCH] vendor.xilinx_7series: implement. --- nmigen/vendor/xilinx_7series.py | 256 ++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 nmigen/vendor/xilinx_7series.py diff --git a/nmigen/vendor/xilinx_7series.py b/nmigen/vendor/xilinx_7series.py new file mode 100644 index 0000000..0fbc54b --- /dev/null +++ b/nmigen/vendor/xilinx_7series.py @@ -0,0 +1,256 @@ +from abc import abstractproperty + +from ..hdl.ast import * +from ..hdl.dsl import * +from ..hdl.ir import * +from ..build import * + + +__all__ = ["Xilinx7SeriesPlatform"] + + +class Xilinx7SeriesPlatform(TemplatedPlatform): + """ + Required tools: + * ``vivado`` + + Available overrides: + * ``script_after_read``: inserts commands after ``read_xdc`` in Tcl script. + * ``script_after_synth``: inserts commands after ``synth_design`` in Tcl script. + * ``script_after_place``: inserts commands after ``place_design`` in Tcl script. + * ``script_after_route``: inserts commands after ``route_design`` in Tcl script. + * ``script_before_bitstream``: inserts commands before ``write_bitstream`` in Tcl script. + * ``script_after_bitstream``: inserts commands after ``write_bitstream`` in Tcl script. + * ``add_constraints``: inserts commands in XDC file. + * ``vivado_opts``: adds extra options for Vivado. + + Build products: + * ``{{name}}.log``: Vivado log. + * ``{{name}}_timing_synth.rpt``: Vivado report. + * ``{{name}}_utilization_hierarchical_synth.rpt``: Vivado report. + * ``{{name}}_utilization_synth.rpt``: Vivado report. + * ``{{name}}_utilization_hierarchical_place.rpt``: Vivado report. + * ``{{name}}_utilization_place.rpt``: Vivado report. + * ``{{name}}_io.rpt``: Vivado report. + * ``{{name}}_control_sets.rpt``: Vivado report. + * ``{{name}}_clock_utilization.rpt``: Vivado report. + * ``{{name}}_route_status.rpt``: Vivado report. + * ``{{name}}_drc.rpt``: Vivado report. + * ``{{name}}_timing.rpt``: Vivado report. + * ``{{name}}_power.rpt``: Vivado report. + * ``{{name}}_route.dcp``: Vivado design checkpoint. + * ``{{name}}.bit``: binary bitstream. + """ + + device = abstractproperty() + package = abstractproperty() + speedgrade = abstractproperty() + + file_templates = { + **TemplatedPlatform.build_script_templates, + "{{name}}.v": r""" + /* {{autogenerated}} */ + {{emit_design("verilog")}} + """, + "{{name}}.tcl": r""" + # {{autogenerated}} + create_project -force -name {{name}} -part {{platform.device}}{{platform.package}}-{{platform.speedgrade}} + {% for file in platform.extra_files %} + {% if file.endswith((".v", ".sv")) -%} + add_files {{file}} + {% endif %} + {% endfor %} + add_files {{name}}.v + read_xdc {{name}}.xdc + {{get_override("script_after_read")|default("# (script_after_read placeholder)")}} + synth_design -top {{name}} -part {{platform.device}} + {{get_override("script_after_synth")|default("# (script_after_synth placeholder)")}} + report_timing_summary -file {{name}}_timing_synth.rpt + report_utilization -hierarchical -file {{name}}_utilization_hierachical_synth.rpt + report_utilization -file {{name}}_utilization_synth.rpt + opt_design + place_design + {{get_override("script_after_place")|default("# (script_after_place placeholder)")}} + report_utilization -hierarchical -file {{name}}_utilization_hierarchical_place.rpt + report_utilization -file {{name}}_utilization_place.rpt + report_io -file {{name}}_io.rpt + report_control_sets -verbose -file {{name}}_control_sets.rpt + report_clock_utilization -file {{name}}_clock_utilization.rpt + route_design + {{get_override("script_after_route")|default("# (script_after_route placeholder)")}} + phys_opt_design + report_timing_summary -no_header -no_detailed_paths + write_checkpoint -force {{name}}_route.dcp + report_route_status -file {{name}}_route_status.rpt + report_drc -file {{name}}_drc.rpt + report_timing_summary -datasheet -max_paths 10 -file {{name}}_timing.rpt + report_power -file {{name}}_power.rpt + {{get_override("script_before_bitstream")|default("# (script_before_bitstream placeholder)")}} + write_bitstream -force {{name}}.bit + {{get_override("script_after_bitstream")|default("# (script_after_bitstream placeholder)")}} + quit + """, + "{{name}}.xdc": r""" + # {{autogenerated}} + {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%} + set_property LOC {{pin_name}} [get_ports {{port_name}}] + {% for attr_name, attr_value in attrs.items() -%} + set_property {{attr_name}} {{attr_value}} [get_ports {{port_name}}] + {% endfor %} + {% endfor %} + {% for signal, frequency in platform.iter_clock_constraints() -%} + create_clock -name {{signal.name}} -period {{1000000000/frequency}} [get_ports {{signal.name}}] + {{get_override("add_constraints")|default("# (add_constraints placeholder)")}} + {% endfor %} + """ + } + command_templates = [ + r""" + {{get_tool("vivado")}} + {{verbose("-verbose")}} + {{get_override("vivado_opts")|join(" ")}} + -mode batch + -log {{name}}.log + -source {{name}}.tcl + """ + ] + + def _get_dff(self, m, clk, d, q): + # SDR I/O is performed by packing a flip-flop into the pad IOB. + for bit in range(len(q)): + _q = Signal() + _q.attrs["IOB"] = "TRUE" + m.submodules += Instance("FDCE", + i_C=clk, + i_CE=Const(1), + i_CLR=Const(0), + i_D=d[bit], + o_Q=_q, + ) + m.d.comb += q[bit].eq(_q) + + def get_input(self, pin, port, attrs): + self._check_feature("single-ended input", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + self._get_dff(m, pin.i_clk, port, pin.i) + else: + m.d.comb += pin.i.eq(port) + return m + + def get_output(self, pin, port, attrs): + self._check_feature("single-ended output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + self._get_dff(m, pin.o_clk, pin.o, port) + else: + m.d.comb += port.eq(pin.o) + return m + + def get_tristate(self, pin, port, attrs): + self._check_feature("single-ended tristate", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + for bit in range(len(port)): + m.submodules += Instance("OBUFT", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=port[bit] + ) + return m + + def get_input_output(self, pin, port, attrs): + self._check_feature("single-ended input/output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + i_ff = Signal.like(pin.i, name="{}_ff".format(pin.i.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + self._get_dff(m, pin.i_clk, i_ff, pin.i) + for bit in range(len(port)): + m.submodules += Instance("IOBUF", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=i_ff[bit] if pin.xdr == 1 else pin.i[bit], + io_IO=port[bit] + ) + return m + + def get_diff_input(self, pin, p_port, n_port, attrs): + self._check_feature("differential input", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + i_ff = Signal.like(pin.i, name="{}_ff".format(pin.i.name)) + self._get_dff(m, pin.i_clk, i_ff, pin.i) + for bit in range(len(p_port)): + m.submodules += Instance("IBUFDS", + i_I=p_port[bit], + i_IB=n_port[bit], + o_O=i_ff[bit] if pin.xdr == 1 else pin.i[bit] + ) + return m + + def get_diff_output(self, pin, p_port, n_port, attrs): + self._check_feature("differential output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + for bit in range(len(p_port)): + m.submodules += Instance("OBUFDS", + o_O=p_port[bit], + o_OB=n_port[bit], + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit] + ) + return m + + def get_diff_tristate(self, pin, p_port, n_port, attrs): + self._check_feature("differential tristate", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + for bit in range(len(p_port)): + m.submodules += Instance("OBUFTDS", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=p_port[bit], + o_OB=n_port[bit] + ) + return m + + def get_diff_input_output(self, pin, p_port, n_port, attrs): + self._check_feature("differential input/output", pin, attrs, + valid_xdrs=(0, 1), valid_attrs=True) + m = Module() + if pin.xdr == 1: + o_ff = Signal.like(pin.o, name="{}_ff".format(pin.o.name)) + oe_ff = Signal.like(pin.oe, name="{}_ff".format(pin.oe.name)) + i_ff = Signal.like(pin.i, name="{}_ff".format(pin.i.name)) + self._get_dff(m, pin.o_clk, pin.o, o_ff) + self._get_dff(m, pin.o_clk, pin.oe, oe_ff) + self._get_dff(m, pin.i_clk, i_ff, pin.i) + for bit in range(len(p_port)): + m.submodules += Instance("IOBUFDS", + i_T=~(oe_ff if pin.xdr == 1 else pin.oe), + i_I=o_ff[bit] if pin.xdr == 1 else pin.o[bit], + o_O=i_ff[bit] if pin.xdr == 1 else pin.i[bit], + io_IO=p_port[bit], + io_IOB=n_port[bit] + ) + return m -- 2.30.2