Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions ipbb/cli/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,15 @@ def git(env, repo, branch, dest):
# Maybe not necessary

lUrl = urlparse(repo)
# Strip '.git' at the end
lRepoName = splitext(basename(lUrl.path))[0] if dest is None else dest
# Strip '.git' at the end if it exists, this supports git in a folder
if 'git' in lUrl.path:
lRepoName = splitext(basename(lUrl.path))[0] if dest is None else dest
else:
lRepoName = lUrl.path if dest is None else dest

lRepoLocalPath = join(env.work.path, kSourceDir, lRepoName)

# Check for
# Check for
if exists(lRepoLocalPath):
raise click.ClickException(
'Repository already exists \'%s\'' % lRepoLocalPath
Expand Down Expand Up @@ -122,7 +126,7 @@ def git(env, repo, branch, dest):
if dest is not None:
lArgs += [dest]

sh.git(*lArgs, _out=sys.stdout, _cwd=env.srcdir)
sh.git(*lArgs)#glein: , _out=sys.stdout, _cwd=env.srcdir)

if branch is not None:

Expand Down Expand Up @@ -402,4 +406,4 @@ def status(env):
@srcs.command('find', short_help="Find src files.")
@click.pass_obj
def find(env):
sh.find(env.srcdir,'-name', '*.vhd', _out=sys.stdout)
sh.find(env.srcdir,'-name', '*.vhd', _out=sys.stdout)
89 changes: 89 additions & 0 deletions ipbb/cli/vivado.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import sys
import sh
import time
import re
import hashlib

# Elements
from os.path import join, split, exists, splitext, abspath, basename
Expand All @@ -20,6 +22,8 @@
from ..depparser.VivadoProjectMaker import VivadoProjectMaker
from ..tools.xilinx import VivadoOpen, VivadoConsoleError, VivadoSnoozer

# Debugging and testing
#import pdb; pdb.set_trace()

# ------------------------------------------------------------------------------
def ensureVivado(env):
Expand Down Expand Up @@ -259,6 +263,91 @@ def synth(env, jobs):
secho("\n{}: Synthesis completed successfully.\n".format(env.currentproj.name), fg='green')
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
def getIPCoresCompiled(aConsole, proj):
lVivProjPath = proj.path
print(lVivProjPath)
lIPCoresPath = join(lVivProjPath, 'top', 'top.srcs', 'sources_1', 'ip')
for folder in next(os.walk(lIPCoresPath))[1]:
if not os.path.isdir(join(lIPCoresPath, folder, 'sim')):
secho("Simulation directory does not exist for %s. Compiling the ip-core."%(folder), fg='yellow')
aConsole('generate_target all [get_files %s/top/top.srcs/sources_1/ip/%s/%s.xci]' % (lVivProjPath, folder, folder))
aConsole('export_ip_user_files -of_objects [get_files %s/top/top.srcs/sources_1/ip/%s/%s.xci] -no_script -sync -force -quiet' % (lVivProjPath,folder,folder))
aConsole('export_simulation -of_objects [get_files %s/top/top.srcs/sources_1/ip/%s/%s.xci] -directory %s/top/top.ip_user_files/sim_scripts -ip_user_files_dir %s/top/top.ip_user_files -ipstatic_source_dir %s/top/top.ip_user_files/ipstatic -lib_map_path [list {modelsim=%s/top/top.cache/compile_simlib/modelsim} {questa=%s/top/top.cache/compile_simlib/questa} {ies=%s/top/top.cache/compile_simlib/ies} {xcelium=%s/top/top.cache/compile_simlib/xcelium} {vcs=%s/top/top.cache/compile_simlib/vcs} {riviera=%s/top/top.cache/compile_simlib/riviera}] -use_ip_compiled_libs -force -quiet' %(lVivProjPath, folder, folder, lVivProjPath, lVivProjPath, lVivProjPath, lVivProjPath, lVivProjPath, lVivProjPath, lVivProjPath, lVivProjPath, lVivProjPath))

# ------------------------------------------------------------------------------
@vivado.command('sim', short_help='Run the simulation step on the specified dependency.')
@click.option('-rf', '--run-for', metavar='<time> <unit>',type=(int, str), default=(0,'us'), help = "Specify the duration of the simulation of <time> <unit> in addition to the default 1 us.")
@click.option('-g', '--GUI-mode', is_flag=True, help = "Show simulation in Vivado interface.")
@click.option('-c', '--iocheck', is_flag=True, help = "Compare simulation output text to the golden output in golden_hash.txt")
@click.pass_obj
def sim(env, run_for, gui_mode, iocheck):

lSessionId = 'sim'

# Check
lVivProjPath = join(env.currentproj.path, 'top', 'top.xpr')
if not exists(lVivProjPath):
raise click.ClickException("Vivado project %s does not exist" % lVivProjPath, fg='red')

ensureVivado(env)

#find the test bench name
proj_file = open(lVivProjPath, 'r')
proj_file_text = proj_file.read()
tb_path = re.search('[^/]+/tb_.+\.',proj_file_text).group(0)

tb_path = tb_path[0:len(tb_path) - 1].split('/')
board = tb_path[0]
tb_file = tb_path[1]

proj_file.close()

from ..tools.xilinx import VivadoOpen, VivadoConsoleError
try: #prepare and run simulation
with VivadoOpen(lSessionId, echo=env.vivadoEcho) as lConsole:
lConsole('open_project {}'.format(lVivProjPath)) #open the project in Vivado
lConsole('set_property top {} [get_filesets sim_1]'.format(tb_file)) #set the top file
lConsole('set_property source_mgmt_mode All [current_project]')
lConsole('update_compile_order -fileset sources_1') #update compile order

getIPCoresCompiled(lConsole, env.currentproj)

#commented for testing
lConsole(["launch_simulation"]) #run the simulation in Vivado for 1000ns
if run_for[0] != 0:
lConsole('run {}{}'.format(run_for[0],run_for[1])) #extend simulation for time specified
lConsole("start_gui" if gui_mode else "") #start GUI when specified

except VivadoConsoleError as lExc:
echoVivadoConsoleError(lExc)
raise click.Abort()

if iocheck: #perform check on the textio output and golden output
md5 = hashlib.md5()
with open("../../src/fpga/framework/hdl/tb/{}/golden_hash.txt".format(board), 'r') as g:
f = open("../../src/fpga/framework/hdl/tb/{}/output_text.txt".format(board), 'r')
md5.update(f.read()) #feed file to md5sum
hash_key = md5.hexdigest()
hash_key_check = False
for line in g.readlines():
if line[0] != '#': #ignore comments in golden_hash.txt
vals = line.split(',')
if vals[1] == hash_key: #catch matching hash
hash_key_check = True
print("Output matched golden output! Calculated hash is: {}".format(hash_key))
break

if hash_key_check != True:
raise click.ClickException(click.style("Simulation output does not match any golden output. Calculated hash is: {}".format(hash_key),fg='red'))

# except Exception as error:
# print("Error: golden_hash.txt not found")
# raise click.Abort()

secho("\n{}: Simulation completed successfully.\n".format(env.currentproj.name), fg='green')

# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
@vivado.command('impl', short_help='Run the implementation step on the current project.')
Expand Down
38 changes: 37 additions & 1 deletion ipbb/depparser/VivadoProjectMaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import time
import os
import collections
import glob
import subprocess

from string import Template as tmpl

Expand All @@ -24,7 +26,9 @@ class VivadoProjectMaker(object):
'.xci': 'sources_1',
'.ngc': 'sources_1',
'.edn': 'sources_1',
'.edf': 'sources_1'
'.edf': 'sources_1',
'.bd': 'sources_1',
'.dat': 'sources_1'
# Legacy ISE files
# '.ucf': 'ise_1',
# '.xco': 'ise_1',
Expand Down Expand Up @@ -60,6 +64,21 @@ def write(self, aTarget, aScriptVariables, aComponentPaths, aCommandList, aLibs,
)
)

