ucb-bar / chipyard

An Agile RISC-V SoC Design Framework with in-order cores, out-of-order cores, accelerators, and more
https://chipyard.readthedocs.io/en/stable/
BSD 3-Clause "New" or "Revised" License
1.67k stars 656 forks source link

FPGA Prototyping Error Caused by Vivado Tcl Interpreter: fpga-shells/xilinx/common/tcl/prologue.tcl #1141

Open zslwyuan opened 2 years ago

zslwyuan commented 2 years ago

Background Work

Chipyard Version and Hash

Release: 1.5.0 Hash: a6a6a6

OS Setup

Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focal

Other Setup

Go through the standard FPGA prototyping flow in Chipyard Documentation

Current Behavior

As mentioned in Chipyard Google Group here:

When I excute the command "make SUB_PROJECT=vcu118 CONFIG=RocketVCU118Config bitstream" ERROR as follows:

source /home/liupeipei/chipyard/fpga/fpga-shells/xilinx/common/tcl/vivado.tcl
# set scriptdir [file dirname [info script]]
# source [file join $scriptdir "prologue.tcl"]
## set ip_vivado_tcls {}
## while {[llength $argv]} {
##   set argv [lassign $argv[set argv {}] flag]
##   switch -glob $flag {
##     -top-module {
##       set argv [lassign $argv[set argv {}] top]
##     }
##     -F {
##       # This should be a simple file format with one filepath per line
##       set argv [lassign $argv[set argv {}] vsrc_manifest]
##     }
##     -board {
##       set argv [lassign $argv[set argv {}] board]
##     }
##     -ip-vivado-tcls {
##       set argv [lassign $argv[set argv {}] ip_vivado_tcls]
##     }
##     -pre-impl-debug-tcl {
##       set argv [lassign $argv[set argv {}] pre_impl_debug_tcl]
##     }
##     -post-impl-debug-tcl {
##       set argv [lassign $argv[set argv {}] post_impl_debug_tcl]
##     }
##     -env-var-srcs {
##       set argv [lassign $argv[set argv {}] env_var_srcs]
##     }
##     default {
##       return -code error [list {unknown option} $flag]
##     }
##   }
## }
{unknown option} {}

    while executing
"source [file join $scriptdir "prologue.tcl"]"
    (file "/home/liupeipei/chipyard/fpga/fpga-shells/xilinx/common/tcl/vivado.tcl" line 7)
INFO: [Common 17-206] Exiting Vivado at Wed Mar  2 10:41:24 2022...
make: *** [Makefile:115: /home/liupeipei/chipyard/fpga/generated-src/chipyard.fpga.vcu118.VCU118FPGATestHarness.RocketVCU118Config/obj/VCU118FPGATestHarness.bit] Error 1

Expected Behavior

The Tcl script should work fine with Error

Other Information

This is a bug of Vivado Tcl interpreter. I am not sure whether I should make a new pull request since the solution is a little bit dirty by modifying the file fpga/fpga-shells/xilinx/common/tcl/prologue.tcl. I provided the solution here in case someone else encounters this similar problem.

-ip-vivado-tcls {
  set ip_vivado_tcls {}
  while {[llength $argv]}  {
      set firstArg [lindex $argv 0]
      set isTclFile [string match *.tcl $firstArg]
      if {$isTclFile}         {
            puts "adding tcl file: ${firstArg}"
        set argv [lassign $argv[set argv {}] firstArg]
        lappend ip_vivado_tcls $firstArg
        puts "tcl file list: ${ip_vivado_tcls}"
      } else  {
          puts "terminate addition of tcl while argv= ${argv}"
          break
      }
  }
}
wangliwei-intel commented 2 years ago

@zslwyuan Could you please show a complete updated prologue.tcl? thanks. I'm experiencing the same issue.

zslwyuan commented 2 years ago

@zslwyuan Could you please show a complete updated prologue.tcl? thanks. I'm experiencing the same issue.

Hi @wangliwei-intel

check the following codes to update prologue.tcl:

# See LICENSE for license details.

# Process command line arguments
# http://wiki.tcl.tk/1730
set ip_vivado_tcls {}

