#-----------------------------------------------------------------------------
# Title      : Vidado Do All
#-----------------------------------------------------------------------------
# File       : viv_do_all.tcl
# Author     : Peter Jansweijer <peterj@nikhef.nl>
# Company    : Nikhef
# Created    : 2018-01-24
# Last update: 2021-06-01
# Platform   : FPGA-generics
# Standard   : VHDL
#-----------------------------------------------------------------------------
# Description:
#
# This script does:
#      set project name
#      set part name
#      creates a new project
#      imports the source files
#      launches synthesis
#      launches implementation
#      generates a bitfile
#-----------------------------------------------------------------------------
#
# Copyright (c) 2021 Nikhef, Peter Jansweijer
#
# This source file is free software; you can redistribute it   
# and/or modify it under the terms of the GNU Lesser General   
# Public License as published by the Free Software Foundation; 
# either version 2.1 of the License, or (at your option) any   
# later version.                                               
#
# This source is distributed in the hope that it will be       
# useful, but WITHOUT ANY WARRANTY; without even the implied   
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      
# PURPOSE.  See the GNU Lesser General Public License for more 
# details.                                                     
#
# You should have received a copy of the GNU Lesser General    
# Public License along with this source; if not, download it   
# from http://www.gnu.org/licenses/lgpl-2.1.html
#
#-----------------------------------------------------------------------------

# do more cores threads.....set the parameter to max threads of the machine.
set_param general.maxThreads 16 

# set proj_name and proj_dir:
source proj_properties.tcl

# Format the raw time [clock seconds] to a date string
puts "[set date_string [clock format [clock seconds] -format "date: %y-%m-%d, time: %H:%M:%S"]] Implementation Started of $proj_name"

#Close currently open project and create a new one. (OVERWRITES PROJECT!!)
close_project -quiet

# Remove old and Create the new build directory
file delete -force $proj_dir
#file mkdir $proj_dir

create_project -force -part $device $proj_name ./$proj_dir
# work_directory is *full* path project directory.
# Vivado doesn't seem to accept relative paths!?
set work_directory [get_property DIRECTORY [current_project]]
set_property default_lib work [current_project]

# Create a hdl_version.xdc file to set the bitfile USERID to the revision date/version
set revision_log_file "revisiondate_log.txt"
if [file exists $revision_log_file] { 
    set revision_log_fileptr [open $revision_log_file]
    gets $revision_log_fileptr revision_log_date
    gets $revision_log_fileptr revision_log_revnumber
    close $revision_log_fileptr
    set userid [format "0x%6d%02d" $revision_log_date $revision_log_revnumber]
    puts "Bitfile USERID set to $userid"
} else {
    set userid 0xFFFFFFFF
    puts "WARNING Bitfile USERID set to 0xFFFFFFFF"
}
set hdl_version_file [open hdl_version.xdc w]
puts $hdl_version_file "set_property BITSTREAM.CONFIG.USERID $userid \[current_design\]"
close $hdl_version_file

set_property target_language VHDL [current_project]

# ------------------------------------------------------------------------------
# Read source files
# ------------------------------------------------------------------------------

set fp [open "proj_file_list.txt" r]
set file_data [read $fp]
close $fp
set content [split $file_data "\n"]

set use_bd  false
set use_bmm false

foreach line $content {
  puts $line
  set line_length [ string length $line ]
  if {[string range $line 0 0] == "#"} {
    # puts "comment"
  } elseif {[string range $line $line_length-4 $line_length] == ".vhd"} {
    # puts "vhdl"
    read_vhdl -library work $line
  } elseif {[string range $line $line_length-2 $line_length] == ".v"} {
    # puts "verilog"
    read_verilog -library work $line
  } elseif {[string range $line $line_length-3 $line_length] == ".vh"} {
    # puts "verilog"
    read_verilog -library work $line
  } elseif {[string range $line $line_length-3 $line_length] == ".sv"} {
    # puts "system verilog"
    read_verilog -sv  -library work $line
  } elseif {[string range $line $line_length-4 $line_length] == ".svh"} {
    # puts "system verilog"
    read_verilog -sv -library work $line
  } elseif {[string range $line $line_length-4 $line_length] == ".xci"} {
    # puts "xilinx ip"
    read_ip $line
  } elseif {[string range $line $line_length-5 $line_length] == ".xcix"} {
    # puts "xilinx ip"
    read_ip $line
  } elseif {[string range $line $line_length-4 $line_length] == ".xdc"} {
    # Read constraints file if any
    # puts "xdc"
    read_xdc -verbose $line
  } elseif {[string range $line $line_length-3 $line_length] == ".bd"} {
   # puts "xilinx bd"
    set use_bd true
    read_bd $line
    make_wrapper -files [get_files $line] -top -import
  } elseif {[string range $line $line_length-4 $line_length] == ".bmm"} {
    # Set pointer to bmm file if any
    # puts "bmm"
    set use_bmm true
    set bmm_file [pwd]/$line
    set bmm_bd ${proj_name}_bd.bmm
    add_files -norecurse $bmm_file
  }
}