# for block designs of development boards
if 'board_part' not in aScriptVariables:
pass
else:
write(
'set_property BOARD_PART {board_part} [current_project]'.format(
**aScriptVariables
)
)

write(
'if {[string equal [get_filesets -quiet constrs_1] ""]} {create_fileset -constrset constrs_1}')
write(
'if {[string equal [get_filesets -quiet sources_1] ""]} {create_fileset -srcset sources_1}')

# Add ip repositories to the project variable
write('set_property ip_repo_paths {{{}}} [current_project]'.format(
' '.join(map( lambda c: c.FilePath, aCommandList['iprepo']))
Expand Down Expand Up @@ -98,6 +117,23 @@ def write(self, aTarget, aScriptVariables, aComponentPaths, aCommandList, aLibs,

lXciBasenames.append(lName)
lXciTargetFiles.append(lTargetFile)

# Support block designs
elif lExt == '.bd': # import pdb; pdb.set_trace()

fl=glob.glob(lPath+'/*') # delete build artefacts to include recursive submodules
fl.remove(lPath+'/'+lBasename) # do not delete the design
if os.path.exists(lPath+'/hdl'): # do not delete hdl file if it exists
fl.remove(lPath+'/hdl')
for file in fl:
subprocess.Popen(['rm', '-rf', file])

# hard write to add, open, and close board design
write(str('add_files -fileset sources_1 {'+lPath+'/'+lBasename+'}'))
write(str('open_bd_design {'+lPath+'/'+lBasename+'}')) # open design to add all submodules
write('close_bd_design [current_bd_design]')
write(str('generate_target all [get_files '+lPath+'/'+lBasename+']')) # get all submodules

else:
if src.Include:

Expand Down
7 changes: 4 additions & 3 deletions ipbb/scripts/programmer.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,10 @@ def _validateDevice(ctx, param, value):
@vivado.command('program')
@click.argument('deviceid', callback=_validateDevice)
@click.argument('bitfile', type=click.Path(exists=True))
@click.option('-v/-q', 'aVerbosity', default=False)
@click.option('-p', '--probe', type=click.File(), default=None, help="Probe file")
@click.option('-v/-q', 'aVerbosity', default=False, help="Turns verbosity on/off. Default is -q (quiet).")
@click.pass_obj
def program(obj, deviceid, bitfile, aVerbosity):
def program(obj, deviceid, bitfile, probe, aVerbosity):

target, device = deviceid

Expand Down Expand Up @@ -196,7 +197,7 @@ def program(obj, deviceid, bitfile, aVerbosity):

if click.confirm(style("Bitfile {0} will be loaded on {1}.\nDo you want to continue?".format(bitfile, lTarget), fg='yellow')):
echo("Programming {}".format(lTarget))
v.programDevice(device, bitfile)
v.programDevice(device, bitfile, probe.name if probe else None)
echo("Done.")
secho("{} successfully programmed on {}".format(bitfile, lTarget), fg='green')
else:
Expand Down
6 changes: 3 additions & 3 deletions ipbb/tools/xilinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ def getHwDevices(self):
# --------------------------------------------------------------

# --------------------------------------------------------------
def programDevice(self, device, bitfile):
def programDevice(self, device, bitfile, probe):
from os.path import abspath, normpath

bitpath = abspath(normpath(bitfile))
Expand All @@ -517,9 +517,9 @@ def programDevice(self, device, bitfile):

self.execute('current_hw_device {0}'.format(device))
self.execute(
'refresh_hw_device -update_hw_probes false [current_hw_device]'
'refresh_hw_device -update_hw_probes {} [current_hw_device]'.format("True" if probe else "False")
)
self.execute('set_property PROBES.FILE {{}} [current_hw_device]')
self.execute('set_property PROBES.FILE {{{0}}} [current_hw_device]'.format(probe if probe else ""))
self.execute(
'set_property PROGRAM.FILE {{{0}}} [current_hw_device]'.format(bitpath)
)
Expand Down