while {[llength $argv]} {
  set argv [lassign $argv[set argv {}] flag]
  switch -glob $flag {
    -top-module {
      set argv [lassign $argv[set argv {}] top]
    }
    -F {
      # This should be a simple file format with one filepath per line
      set argv [lassign $argv[set argv {}] vsrc_manifest]
    }
    -board {
      set argv [lassign $argv[set argv {}] board]
    }
-ip-vivado-tcls {
  set ip_vivado_tcls {}
  while {[llength $argv]}  {
      set firstArg [lindex $argv 0]
      set isTclFile [string match *.tcl $firstArg]
      if {$isTclFile}         {
            puts "adding tcl file: ${firstArg}"
        set argv [lassign $argv[set argv {}] firstArg]
        lappend ip_vivado_tcls $firstArg
        puts "tcl file list: ${ip_vivado_tcls}"
      } else  {
          puts "terminate addition of tcl while argv= ${argv}"
          break
      }
  }
}
    -pre-impl-debug-tcl {
      set argv [lassign $argv[set argv {}] pre_impl_debug_tcl]
    }
    -post-impl-debug-tcl {
      set argv [lassign $argv[set argv {}] post_impl_debug_tcl]
    }
    -env-var-srcs {
      set argv [lassign $argv[set argv {}] env_var_srcs]
    }
    default {
      return -code error [list {unknown option} $flag]
    }
  }
}
# tcl-env-srcs: Command line argument to pass the name of an environment variable that contains additional vsrcs 
# (from what is contained in .F file) that you want to have read in

if {![info exists top]} {
  return -code error [list {--top-module option is required}]
}

if {![info exists vsrc_manifest]} {
  return -code error [list {-F option is required}]
}

if {![info exists board]} {
  return -code error [list {--board option is required}]
}

# Set the variable for all the common files
set commondir [file dirname $scriptdir]

# Set the variable that points to board specific files
set boarddir [file join [file dirname $commondir] $board]
source [file join $boarddir tcl board.tcl]

# Set the variable that points to board constraint files
set constraintsdir [file join $boarddir constraints]

# Set the variable that points to common verilog sources
set srcdir [file join $commondir vsrc]

# Creates a work directory
set wrkdir [file join [pwd] obj]

# Create the directory for IPs
set ipdir [file join $wrkdir ip]

# Create an in-memory project
create_project -part $part_fpga -force $top

set_param messaging.defaultLimit 1000000

# Set the board part, target language, default library, and IP directory
# paths for the current project
set_property -dict [list \
    BOARD_PART $part_board \
    TARGET_LANGUAGE {Verilog} \
    DEFAULT_LIB {xil_defaultlib} \
    IP_REPO_PATHS $ipdir \
    ] [current_project]

if {[get_filesets -quiet sources_1] eq ""} {
    create_fileset -srcset sources_1
}
set obj [current_fileset]

# Add verilog files from manifest
proc load_vsrc_manifest {obj vsrc_manifest} {
  set fp [open $vsrc_manifest r]
  set files [lsearch -not -exact -all -inline [split [read $fp] "\n"] {}]
  set relative_files {}
  foreach path $files {
    if {[string match {/*} $path]} {
      lappend relative_files $path
    } elseif {![string match {#*} $path]} {
      lappend relative_files [file join [file dirname $vsrc_manifest] $path]
    }
  }
  # Read environment variable vsrcs and append to relative_files
  upvar #0 env_var_srcs env_var_srcs
  set additions [info exists env_var_srcs]
  if {$additions} {
    if {[info exists ::env($env_var_srcs)]} {
      set resources [split $::env($env_var_srcs) :]
      set relative_files [list {*}$relative_files {*}$resources]
    }
  }
  add_files -norecurse -fileset $obj {*}$relative_files
  close $fp
}

load_vsrc_manifest $obj $vsrc_manifest

# Add IP Vivado TCL
if {$ip_vivado_tcls ne {}} {
  # Split string into words even with multiple consecutive spaces
  # http://wiki.tcl.tk/989
  set ip_vivado_tcls [regexp -inline -all -- {\S+} $ip_vivado_tcls]
}

if {[get_filesets -quiet sim_1] eq ""} {
    create_fileset -simset sim_1
}
set obj [current_fileset -simset]

if {[get_filesets -quiet constrs_1] eq ""} {
    create_fileset -constrset constrs_1
}

set obj [current_fileset -constrset]
add_files -quiet -norecurse -fileset $obj [lsort [glob -directory $constraintsdir -nocomplain {*.tcl}]]
add_files -quiet -norecurse -fileset $obj [lsort [glob -directory $constraintsdir -nocomplain {*.xdc}]]