f4pga enable new eos-s3 flow (#577)

This commit is contained in:
Unai Martinez-Corral 2022-08-01 14:14:30 +02:00 committed by GitHub
commit c342fc6ff1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 569 additions and 84 deletions

View File

@ -1 +1,26 @@
{}
{
"default_part": "EOS3FF512-PDN64",
"values": {
"top": "top"
},
"dependencies": {
"sources": [
"eos-s3/btn_counter/btn_counter.v"
],
"synth_log": "synth.log",
"pack_log": "pack.log",
"analysis_log": "analysis.log"
},
"EOS3FF512-PDN64": {
"default_target": "bitstream",
"dependencies": {
"build_dir": "build/eos-s3",
"pcf": "eos-s3/btn_counter/chandalar.pcf",
"sdc-in": "eos-s3/btn_counter/dummy.sdc"
},
"values": {
"part": "ql-eos-s3",
"package": "PD64"
}
}
}

View File

@ -115,26 +115,15 @@ jobs:
if: matrix.flow == 'F4PGA'
run: |
. ./.github/scripts/activate.sh
cd f4pga-examples
f4pga build --flow ../.github/${{ matrix.fam }}_test.json
# FIXME
# Temporarily allow QL example to fail, until https://github.com/chipsalliance/f4pga/pull/577 is merged.
case '${{ matrix.fam }}' in
eos-s3)
f4pga build --flow ../.github/${{ matrix.fam }}_test.json | echo 'See #577'
;;
*)
f4pga build --flow ../.github/${{ matrix.fam }}_test.json
;;
esac
- name: '📤 Upload artifact: Arty 35 bitstream'
if: matrix.flow == 'F4PGA' && matrix.fam == 'xc7'
- name: '📤 Upload artifact: ${{ matrix.fam }} bitstream'
if: matrix.flow == 'F4PGA'
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.flow }}-arty_35-Bitstream-pyF4PGA
path: f4pga-examples/build/arty_35/top.bit
name: ${{ matrix.flow }}-${{ matrix.fam }}-Bitstream
path: f4pga-examples/build/${{ matrix.fam }}/top.bit
if-no-files-found: error
# SymbiFlow
@ -163,19 +152,19 @@ jobs:
esac
- name: '📤 Upload artifact: Arty 35 bitstream'
if: matrix.flow == 'SymbiFLow' && matrix.fam == 'xc7'
if: matrix.flow == 'SymbiFlow' && matrix.fam == 'xc7'
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.flow }}-arty_35-Bitstream
path: f4pga-examples/xc7/counter_test/build/arty_35/top.bit
name: ${{ matrix.flow }}-${{ matrix.fam }}-Bitstream
path: f4pga-examples/${{ matrix.fam }}/counter_test/build/arty_35/top.bit
if-no-files-found: error
- name: '📤 Upload artifact: QuickLogic bitstream'
if: matrix.flow == 'SymbiFLow' && matrix.fam == 'eos-s3'
if: matrix.flow == 'SymbiFlow' && matrix.fam == 'eos-s3'
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.flow }}-eos-s3-Bitstream
path: f4pga-examples/eos-s3/btn_counter/build/top.bit
name: ${{ matrix.flow }}-${{ matrix.fam }}-Bitstream
path: f4pga-examples/${{ matrix.fam }}/btn_counter/build/top.bit
if-no-files-found: error
@ -225,4 +214,4 @@ jobs:
- name: 🚧 Test pyF4PGA (PYTHONPATH)
run: |
PYTHONPATH=$(pwd) python3 f4pga/__init__.py
PYTHONPATH=$(pwd) python3 f4pga/__init__.py -h
PYTHONPATH=$(pwd) python3 f4pga/__init__.py -h

View File

