Skip to content

Commit

Permalink
Merge pull request #38 from sgherbst/feature/merge_github_resolve_fun…
Browse files Browse the repository at this point in the history
…c_issue

Feature/merge GitHub resolve func issue
  • Loading branch information
sgherbst authored Oct 28, 2020
2 parents cc68d47 + 1e6707c commit 49eb8df
Show file tree
Hide file tree
Showing 44 changed files with 1,451 additions and 727 deletions.
73 changes: 40 additions & 33 deletions anasymod/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from anasymod.filesets import Filesets
from anasymod.defines import Define
from anasymod.targets import CPUTarget, FPGATarget
from anasymod.enums import ConfigSections
from anasymod.enums import ConfigSections, FPGASimCtrl
from anasymod.utils import statpro
from anasymod.util import expand_path
from anasymod.wave import ConvertWaveform
Expand Down Expand Up @@ -314,7 +314,7 @@ def gen_sources(self, plugins=None):
plugin._set_generator_sources(generator_sources=self.filesets._functional_models)
plugin.models()

def build(self):
def build(self, *args, **kwargs):
"""
Generate bitstream for FPGA target
"""
Expand All @@ -327,20 +327,12 @@ def build(self):
target = getattr(self, self.act_fpga_target)

VivadoEmulation(target=target).build()
statpro.statpro_update(statpro.FEATURES.anasymod_build_vivado)

def build_firmware(self, *args, **kwargs):
# create target object, but don't generate instrumentation structure again in case target object does not exist yet
if not hasattr(self, self.act_fpga_target):
self._setup_targets(target=self.act_fpga_target)
# Build firmware for ctrl infrastructure if needed
if target.cfg.fpga_sim_ctrl == FPGASimCtrl.UART_ZYNQ:
self._build_firmware(*args, **kwargs)

# check if bitstream was generated for active fpga target
target = getattr(self, self.act_fpga_target)
if not os.path.isfile(getattr(target, 'bitfile_path')):
raise Exception(f'Bitstream for active FPGA target was not generated beforehand; please do so before running emulation.')

# build the firmware
XSCTEmulation(target=target).build(*args, **kwargs)
statpro.statpro_update(statpro.FEATURES.anasymod_build_vivado)

def emulate(self, server_addr=None, convert_waveform=True):
"""
Expand Down Expand Up @@ -388,19 +380,6 @@ def emulate(self, server_addr=None, convert_waveform=True):
dt_scale=self._prj_cfg.cfg.dt_scale
)

def program_firmware(self, *args, **kwargs):
# create target object, but don't generate instrumentation structure again in case target object does not exist yet
if not hasattr(self, self.act_fpga_target):
self._setup_targets(target=self.act_fpga_target)

# check if bitstream was generated for active fpga target
target = getattr(self, self.act_fpga_target)
if not os.path.isfile(getattr(target, 'bitfile_path')):
raise Exception(f'Bitstream for active FPGA target was not generated beforehand; please do so before running emulation.')

# build the firmware
XSCTEmulation(target=target).program(*args, **kwargs)

def launch(self, server_addr=None, debug=False):
"""
Program bitstream to FPGA, setup control infrastructure and wait for interactive commands.
Expand Down Expand Up @@ -435,9 +414,6 @@ def launch(self, server_addr=None, debug=False):
# Return ctrl handle for interactive control
return ctrl_handle

#ToDo: once recording via ila in interactive mode is finishe and caotured results were dumped into a file,
#ToDo: the conversion step to .vcd needs to be triggered via some command

