Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modelsim Block Design and IP Core integration #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
40 changes: 40 additions & 0 deletions build/Modelsim.bd.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
set output_path [lindex $argv 0]
set bd_core_file [lindex $argv 1]
set fpga [lindex $argv 2]

set modelsim_library ""
if { [info exists ::env(MODELSIM_XIL_LIBRARY)] } {
set modelsim_library "$env(MODELSIM_XIL_LIBRARY)"
} else {
set modelsim_library "$env(XILINX_VIVADO)/modelsimlib"
}

puts "Ouput path: $output_path"
puts "IP Core file: $ip_core_file"
puts "FPGA: $fpga"

set lib_map_path_arg ""
if {[file exist $modelsim_library]} {
puts "Using Modelsim precompiled library - $modelsim_library"
set lib_map_path_arg [list {-lib_map_path} [list {modelsim="$modelsim_library"}]]
}

create_project -in_memory -part "$fpga"

read_bd "$bd_core_file"
upgrade_ip [get_ips *] -quiet

exec mkdir -p "$output_path/ip_user_files_dir/ipstatic"

generate_target all [get_files "$bd_core_file"] -force
export_simulation \
-simulator modelsim \
-force \
-absolute_path \
-use_ip_compiled_libs \
-ip_user_files_dir $output_path/ip_user_files_dir \
{*}$lib_map_path_arg \
-ipstatic_source_dir $output_path/ip_user_files_dir/ipstatic \
-export_source_files \
-directory "$output_path" \
-of_objects [get_files "$bd_core_file"]
159 changes: 128 additions & 31 deletions build/Modelsim.inc.fdo
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,76 @@ source $OFM_PATH/build/Shared.tcl
# Procedures and Functions
# ---------------------------------------------------------------------

proc VivadoProcessTCLScript {IP_GEN_PATH SIM_GEN_PATH FNAME SCRIPT} {
namespace upvar ::NDKBuild SIM_FLAGS SIM_FLAGS

set IP_NAME [file rootname [file tail $FNAME]]
exec vivado -mode batch -journal ${IP_GEN_PATH}${IP_NAME}_vivado.jou -log ${IP_GEN_PATH}${IP_NAME}_vivado.log -source "$SCRIPT" -tclargs "$SIM_GEN_PATH" "$FNAME" "${SIM_FLAGS(FPGA)}"
}

proc CompileIPCore {IP_GEN_PATH SIM_GEN_PATH FNAME} {
global OFM_PATH
namespace upvar ::NDKBuild SIM_FLAGS SIM_FLAGS
set VIVADO_IP_BUILD [file normalize [file join $OFM_PATH/build Modelsim.ip.tcl]]

#IP core compiling
puts "Generating IP Core file: $FNAME"
if { ![regexp {^.*.xci$} $FNAME] } {
return
}

#Generate files using vivado
VivadoProcessTCLScript $IP_GEN_PATH $SIM_GEN_PATH $FNAME $VIVADO_IP_BUILD
}

# Compile vivado block design using modelsim
proc CompileBlockDesign {IP_GEN_PATH SIM_GEN_PATH FNAME} {
global OFM_PATH
namespace upvar ::NDKBuild SIM_FLAGS SIM_FLAGS
set VIVADO_BD_BUILD [file normalize [file join $OFM_PATH/build Modelsim.bd.tcl]]

#Block Design compiling
puts "Generating Block Design file: $FNAME"
if { ![regexp {^.*.bd$} $FNAME] } {
return
}

#Generate files using vivado
VivadoProcessTCLScript $IP_GEN_PATH $SIM_GEN_PATH $FNAME $VIVADO_IP_BUILD
}

proc ProcessVivadoSimCompile {COMPILE_FILE} {
namespace upvar ::NDKBuild SIM_FLAGS SIM_FLAGS

exec /bin/sed -i {s/ xil_defaultlib/ work/g} "$COMPILE_FILE"
exec /bin/sed -i {/vmap work/d} "$COMPILE_FILE"

source "$COMPILE_FILE"
}

proc ProcessVivadoSimulationExport {SIM_FILE} {
namespace upvar ::NDKBuild SIM_FLAGS SIM_FLAGS
exec /bin/sed -i {s/ xil_defaultlib/ work/g} "$SIM_FILE"
set fp [open [ glob "$SIM_FILE"]]
set compile_content [read $fp]
close $fp

regexp -line {^vsim .*$} "$compile_content" vsim_content
#Regex starting with - must be escaped in tcl ?
regexp {\-(?:[^-\s])+(?:\s(?:[^-\s])+){2}((?:\s[^-\s]+)*)$} "$vsim_content" modules_match modules
set libraries_match [ regexp -all -inline {(?:-L ([^-\s]+))} "$vsim_content" ]
set libraries [ lmap {match group} $libraries_match { set group } ]

if {[info exists libraries]} {
puts "Adding Libs: $libraries"
lappend SIM_FLAGS(SIM_LIB) {*}$libraries
}
if {[info exists modules]} {
puts "Adding Modules: $modules"
lappend SIM_FLAGS(SIM_MODULE) {*}$modules
}
}