@ -13,7 +13,7 @@
"XC7A35TCSG324-1": {
"default_target": "bitstream",
"dependencies": {
"build_dir": "build/arty_35",
"build_dir": "build/xc7",
"xdc": [
"xc7/counter_test/arty.xdc"
]

View File

@ -74,14 +74,13 @@ install_dir = environ.get("F4PGA_INSTALL_DIR", "/usr/local")
mypath = str(Path(__file__).resolve().parent)
FPGA_FAM = environ.get('FPGA_FAM', 'xc7')
bin_dir_path = \
environ.get('F4PGA_BIN_DIR', str(Path(sys_argv[0]).resolve().parent.parent))
share_dir_path = \
environ.get('F4PGA_SHARE_DIR',
str(Path(f'{install_dir}/xc7/install/share/f4pga').resolve()))
if share_dir_path is None:
share_dir_path = str(Path(f'{install_dir}/xc7/install/share/f4pga').resolve())
str(Path(f'{install_dir}/{FPGA_FAM}/install/share/f4pga').resolve()))
class DependencyNotProducedException(F4PGAException):
dep_name: str
@ -532,11 +531,14 @@ def setup_resolution_env():
"""
Generate initial values, available in configs.
"""
return {
'prjxray_db': common_sub('prjxray-config').decode().replace('\n', ''),
conf = {
'python3': common_sub('which', 'python3').decode().replace('\n', ''),
'noisyWarnings': _noisy_warnings()
}
if (FPGA_FAM == 'xc7'):
conf['prjxray_db'] = common_sub('prjxray-config').decode().replace('\n', '')
return conf
r_env.add_values(_generate_values())
return r_env

View File

@ -174,6 +174,8 @@ def vpr(mode: str, vprargs: VprArgs, cwd=None):
modeargs = ['--place']
elif mode == 'route':
modeargs = ['--route']
elif mode == 'analysis':
modeargs = ['--analysis']
return sub(*([
'vpr',

View File

@ -0,0 +1,88 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2022 F4PGA Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
from pathlib import Path
from shutil import move as sh_mv
from f4pga.common import *
from f4pga.module import Module, ModuleContext
def analysis_merged_post_implementation_file(ctx: ModuleContext):
return str(Path(ctx.takes.eblif).with_suffix('')) + '_merged_post_implementation.v'
def analysis_post_implementation_file(ctx: ModuleContext):
return str(Path(ctx.takes.eblif).with_suffix('')) + '_post_synthesis.v'
class analysisModule(Module):
def map_io(self, ctx: ModuleContext):
return {
'merged_post_implementation_v': analysis_merged_post_implementation_file(ctx),
'post_implementation_v': analysis_post_implementation_file(ctx)
}
def execute(self, ctx: ModuleContext):
build_dir = str(Path(ctx.takes.eblif).parent)
vpr_options = []
if ctx.values.vpr_options:
vpr_options = options_dict_to_list(ctx.values.vpr_options)
yield 'Analysis with VPR...'
vpr(
'analysis',
VprArgs(
ctx.share,
ctx.takes.eblif,
ctx.values,
sdc_file=ctx.takes.sdc
),
cwd=build_dir
)
if ctx.is_output_explicit('merged_post_implementation_v'):
sh_mv(analysis_merged_post_implementation_file(ctx), ctx.outputs.merged_post_implementation_v)
if ctx.is_output_explicit('post_implementation_v'):
sh_mv(analysis_post_implementation_file(ctx), ctx.outputs.post_implementation_v)
yield 'Saving log...'
save_vpr_log('analysis.log', build_dir=build_dir)
def __init__(self, _):
self.name = 'analysis'
self.no_of_phases = 2
self.takes = [
'eblif',
'route',
'sdc?'
]
self.produces = [
'merged_post_implementation_v',
'post_implementation_v',
'analysis_log'
]
self.values = [
'device',
'vpr_options?'
] + vpr_specific_values()
ModuleClass = analysisModule

View File

@ -18,6 +18,7 @@
# SPDX-License-Identifier: Apache-2.0
import os
from pathlib import Path
from f4pga.common import *
from f4pga.module import Module, ModuleContext
@ -97,23 +98,22 @@ class SynthModule(Module):
return mapping
def execute(self, ctx: ModuleContext):
split_inouts = os.path.join(ctx.share, 'scripts/split_inouts.py')
synth_tcl = os.path.join(ctx.values.tcl_scripts, 'synth.tcl')
conv_tcl = os.path.join(ctx.values.tcl_scripts, 'conv.tcl')
tcl_env = yosys_setup_tcl_env(ctx.values.yosys_tcl_env) \
if ctx.values.yosys_tcl_env else {}
split_inouts = Path(tcl_env["UTILS_PATH"]) / 'split_inouts.py'
synth_tcl = Path(ctx.values.tcl_scripts) / 'synth.tcl'
conv_tcl = Path(ctx.values.tcl_scripts) / 'conv.tcl'
if get_verbosity_level() >= 2:
yield f'Synthesizing sources: {ctx.takes.sources}...'
else:
yield f'Synthesizing sources...'
yosys_synth(synth_tcl, tcl_env, ctx.takes.sources,
yosys_synth(str(synth_tcl), tcl_env, ctx.takes.sources,
ctx.values.read_verilog_args, ctx.outputs.synth_log)
yield f'Splitting in/outs...'
sub('python3', split_inouts, '-i', ctx.outputs.json, '-o',
sub('python3', str(split_inouts), '-i', ctx.outputs.json, '-o',
ctx.outputs.synth_json)
if not os.path.isfile(ctx.produces.fasm_extra):
@ -121,7 +121,7 @@ class SynthModule(Module):
f.write('')
yield f'Converting...'
yosys_conv(conv_tcl, tcl_env, ctx.outputs.synth_json)
yosys_conv(str(conv_tcl), tcl_env, ctx.outputs.synth_json)
def __init__(self, params):
self.name = 'synthesize'

View File

@ -2,18 +2,29 @@
"stages": {
"mk_build_dir": "common:mkdirs",
"synth": "common:synth",
"prepare_sdc": "common:generic_script_wrapper",
"pack": "common:pack",
"ioplace": "common:generic_script_wrapper",
"place_constraints": "common:generic_script_wrapper",
"iomux_jlink": "common:generic_script_wrapper",
"iomux_openocd": "common:generic_script_wrapper",
"iomux_binary": "common:generic_script_wrapper",
"place": "common:place",
"route": "common:route",
"analysis": "common:analysis",
"fasm": "common:fasm",
"bitstream": "common:generic_script_wrapper"
"bitstream": "common:generic_script_wrapper",
"bitstream_bitheader": "common:generic_script_wrapper",
"bitstream_binary": "common:generic_script_wrapper",
"bitstream_jlink": "common:generic_script_wrapper",
"bitstream_openocd": "common:generic_script_wrapper",
"fasm2bels": "common:generic_script_wrapper"
},
"values": {
"device": "ql-eos-s3",
"device_alt": "ql-eos-s3_wlcsp",
"pinmap": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_PD64.csv",
"pinmap": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"arch_def": "${shareDir}/arch/ql-eos-s3_wlcsp/arch.timing.xml",
"rr_graph_lookahead_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.lookahead.bin",
"rr_graph_real_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.rr_graph.real.bin",
@ -52,7 +63,9 @@
"synth": {
"params": {
"takes": [ "pcf?" ],
"produces": [ "synth_v" ]
"produces": [
"synth_v"
]
},
"values": {
"tcl_scripts": "${shareDir}/scripts/pp3",
@ -65,8 +78,67 @@
"TECHMAP_PATH": "${shareDir}/techmaps/pp3",
"DEVICE_CELLS_SIM": "${shareDir}/arch/ql-eos-s3_wlcsp/cells/ram_sim.v",
"DEVICE_CELLS_MAP": "${shareDir}/arch/ql-eos-s3_wlcsp/cells/ram_map.v",
"PINMAP_FILE": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_PD64.csv",
"PCF_FILE": "${:pcf}"
"PINMAP_FILE": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"PCF_FILE": "${:pcf}",
"PYTHON3": "${python3}",
"UTILS_PATH": "${shareDir}/scripts"
}
}
},
"prepare_sdc": {
"params": {
"stage_name": "prepare_sdc",
"interpreter": "${python3}",
"script": "${shareDir}/scripts/process_sdc_constraints.py",
"outputs": {
"sdc": {
"mode": "file",
"file": "${:eblif[noext]}.sdc",
"target": "${:eblif[noext]}.sdc"
}
},
"inputs": {
"eblif": "${:eblif}",
"sdc-in": "${:sdc-in}",
"sdc-out": "${:eblif[noext]}.sdc",
"pcf": "${:pcf}",
"pin-map": "",
"$PYTHONPATH": "${shareDir}/scripts/"
}
}
},
"pack": {
"values": {
"device": "ql-eos-s3",
"device_alt": "ql-eos-s3_wlcsp",
"pinmap": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"arch_def": "${shareDir}/arch/ql-eos-s3_wlcsp/arch.timing.xml",
"rr_graph_lookahead_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.lookahead.bin",
"rr_graph_real_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.rr_graph.real.bin",
"vpr_place_delay": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.place_delay.bin",
"vpr_grid_layout_name": "ql-eos-s3",
"vpr_options": {
"write_block_usage": "block_usage.json",
"max_router_iterations": 500,
"routing_failure_predictor": "off",
"router_high_fanout_threshold": -1,
"constant_net_method": "route",
"route_chan_width": 100,
"clock_modeling": "route",
"place_delay_model": "delta_override",
"router_lookahead": "extended_map",
"check_route": "quick",
"strict_checks": "off",
"allow_dangling_combinational_nodes": "on",
"disable_errors": "check_unbuffered_edges:check_route",
"congested_routing_iteration_threshold": "0.8",
"incremental_reroute_delay_ripup": "off",
"base_cost_type": "delay_normalized_length_bounded",
"bb_factor": "10",
"initial_pres_fac": "4.0",
"check_rr_graph": "off",
"pack_high_fanout_threshold": "PB-lOGIC:18",
"suppress_warnings": "${noisyWarnings},sum_pin_class:check_unbuffered_edges:load_rr_indexed_data_T_values:check_rr_node:trans_per_R:check_route:set_rr_graph_tool_comment "
}
}
},
@ -74,7 +146,7 @@
"params": {
"stage_name": "ioplace",
"interpreter": "${python3}",
"script": "${binDir}/python/ql_pp3_create_ioplace.py",
"script": "${shareDir}/scripts/pp3_create_ioplace.py",
"outputs": {
"io_place": {
"mode": "stdout",
@ -85,8 +157,161 @@
"blif": "${:eblif}",
"net": "${:net}",
"pcf": "${:pcf}",
"map": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_PD64.csv",
"$PYTHONPATH": "${binDir}/python/"
"map": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"$PYTHONPATH": "${shareDir}/scripts/"
}
}
},
"place_constraints": {
"params": {
"stage_name": "place_constraints",
"interpreter": "${python3}",
"script": "${shareDir}/scripts/pp3_create_place_constraints.py",
"outputs": {
"place_constraints": {
"mode": "stdout",
"target": "${:eblif[noext]}_constraints.place"
}
},
"inputs": {
"blif": "${:eblif}",
"map": "${shareDir}/arch/ql-eos-s3_wlcsp/clkmap_${package}.csv",
"i": "${:io_place}",
"$PYTHONPATH": "${shareDir}/scripts/"
}
}
},
"iomux_jlink": {
"params": {
"stage_name": "iomux_jlink",
"interpreter": "${python3}",
"script": "${shareDir}/scripts/pp3_eos_s3_iomux_config.py",
"outputs": {
"iomux_jlink": {
"mode": "stdout",
"target": "${:eblif[noext]}_iomux.jlink"
}
},
"inputs": {
"eblif": "${:eblif}",
"pcf": "${:pcf}",
"map": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"output-format": "jlink",
"$PYTHONPATH": "${shareDir}/scripts/"
}
}
},
"iomux_openocd": {
"params": {
"stage_name": "iomux_openocd",
"interpreter": "${python3}",
"script": "${shareDir}/scripts/pp3_eos_s3_iomux_config.py",
"outputs": {
"iomux_openocd": {
"mode": "stdout",
"target": "${:eblif[noext]}_iomux.openocd"
}
},
"inputs": {
"eblif": "${:eblif}",
"pcf": "${:pcf}",
"map": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"output-format": "openocd",
"$PYTHONPATH": "${shareDir}/scripts/"
}
}
},
"iomux_binary": {
"params": {
"stage_name": "iomux_binary",
"interpreter": "${python3}",
"script": "${shareDir}/scripts/pp3_eos_s3_iomux_config.py",
"outputs": {
"iomux_binary": {
"mode": "stdout",
"target": "${:eblif[noext]}_iomux.bin"
}
},
"inputs": {
"eblif": "${:eblif}",
"pcf": "${:pcf}",
"map": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"output-format": "binary",
"$PYTHONPATH": "${shareDir}/scripts/"
}
}
},
"route": {
"values": {
"device": "ql-eos-s3",
"device_alt": "ql-eos-s3_wlcsp",
"pinmap": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"arch_def": "${shareDir}/arch/ql-eos-s3_wlcsp/arch.timing.xml",
"rr_graph_lookahead_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.lookahead.bin",
"rr_graph_real_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.rr_graph.real.bin",
"vpr_place_delay": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.place_delay.bin",
"vpr_grid_layout_name": "ql-eos-s3",
"vpr_options": {
"write_timing_summary": "timing_summary.json",
"max_router_iterations": 500,
"routing_failure_predictor": "off",
"router_high_fanout_threshold": -1,
"constant_net_method": "route",
"route_chan_width": 100,
"clock_modeling": "route",
"place_delay_model": "delta_override",
"router_lookahead": "extended_map",
"check_route": "quick",
"strict_checks": "off",
"allow_dangling_combinational_nodes": "on",
"disable_errors": "check_unbuffered_edges:check_route",
"congested_routing_iteration_threshold": "0.8",
"incremental_reroute_delay_ripup": "off",
"base_cost_type": "delay_normalized_length_bounded",
"bb_factor": "10",
"initial_pres_fac": "4.0",
"check_rr_graph": "off",
"pack_high_fanout_threshold": "PB-lOGIC:18",
"suppress_warnings": "${noisyWarnings},sum_pin_class:check_unbuffered_edges:load_rr_indexed_data_T_values:check_rr_node:trans_per_R:check_route:set_rr_graph_tool_comment "
}
}
},
"analysis": {
"values": {
"device": "ql-eos-s3",
"device_alt": "ql-eos-s3_wlcsp",
"pinmap": "${shareDir}/arch/ql-eos-s3_wlcsp/pinmap_${package}.csv",
"arch_def": "${shareDir}/arch/ql-eos-s3_wlcsp/arch.timing.xml",
"rr_graph_lookahead_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.lookahead.bin",
"rr_graph_real_bin": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.rr_graph.real.bin",
"vpr_place_delay": "${shareDir}/arch/ql-eos-s3_wlcsp/rr_graph_ql-eos-s3_wlcsp.place_delay.bin",
"vpr_grid_layout_name": "ql-eos-s3",
"vpr_options": {
"gen_post_synthesis_netlist": "on",
"gen_post_implementation_merged_netlist": "on",
"post_synth_netlist_unconn_inputs": "nets",
"post_synth_netlist_unconn_outputs": "nets",
"verify_file_digests": "off",
"max_router_iterations": 500,
"routing_failure_predictor": "off",
"router_high_fanout_threshold": -1,
"constant_net_method": "route",
"route_chan_width": 100,
"clock_modeling": "route",
"place_delay_model": "delta_override",
"router_lookahead": "extended_map",
"check_route": "quick",
"strict_checks": "off",
"allow_dangling_combinational_nodes": "on",
"disable_errors": "check_unbuffered_edges:check_route",
"congested_routing_iteration_threshold": "0.8",
"incremental_reroute_delay_ripup": "off",
"base_cost_type": "delay_normalized_length_bounded",
"bb_factor": "10",
"initial_pres_fac": "4.0",
"check_rr_graph": "off",
"pack_high_fanout_threshold": "PB-lOGIC:18",
"suppress_warnings": "${noisyWarnings},sum_pin_class:check_unbuffered_edges:load_rr_indexed_data_T_values:check_rr_node:trans_per_R:check_route:set_rr_graph_tool_comment "
}
}
},
@ -97,24 +322,152 @@
"outputs": {
"bitstream": {
"mode": "file",
"file": "bitstream-${device}.bit",
"target": "${build_dir?}/bitstream-${device}.bit"
"file": "${:eblif[noext]}.bit",
"target": "${:eblif[noext]}.bit"
},
"bitstream_log": {
"mode": "stdout",
"target": "${build_dir?}/bitstream-${device}.log"
"target": "${:eblif[noext]}.bit.log"
}
},
"inputs": {
"#1": "${:fasm}",
"#2": "bitstream-${device}.bit",
"dev-type": "ql-eos-s3",
"db-root": "${shareDir}/fasm_database/pp3"
"#2": "${:eblif[noext]}.bit",
"dev-type": "ql-eos-s3"
}
},
"values": {
"build_dir?": "."
"build_dir": "."
}
},
"bitstream_bitheader": {
"params": {
"stage_name": "bitstream_bitheader",
"script": "symbiflow_write_bitheader",
"outputs": {
"bitstream_bitheader": {
"mode": "file",
"file": "${:bitstream}.h",
"target": "${:bitstream}.h"
},
"bitstream_bitheader_log": {
"mode": "stdout",
"target": "${:bitstream}.h.log"
}
},
"inputs": {
"#1": "${:bitstream}",
"#2": "${:bitstream}.h",
"#3": "${:iomux_binary}"
}
}
},
"bitstream_jlink": {
"params": {
"stage_name": "bitstream_jlink",
"script": "symbiflow_write_jlink",
"outputs": {
"bitstream_jlink": {
"mode": "file",
"file": "${:bitstream}.jlink",
"target": "${:bitstream}.jlink"
},
"bitstream_jlink_log": {
"mode": "stdout",
"target": "${:bitstream}.jlink.log"
}
},
"inputs": {
"#1": "${:bitstream}",
"#2": "${:bitstream}.jlink",
"#3": "${:iomux_jlink}"
}
}
},
"bitstream_openocd": {
"params": {
"stage_name": "bitstream_openocd",
"script": "symbiflow_write_openocd",
"outputs": {
"bitstream_openocd": {
"mode": "file",
"file": "${:bitstream}.openocd",
"target": "${:bitstream}.openocd"
},
"bitstream_openocd_log": {
"mode": "stdout",
"target": "${:bitstream}.openocd.log"
}
},
"inputs": {
"#1": "${:bitstream}",
"#2": "${:bitstream}.openocd",
"#3": "${:iomux_openocd}"
}
}
},
"bitstream_binary": {
"params": {
"stage_name": "bitstream_binary",
"script": "symbiflow_write_binary",
"outputs": {
"bitstream_binary": {
"mode": "file",
"file": "${:bitstream}.bin",
"target": "${:bitstream}.bin"
},
"bitstream_binary_log": {
"mode": "stdout",
"target": "${:bitstream}.bin.log"
}
},
"inputs": {
"#1": "${:bitstream}",
"#2": "${:bitstream}.bin",
"#3": "${:iomux_binary}"
}
}
},
"fasm2bels": {
"params": {
"stage_name": "fasm2bels",
"script": "symbiflow_fasm2bels",
"outputs": {
"fasm2bels_verilog": {
"mode": "file",
"file": "${:bitstream}.v",
"target": "${:bitstream}.v"
},
"fasm2bels_pcf": {
"mode": "file",
"file": "${:bitstream}.pcf",
"target": "${:bitstream}.pcf"
},
"fasm2bels_qcf": {
"mode": "file",
"file": "${:bitstream}.qcf",
"target": "${:bitstream}.qcf"
},
"fasm2bels_log": {
"mode": "stdout",
"target": "${:bitstream}.log"
}
},
"inputs": {
"device": "${device}",
"part": "${package}",
"pcf": "${:pcf}",
"bit": "${:bitstream}",
"out-verilog": "${:bitstream}.v",
"out-pcf": "${:bitstream}.pcf",
"out-qcf": "${:bitstream}.qcf",
"$F4PGA_INSTALL_DIR": "${shareDir}/../../../../",
"$FPGA_FAM": "eos-s3",
"$PATH": "${shareDir}/../../../conda/envs/eos-s3/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"$SHARE_DIR_PATH": "${shareDir}",
"$BIN_DIR_PATH": "${binDir}"
}
}
}
}
}
}

View File

@ -72,6 +72,10 @@ wrapper_entrypoints = [
f"{sf}_generate_constraints = {shwrappers}:generate_constraints",
f"{sf}_analysis = {shwrappers}:analysis",
f"{sf}_fasm2bels = {shwrappers}:fasm2bels",
f"{sf}_write_binary = {shwrappers}:write_binary",
f"{sf}_write_bitheader = {shwrappers}:write_bitheader",
f"{sf}_write_jlink = {shwrappers}:write_jlink",
f"{sf}_write_openocd = {shwrappers}:write_openocd",
f"ql_{sf} = {shwrappers}:ql",
f"vpr_common = {shwrappers}:vpr_common",
]

View File

@ -120,3 +120,19 @@ def ql():
def fasm2bels():
print("[F4PGA] Running (deprecated) fasm2bels")
run_sh(ROOT / "quicklogic/fasm2bels.f4pga.sh")
def write_bitheader():
print("[F4PGA] Running (deprecated) write bitheader")
run_sh(ROOT / "quicklogic/write_bitheader.f4pga.sh")
def write_binary():
print("[F4PGA] Running (deprecated) write binary")
run_sh(ROOT / "quicklogic/write_binary.f4pga.sh")
def write_jlink():
print("[F4PGA] Running (deprecated) write jlink")
run_sh(ROOT / "quicklogic/write_jlink.f4pga.sh")
def write_openocd():
print("[F4PGA] Running (deprecated) write openocd")
run_sh(ROOT / "quicklogic/write_openocd.f4pga.sh")

View File

@ -21,8 +21,8 @@ set -e
SHARE_DIR_PATH=${SHARE_DIR_PATH:="$F4PGA_SHARE_DIR"}
BIN_DIR_PATH=${BIN_DIR_PATH:="$F4PGA_BIN_DIR"}
OPTS=d:P:p:b:
LONGOPTS=device:,part:,pcf:,bit:,
OPTS=d:P:p:b:v:o:q
LONGOPTS=device:,part:,pcf:,bit:,out-verilog:,out-pcf:,out-qcf:,
PARSED_OPTS=`getopt --options=${OPTS} --longoptions=${LONGOPTS} --name $0 -- "$@"`
eval set -- "${PARSED_OPTS}"
@ -31,6 +31,9 @@ DEVICE=""
PART=""
PCF=""
BIT=""
OUT_VERILOG=""
OUT_PCF=""
OUT_QCF=""
while true; do
case "$1" in
@ -50,6 +53,18 @@ while true; do
BIT=$2
shift 2
;;
-v|--out-verilog)
OUT_VERILOG=$2
shift 2
;;
-o|--out-pcf)
OUT_PCF=$2
shift 2
;;
-q|--out-qcf)
OUT_QCF=$2
shift 2
;;
--)
break
;;
@ -67,27 +82,26 @@ if [ -z $BIT ]; then
fi
# Run fasm2bels
if [[ "$DEVICE" =~ ^(ql-eos-s3|ql-pp3e)$ ]]; then
VPR_DB=`readlink -f ${SHARE_DIR_PATH}/arch/${DEVICE}_wlcsp/db_phy.pickle`
FASM2BELS=`readlink -f ${SHARE_DIR_PATH}/scripts/fasm2bels.py`
FASM2BELS_DEVICE=${DEVICE/ql-/}
VERILOG_FILE="${BIT}.v"
PCF_FILE="${BIT}.v.pcf"
QCF_FILE="${BIT}.v.qcf"
if [ ! -z "{PCF}" ]; then
PCF_ARGS="--input-pcf ${PCF}"
else
PCF_ARGS=""
fi
echo "Running fasm2bels"
`which python3` ${FASM2BELS} ${BIT} --phy-db ${VPR_DB} --device-name ${FASM2BELS_DEVICE} --package-name ${PART} --input-type bitstream --output-verilog ${VERILOG_FILE} ${PCF_ARGS} --output-pcf ${PCF_FILE} --output-qcf ${QCF_FILE}
else
# $DEVICE is not ql-eos-s3 or ql-pp3e
if ! [[ "$DEVICE" =~ ^(ql-eos-s3|ql-pp3e)$ ]]; then
echo "ERROR: Unsupported device '${DEVICE}' for fasm2bels"
exit -1
fi
# Run fasm2bels
VPR_DB=`readlink -f ${SHARE_DIR_PATH}/arch/${DEVICE}_wlcsp/db_phy.pickle`
FASM2BELS=`readlink -f ${SHARE_DIR_PATH}/scripts/fasm2bels.py`
FASM2BELS_DEVICE=${DEVICE/ql-/}
VERILOG_FILE="${OUT_VERILOG:-$BIT.v}"
PCF_FILE="${OUT_PCF:-$BIT.v.pcf}"
QCF_FILE="${OUT_QCF:-$BIT.v.qcf}"
if [ ! -z "{PCF}" ]; then
PCF_ARGS="--input-pcf ${PCF}"
else
PCF_ARGS=""
fi
echo "Running fasm2bels"
`which python3` ${FASM2BELS} ${BIT} --phy-db ${VPR_DB} --device-name ${FASM2BELS_DEVICE} --package-name ${PART} --input-type bitstream --output-verilog ${VERILOG_FILE} ${PCF_ARGS} --output-pcf ${PCF_FILE} --output-qcf ${QCF_FILE}