if {[info exists spec7_design]} {
  if {$spec7_design == "spec7_ref_top"} {
    puts "use spec7_wr_ref_top.xdc"
    read_xdc -verbose ../../top/spec7_ref_design/spec7_wr_ref_top.xdc
  } elseif {$spec7_design == "spec7_hpsec_top"} {
    puts "use spec7_wr_hpsec_top.xdc"
    read_xdc -verbose ../../top/spec7_ref_design/spec7_wr_hpsec_top.xdc
  }
}

# Set Top level
set_property top $proj_name [current_fileset]
set_property source_mgmt_mode All [current_project]
update_compile_order -fileset sources_1

# Pass generics
set_property generic $generics [current_fileset]
puts "INFO: Reading Source Files Done!"

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

source $script_dir/viv_do_synt.tcl 
source $script_dir/viv_do_impl.tcl
if {$use_bmm} {
  source $script_dir/viv_generate_bd_bmm.tcl
  source $script_dir/viv_generate_bd_mmi.tcl
}
if {$use_bd} {
  write_hw_platform -fixed -force  -file ${proj_name}.xsa
}

close_design

# Generate a new name for .bit, .mmi and xsa file and copy to project directory.
# Also create a copy of these files in the work directory that can be picked up by .gitlab-ci.yml
# Create a senible name including date and time
set bitfile_name ${spec7_design}_[string range $device 3 6]_[clock format [clock seconds] -format %y%m%d_%H%M]
file copy ./work/${proj_name}.runs/impl_1/${proj_name}.bit ../${bitfile_name}.bit 
file copy ./work/${proj_name}.runs/impl_1/${proj_name}.bit ./work/${bitfile_name}.bit 
if [file exists ./${proj_name}.mmi] { 
  file copy ./${proj_name}.mmi ../${bitfile_name}.mmi
  file copy ./${proj_name}.mmi ./work/${bitfile_name}.mmi
  exec updatemem -meminfo ./${proj_name}.mmi -data ${lm32_wrpc_elf} -bit ./work/${proj_name}.runs/impl_1/${proj_name}.bit -proc ${lm32_wrpc_instpath} -out ../${bitfile_name}_elf.bit -force 
  file copy ../${bitfile_name}_elf.bit ./work/${bitfile_name}_elf.bit
}
if [file exists ./${proj_name}.xsa] { 
  file copy ./${proj_name}.xsa ../${bitfile_name}.xsa
  file copy ./${proj_name}.xsa ./work/${bitfile_name}.xsa
}

set syn_dir [pwd]
# Get SHA codes for spec7, wr-cores and general-cores repositories
set spec7_sha [exec git rev-parse HEAD]
cd ../../wr-cores/ ; set wr_cores_sha [exec git rev-parse HEAD]
cd ip_cores/general-cores/ ; set general_cores_sha [exec git rev-parse HEAD]
cd $syn_dir 
# write SHA codes in log a file
set git_log_fp [open ../${bitfile_name}.log w]
puts $git_log_fp "Build with following project properties:"
puts $git_log_fp "spec7_design = $spec7_design"
puts $git_log_fp "device = $device"
if [info exists pps_in] {
  puts $git_log_fp "pps_in = $pps_in"
}
puts $git_log_fp "Build was based on the following SHA codes:"
puts $git_log_fp "spec7.git           $spec7_sha"
puts $git_log_fp "wr-cores.git        $wr_cores_sha"
puts $git_log_fp "general-cores.git   $general_cores_sha"
close $git_log_fp
file copy ../${bitfile_name}.log ./work/${bitfile_name}.log
