From d24d830764078b326dd966a8b000885e545f738e Mon Sep 17 00:00:00 2001 From: Jan Kowalewski Date: Fri, 16 Apr 2021 14:50:32 +0200 Subject: [PATCH] edalize: add fpga_interchange variant to nextpnr flow Signed-off-by: Jan Kowalewski --- edalize/nextpnr.py | 30 ++++++++++++++- edalize/symbiflow.py | 37 +++++++++++++++---- .../nextpnr-fpga_interchange-makefile.j2 | 21 +++++++++++ ...makefile.j2 => nextpnr-xilinx-makefile.j2} | 0 ...iflow-nextpnr-fpga_interchange-makefile.j2 | 26 +++++++++++++ ...2 => symbiflow-nextpnr-xilinx-makefile.j2} | 0 6 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 edalize/templates/nextpnr/nextpnr-fpga_interchange-makefile.j2 rename edalize/templates/nextpnr/{nextpnr-makefile.j2 => nextpnr-xilinx-makefile.j2} (100%) create mode 100644 edalize/templates/symbiflow/symbiflow-nextpnr-fpga_interchange-makefile.j2 rename edalize/templates/symbiflow/{symbiflow-nextpnr-makefile.j2 => symbiflow-nextpnr-xilinx-makefile.j2} (100%) diff --git a/edalize/nextpnr.py b/edalize/nextpnr.py index 5cd051108..e66a10d04 100644 --- a/edalize/nextpnr.py +++ b/edalize/nextpnr.py @@ -7,6 +7,8 @@ class Nextpnr(Edatool): argtypes = [] + archs = ['xilinx', 'fpga_interchange'] + families = ['xc7'] @classmethod def get_doc(cls, api_ver): @@ -95,10 +97,13 @@ def configure_main(self): file_table = [] output_format = self.tool_options.get('output_format', 'fasm') - arch = self.tool_options.get('arch', 'xilinx') + arch = self.tool_options.get('arch') + + assert arch in getattr(self, 'archs'), 'Missing or invalid "arch" parameter in "tool_options"' synth_design = None chipdb = None + device = None xdc = None for f in src_files: @@ -106,26 +111,47 @@ def configure_main(self): synth_design = f.name elif f.file_type in ['bba']: chipdb = f.name + elif f.file_type in ['device']: + device = f.name elif f.file_type in ['xdc']: xdc = f.name else: continue assert chipdb and xdc, "Missing required files." + assert device is not None or arch is not 'fpga_interchange', 'Missing required ".device" file for "fpga_interchange" arch' additional_options = self.tool_options.get('nextpnr_impl_options', '') + package = self.tool_options.get('package', None) + + assert package is not None or arch is not 'fpga_interchange', 'Missing required "package" parameter for "fpga_interchange" arch' + + package = package.split('-')[0] if arch == "fpga_interchange" else None + + family = self.tool_options.get('family', None) + + assert family is not None or arch is not 'fpga_interchange', 'Missing required "family" parameter for "fpga_interchange" arch' + assert family in getattr(self, 'families') or arch is not 'fpga_interchange', 'Unsupported family: {}'.format(family) + + schema_dir = self.tool_options.get('schema_dir', None) + assert schema_dir is not None or arch is not 'fpga_interchange', 'Missing required "schema_dir" parameter for "fpga_interchange" arch' template_vars = { + 'toplevel' : self.toplevel, 'arch' : arch, 'chipdb' : chipdb, + 'device' : device, 'constr' : xdc, 'default_target' : output_format, 'name' : self.name, + 'package' : package, + 'family' : family, + 'schema_dir' : schema_dir, 'additional_options': additional_options, } makefile_name = self.name + '-nextpnr.mk' if part_of_toolchain else 'Makefile' - self.render_template('nextpnr-makefile.j2', + self.render_template('nextpnr-{}-makefile.j2'.format(arch), makefile_name, template_vars) diff --git a/edalize/symbiflow.py b/edalize/symbiflow.py index 18dcc732a..0bc76aeac 100644 --- a/edalize/symbiflow.py +++ b/edalize/symbiflow.py @@ -23,6 +23,8 @@ class Symbiflow(Edatool): argtypes = ['vlogdefine', 'vlogparam', 'generic'] + archs = ['xilinx', 'fpga_interchange'] + families = ['xc7'] @classmethod def get_doc(cls, api_ver): @@ -78,16 +80,41 @@ def configure_nextpnr(self): yosys_synth_options = self.tool_options.get('yosys_synth_options', '') yosys_additional_commands = self.tool_options.get('yosys_additional_commands', '') nextpnr_impl_options = self.tool_options.get('options', '') + arch = self.tool_options.get('arch') + + assert arch in getattr(self, 'archs'), 'Missing or invalid "arch" parameter: {} in "tool_options"'.format(arch) + + package = self.tool_options.get('package', None) + assert package is not None, 'Missing required "package" parameter' + + schema_dir = self.tool_options.get('schema_dir', None) + assert schema_dir is not None or arch is not 'fpga_interchange', 'Missing required "schema_dir" parameter for "fpga_interchange" arch' + + part = self.tool_options.get('part', None) + + assert part is not None, 'Missing required "part" parameter' + + target_family = None + for family in getattr(self, 'families'): + if family in part: + target_family = family + break + + assert target_family is not None or arch is not "fpga_interchange", "Couldn't find family for part: {}. Available families: {}".format(part, ", ".join(getattr(self, 'families'))) + nextpnr_edam = { 'files' : self.files, 'name' : self.name, 'toplevel' : self.toplevel, 'tool_options' : {'nextpnr' : { - 'arch' : 'xilinx', + 'arch' : arch, 'yosys_synth_options' : yosys_synth_options, 'yosys_additional_commands' : yosys_additional_commands, 'nextpnr_impl_options' : nextpnr_impl_options, 'nextpnr_as_subtool' : True, + 'package' : package, + 'family' : target_family, + 'schema_dir' : schema_dir, } } @@ -98,12 +125,6 @@ def configure_nextpnr(self): builddir = self.tool_options.get('builddir', 'build') - part = self.tool_options.get('part', None) - package = self.tool_options.get('package', None) - - assert part is not None, 'Missing required "part" parameter' - assert package is not None, 'Missing required "package" parameter' - partname = part + package if 'xc7a' in part: @@ -174,7 +195,7 @@ def configure_nextpnr(self): 'environment_script': environment_script, } - self.render_template('symbiflow-nextpnr-makefile.j2', + self.render_template('symbiflow-nextpnr-{}-makefile.j2'.format(arch), 'Makefile', makefile_params) diff --git a/edalize/templates/nextpnr/nextpnr-fpga_interchange-makefile.j2 b/edalize/templates/nextpnr/nextpnr-fpga_interchange-makefile.j2 new file mode 100644 index 000000000..5ce0396fb --- /dev/null +++ b/edalize/templates/nextpnr/nextpnr-fpga_interchange-makefile.j2 @@ -0,0 +1,21 @@ +#Auto generated by Edalize + +TARGET := {{ name }} + +all: $(TARGET).{{ default_target }} + +{{ name }}.json: {{ name }}.mk + $(MAKE) -f $< + +{{ name }}.netlist: {{ name }}.json + python -m fpga_interchange.yosys_json --schema_dir {{ schema_dir }} --device {{ device }} --top {{ toplevel }} {{ name }}.json {{ name }}.netlist + +{{ name }}.phys: {{ name }}.netlist + nextpnr-{{ arch }} --chipdb {{ chipdb }} --package {{ package }} --xdc {{ constr }} --netlist {{ name }}.netlist --write {{ name }}.routed.json --phys {{ name }}.phys {{ additional_options }} + +{{ name }}.fasm: {{ name }}.phys + python -m fpga_interchange.fasm_generator --schema_dir {{ schema_dir }} --family {{ family }} {{ device }} {{ name }}.netlist {{ name }}.phys {{ name }}.fasm + + +clean: + rm -f $(TARGET).json $(TARGET).routed.json $(TARGET).netlist $(TARGET).phys $(TARGET).fasm diff --git a/edalize/templates/nextpnr/nextpnr-makefile.j2 b/edalize/templates/nextpnr/nextpnr-xilinx-makefile.j2 similarity index 100% rename from edalize/templates/nextpnr/nextpnr-makefile.j2 rename to edalize/templates/nextpnr/nextpnr-xilinx-makefile.j2 diff --git a/edalize/templates/symbiflow/symbiflow-nextpnr-fpga_interchange-makefile.j2 b/edalize/templates/symbiflow/symbiflow-nextpnr-fpga_interchange-makefile.j2 new file mode 100644 index 000000000..c9fb88f6b --- /dev/null +++ b/edalize/templates/symbiflow/symbiflow-nextpnr-fpga_interchange-makefile.j2 @@ -0,0 +1,26 @@ +#Auto generated by Edalize +SHELL = bash + +NAME := {{ top }} +PARTNAME:= {{ partname }} +BITSTREAM_DEVICE := {{ bitstream_device }} +BUILDDIR:= {{ builddir }} + +all: ${NAME}.bit + +{% if environment_script -%} +SOURCE_OPTS = source {{ environment_script }} && +{%- endif %} + +${BUILDDIR}: + mkdir ${BUILDDIR} + +${NAME}.fasm: ${NAME}-nextpnr.mk | ${BUILDDIR} + ${SOURCE_OPTS} $(MAKE) -f ${NAME}-nextpnr.mk + +${NAME}.bit: ${NAME}.fasm + ${SOURCE_OPTS} cd ${BUILDDIR} && symbiflow_write_bitstream -d ${BITSTREAM_DEVICE} -f ${NAME}.fasm -p ${PARTNAME} -b ${NAME}.bit + +clean: + rm -rf ${BUILDDIR} + diff --git a/edalize/templates/symbiflow/symbiflow-nextpnr-makefile.j2 b/edalize/templates/symbiflow/symbiflow-nextpnr-xilinx-makefile.j2 similarity index 100% rename from edalize/templates/symbiflow/symbiflow-nextpnr-makefile.j2 rename to edalize/templates/symbiflow/symbiflow-nextpnr-xilinx-makefile.j2