2
f4pga/wrappers/sh/quicklogic/write_binary.f4pga.sh Normal file → Executable file
View File

@ -18,7 +18,5 @@
set -e
source $(dirname "$(readlink -f "$BASH_SOURCE")")/env
echo "Converting bitstream to flashable binary format"
`which python3` -m quicklogic_fasm.bitstream_to_binary $@

2
f4pga/wrappers/sh/quicklogic/write_bitheader.f4pga.sh Normal file → Executable file
View File

@ -18,7 +18,5 @@
set -e
source $(dirname "$(readlink -f "$BASH_SOURCE")")/env
echo "Converting bitstream to C Header"
`which python3` -m quicklogic_fasm.bitstream_to_header $@

2
f4pga/wrappers/sh/quicklogic/write_jlink.f4pga.sh Normal file → Executable file
View File

@ -18,7 +18,5 @@
set -e
source $(dirname "$(readlink -f "$BASH_SOURCE")")/env
echo "Converting bitstream to JLink script"
`which python3` -m quicklogic_fasm.bitstream_to_jlink $@

2
f4pga/wrappers/sh/quicklogic/write_openocd.f4pga.sh Normal file → Executable file
View File

@ -18,7 +18,5 @@
set -e
source $(dirname "$(readlink -f "$BASH_SOURCE")")/env
echo "Converting bitstream to OpenOCD script"
`which python3` -m quicklogic_fasm.bitstream_to_openocd $@