# Decide which command should be used for particular file
proc CompileMod {FNAME OPT} {
namespace upvar ::NDKBuild SIM_FLAGS SIM_FLAGS
Expand All @@ -46,36 +116,53 @@ proc CompileMod {FNAME OPT} {
}

# Generate netlists for utilized Vivado IP cores
# TCL Debug trace: trace add execution source enterstep {apply {{cmd op} {puts "+ $cmd"}}}
if {$opt(TYPE) == "VIVADO_IP_XACT"} {
if {![info exists SIM_FLAGS(FPGA)]} {
puts "WARNING: SIM_FLAGS(FPGA) doesn't exists, skipping generating netlist for Vivado IP core $FNAME"
} else {
set IP_GEN_PATH "$SIM_FLAGS(SIM_MODULE)-${SIM_FLAGS(FPGA)}.vivado_ip_tmp/"
file mkdir $IP_GEN_PATH

# Initialization
if {![info exists SIM_FLAGS(FPGA)]} {
puts "WARNING: SIM_FLAGS(FPGA) doesn't exists, generating of Modelsim Simulation for Vivado IP core $FNAME. Will most likely fail"
}
if { ![file exist "modelsim_lib"] } {
file mkdir "modelsim_lib"
}
set IP_NAME [file rootname [file tail $FNAME]]
set IP_GEN_SCRIPT ${IP_GEN_PATH}${IP_NAME}_netlist_gen.tcl
if {[file exists $IP_GEN_SCRIPT]} {
puts "$IP_GEN_SCRIPT exists, assume IP core's netlist has already been generated"
return
set SIM_GET_FOLDER "gen_sim"
set IP_GEN_PATH "${SIM_FLAGS(FPGA)}.vivado_ip_tmp/"
set SIM_GEN_PATH [file join "$IP_GEN_PATH" "$IP_NAME" ]
set compile_do [file join "$SIM_GEN_PATH" "*/modelsim/compile.do" ]
set simulate_do [file join "$SIM_GEN_PATH" "*/modelsim/simulate.do" ]
try { glob "$compile_do" } trap {TCL OPERATION GLOB NOMATCH} {} { set generate "" }

if {[info exists generate]} {
CompileIPCore "$IP_GEN_PATH" "$SIM_GEN_PATH" "$FNAME"
}
PrintLabel "IP Netlist Generation ($IP_NAME)"

# Prepare netlist generation Tcl script for Vivado
exec echo "
create_project -in_memory -part $SIM_FLAGS(FPGA)
set_property target_language VHDL \[current_project\]
read_ip $FNAME
upgrade_ip \[get_ips $IP_NAME\]
set_property GENERATE_SYNTH_CHECKPOINT TRUE \[get_files $FNAME\]
synth_ip \[get_ips $IP_NAME\]
quit
" > $IP_GEN_SCRIPT

# Generate netlist using Vivado
exec vivado -mode tcl -journal ${IP_GEN_PATH}${IP_NAME}_vivado.jou -log ${IP_GEN_PATH}${IP_NAME}_vivado.log -source $IP_GEN_SCRIPT >&@stdout
}
set compile_glob_do [ glob "$compile_do" ]
set simulate_glob_do [ glob "$simulate_do" ]
ProcessVivadoSimCompile "$compile_glob_do"
ProcessVivadoSimulationExport "$simulate_glob_do"
return;
} elseif {$opt(TYPE) == "VIVADO_BD"} {
if {![info exists SIM_FLAGS(FPGA)]} {
puts "WARNING: SIM_FLAGS(FPGA) doesn't exists, generating of Modelsim Simulation for Vivado BD $FNAME. Will most likely fail"
}
if { ![file exist "modelsim_lib"] } {
file mkdir "modelsim_lib"
}
set BD_NAME [file rootname [file tail $FNAME]]
set SIM_GET_FOLDER "gen_sim"
set BD_GEN_PATH "${SIM_FLAGS(FPGA)}.vivado_ip_tmp/"
set SIM_GEN_PATH [file join "$BD_GEN_PATH" "$BD_NAME" ]
set compile_do [file join "$SIM_GEN_PATH" "*/modelsim/compile.do" ]
set simulate_do [file join "$SIM_GEN_PATH" "*/modelsim/simulate.do" ]
try { glob "$compile_do" } trap {TCL OPERATION GLOB NOMATCH} {} { set generate "" }

if {[info exists generate]} {
CompileBlockDesign "$BD_GEN_PATH" "$SIM_GEN_PATH" "$FNAME"
}
set compile_glob_do [ glob "$compile_do" ]
set simulate_glob_do [ glob "$simulate_do" ]
ProcessVivadoSimCompile "$compile_glob_do"
ProcessVivadoSimulationExport "$simulate_glob_do"
return;
}

# Skip unknown file types
Expand All @@ -94,13 +181,21 @@ proc CompileMod {FNAME OPT} {
lappend opt(VLOG_SV_FLAGS)

# Source compiling
if {$FEXT in [list .v .vh]} {
if {$FEXT in [list .vh .svh]} {
return
} elseif {$FEXT in [list .v]} {
set CMD [list vlog {*}$COVER_PARAMS -timescale "1ps/1ps" -work $LIB]
} elseif {$FEXT in [list .sv]} {
# Add simulation libarries to .sv files to allow use of modules generated by .ip and .bds
set SV_LIBS ""
foreach i [uniqueList $SIM_FLAGS(SIM_LIB)] {
lappend SV_LIBS -L "$i"
}

regsub "/\[^/\]+\$" $FNAME "/" DIR
set CMD [list vlog $VMAKE_OPT {*}$COVER_PARAMS_SV -sv -timescale "1ps/1ps" -work $LIB +incdir+$DIR {*}$SIM_FLAGS(VLOG_SV_FLAGS) {*}$opt(VLOG_SV_FLAGS)]
} else {
set CMD [list vcom -2008 -explicit {*}$COVER_PARAMS -work $LIB]
set CMD [list vlog $VMAKE_OPT {*}$COVER_PARAMS_SV -sv -timescale "1ps/1ps" -work $LIB +incdir+$DIR $SV_LIBS {*}$SIM_FLAGS(VLOG_SV_FLAGS) {*}$opt(VLOG_SV_FLAGS)]
} elseif {$FEXT in [list .vhd]} {
set CMD [list vcom -mixedsvvh b -2008 -explicit {*}$COVER_PARAMS -work $LIB]
}

if {$SIM_FLAGS(BATCH_COMPILE)} {
Expand Down Expand Up @@ -329,6 +424,7 @@ proc nb_vsim_set_flags {vsim_flags sim_flags} {
}

proc nb_sim_main {{user_sim_flags SIM_FLAGS}} {

# Let VSIM_FLAGS variable to be accessible in top level stack frame for running vsim by hand
upvar 1 VSIM_FLAGS VSIM_FLAGS

Expand All @@ -352,6 +448,7 @@ proc nb_sim_main {{user_sim_flags SIM_FLAGS}} {

# Run simulation
if {!$SIM_FLAGS(VSIM_MANUAL_START)} {
puts "vsim {*}$VSIM_FLAGS"
vsim {*}$VSIM_FLAGS
}
}
Expand Down
40 changes: 40 additions & 0 deletions build/Modelsim.ip.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
set output_path [lindex $argv 0]
set ip_core_file [lindex $argv 1]
set fpga [lindex $argv 2]

set modelsim_library ""
if { [info exists ::env(MODELSIM_XIL_LIBRARY)] } {
set modelsim_library "$env(MODELSIM_XIL_LIBRARY)"
} else {
set modelsim_library "$env(XILINX_VIVADO)/modelsimlib"
}

puts "Ouput path: $output_path"
puts "IP Core file: $ip_core_file"
puts "FPGA: $fpga"

set lib_map_path_arg ""
if {[file exist $modelsim_library]} {
puts "Using Modelsim precompiled library - $modelsim_library"
set lib_map_path_arg [list "-lib_map_path" [list "modelsim\=$modelsim_library"]]
}

create_project -in_memory -part "$fpga"

read_ip "$ip_core_file"
upgrade_ip [get_ips *] -quiet

exec mkdir -p "$output_path/ip_user_files_dir/ipstatic"

generate_target all [get_files "$ip_core_file"] -force
export_simulation \
-simulator modelsim \
-force \
-absolute_path \
-use_ip_compiled_libs \
-ip_user_files_dir $output_path/ip_user_files_dir \
{*}$lib_map_path_arg \
-ipstatic_source_dir $output_path/ip_user_files_dir/ipstatic \
-export_source_files \
-directory "$output_path" \
-of_objects [get_files $ip_core_file]