def simulate(self, unit=None, id=None, convert_waveform=True, flags=None):
"""
Run simulation on a pc target. 'flags' contains a list of simulator-specific
Expand Down Expand Up @@ -868,9 +844,6 @@ def _setup_targets(self, target, gen_structures=False, debug=False):
if gen_structures:
getattr(getattr(self, target), 'gen_structure')()

# Generate corresponding firmware and add to sources
getattr(getattr(self, target), 'gen_firmware')()

# Copy generated sources by plugin from plugin build_root to target-specific build_root
for plugin in self._plugins:
try:
Expand Down Expand Up @@ -913,6 +886,40 @@ def _setup_probeobj(self, target: Union[FPGATarget, CPUTarget]):

return target.probes[target_name]

def _build_firmware(self, *args, **kwargs):
# create target object, but don't generate instrumentation structure again in case target object does not exist yet
if not hasattr(self, self.act_fpga_target):
self._setup_targets(target=self.act_fpga_target, gen_structures=True)

# check if bitstream was generated for active fpga target
target = getattr(self, self.act_fpga_target)
if not os.path.isfile(getattr(target, 'bitfile_path')):
raise Exception(f'Bitstream for active FPGA target was not generated beforehand; please do so before running emulation.')

# build the firmware
XSCTEmulation(pcfg=target.prj_cfg,
content=target.content,
project_root=target.project_root,
top_module=target.cfg.top_module
).build(*args, **kwargs)

def _program_firmware(self, server_addr=None, *args, **kwargs):
# create target object, but don't generate instrumentation structure again in case target object does not exist yet
if not hasattr(self, self.act_fpga_target):
self._setup_targets(target=self.act_fpga_target)

# check if bitstream was generated for active fpga target
target = getattr(self, self.act_fpga_target)
if not os.path.isfile(getattr(target, 'bitfile_path')):
raise Exception(f'Bitstream for active FPGA target was not generated beforehand; please do so before running emulation.')

# program the firmware
XSCTEmulation(pcfg=target.prj_cfg,
content=target.content,
project_root=target.project_root,
top_module=target.cfg.top_module
).program(server_addr=server_addr, **kwargs)

def main():
Analysis(op_mode='commandline')

Expand Down
72 changes: 72 additions & 0 deletions anasymod/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from sys import platform
from glob import glob
from pathlib import Path
from anasymod.files import get_full_path, mkdir_p
from anasymod.util import vivado_search_key
from os import environ as env
Expand Down Expand Up @@ -58,6 +59,9 @@ def __init__(self, root, cfg_file, active_target, build_root=None):
# Vivado configuration
self.vivado_config = VivadoConfig(parent=self)

# XSCT configuration
self.xsct_config = XSCTConfig(parent=self)

# GtkWave configuration
self.gtkwave_config = GtkWaveConfig(parent=self)

Expand Down Expand Up @@ -175,6 +179,74 @@ def version_number(self):
self._version_number = int(self._version_number)
return self._version_number

class XSCTConfig():
def __init__(self, parent: EmuConfig, xsct=None, version=None,
version_year=None, version_number=None, xsct_install_dir=None):
# save reference to parent config
self.parent = parent

# set project name
self.project_name = 'prj'
# intermediate variables for generic Xilinx path
if platform in {'win32', 'cygwin'}:
xilinx_version_path = parent.cfg_dict['TOOLS_xilinx']
xilinx_version = "20" + ".".join(xilinx_version_path.split(".")[0:2]).split("-")[1]
# set path to vivado binary
self.hints = [lambda: os.path.join(env['XSCT_INSTALL_PATH'], 'bin'),
lambda: os.path.join(parent.cfg_dict['INICIO_TOOLS'], xilinx_version_path, "SDK", xilinx_version, "bin" ),]
# lsf options for tcl mode of Vivado
self.lsf_opts_ls = ''
self.lsf_opts = parent.cfg.lsf_opts
if platform in {'linux', 'linux2'}:
sorted_dirs = sorted(glob('/tools/Xilinx/Vivado/*.*'), key=vivado_search_key)
self.hints.extend(lambda: os.path.join(dir_, 'bin') for dir_ in sorted_dirs)
if 'CAMINO' in os.environ:
self.lsf_opts = "-eh_ram 70000 -eh_ncpu 8 -eh_ui inicio_batch"
self.lsf_opts_ls = "-eh_ram 70000 -eh_ncpu 8 -eh_dispatch LS_SHELL"

self._xsct = xsct
self._xsct_install_dir = xsct_install_dir

# version, year, number
self._version = version
self._version_year = version_year
self._version_number = version_number

# set various project options
self.num_cores = multiprocessing.cpu_count()

@property
def xsct(self):
if self._xsct is None:
self._xsct = find_tool(name='xsct', hints=self.hints)
return self._xsct

@property
def xsct_install_dir(self):
if self._xsct_install_dir is None:
self._xsct_install_dir = Path(self.xsct).resolve().parent.parent
return self._xsct_install_dir

@property
def version(self):
if self._version is None:
self._version = pathlib.Path(self.xsct).parent.parent.name
return self._version

@property
def version_year(self):
if self._version_year is None:
self._version_year = re.match(r'(\d+)\.(\d+)', self.version).groups()[0]
self._version_year = int(self._version_year)
return self._version_year

@property
def version_number(self):
if self._version_number is None:
self._version_number = re.match(r'(\d+)\.(\d+)', self.version).groups()[1]
self._version_number = int(self._version_number)
return self._version_number

class XceliumConfig():
def __init__(self, parent: EmuConfig, xrun=None):
# save reference to parent config
Expand Down
39 changes: 35 additions & 4 deletions anasymod/emu/vivado_emu.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os.path
import subprocess

from anasymod.generators.vivado import VivadoTCLGenerator
from anasymod.generators.codegen import CodeGenerator
Expand All @@ -24,14 +25,31 @@ def __init__(self, target: FPGATarget):
super().__init__(target=target)

def build(self):
#subst drive
drive = 'V:'
# Check if on-chip memory is sufficient on selected FPGA board
if self.target.prj_cfg.board.bram is not None:
bits_per_sample = 0
probes = (self.target.str_cfg.digital_probes + self.target.str_cfg.analog_probes +
[self.target.str_cfg.time_probe] + [self.target.str_cfg.dec_cmp])
for probe in probes:
bits_per_sample += int(probe.width)
if (bits_per_sample * self.target.prj_cfg.ila_depth) > (self.target.prj_cfg.board.bram * 8):
raise(f'ERROR: Number ob samples to be recorded does not fit on FPGA board, please either select a '
f'board with more block memory, or change the ila_depth')
else:
print(f'WARNING: Check for sufficient BRAM could not be conducted, '
f'not enough information given in board definition!')

scfg = self.target.str_cfg
""" type : StructureConfig """
project_root = self.target.project_root
# under Windows there is the problem with path length more than 146 characters, that's why we have to use
# subst command to substitute project directory to a drive letter
if os.name == 'nt':
if len(back2fwd(self.target.project_root)) > 80:
project_root = self.subst_path(drive='V:')

project_root = self.subst_path(drive=drive)

# create a new project
self.create_project(
Expand Down Expand Up @@ -115,8 +133,7 @@ def build(self):
# generate all IPs
self.writeln('generate_target all [get_ips]')

# create block diagram if needed
# TODO: pass through configuration options
# create additional Hardware for control interface
if self.target.cfg.fpga_sim_ctrl == FPGASimCtrl.UART_ZYNQ:
self.use_templ(TemplZynqGPIO(is_ultrascale=scfg.is_ultrascale))

Expand Down Expand Up @@ -153,7 +170,21 @@ def build(self):
self.writeln('exec subst ' + self.subst + ' ' + self.old_subst)

# run bitstream generation
self.run(filename=r"bitstream.tcl", stack=self.target.prj_cfg.cfg.vivado_stack)
ret_error = self.run(filename=r"bitstream.tcl", stack=self.target.prj_cfg.cfg.vivado_stack, return_error=True)
if os.name == 'nt':
if ret_error:
#remove and restore drive substitutions
if self.subst:
try:
subprocess.call(f'subst {drive} /d', shell=True)
except:
print(f'WARNING: Removing mapped drive:{drive} did not work.')
if self.old_subst:
try:
subprocess.call(f'subst {drive} {self.old_subst}', shell=True)
except:
print(f'WARNING: Mapping of drive:{drive} to network path: {self.old_subst} did not work.')


def run_FPGA(self, **kwargs):
"""
Expand Down
Loading

0 comments on commit 49eb8df

Please sign in to comment.