diff --git a/scripts/Murax/arty_a7/make_bit_file.tcl b/scripts/Murax/arty_a7/make_bit_file.tcl new file mode 100644 index 0000000..a97b399 --- /dev/null +++ b/scripts/Murax/arty_a7/make_bit_file.tcl @@ -0,0 +1,50 @@ + +# Input files +set mmi_file "./soc.mmi" +set elf_file "./soc.elf" +set source_bit_file "./soc.bit" + +# Output files +set output_bit_file "./soc_latest_sw.bit" + +# Enable to turn on debug +set updatemem_debug 0 + +# Assemble bit file that can be downloaded to device directly +# Combine the original bit file, mmi file, and software elf to create the full bitstream + +# Delete target file +file delete -force $output_bit_file + +# Determine if the user has built the project and has the target source file +# If not, then use the reference bit file shipped with the project +if { ![file exists $source_bit_file] } { + puts "\n********************************************" + puts "INFO - File $source_bit_file doesn't exist as project has not been built" + puts " Using $reference_bit_file instead\n" + puts "********************************************/n" + set source_bit_file $reference_bit_file +} + +# Banner message to console as there is no output for a few seconds +puts " Running updatemem ..." + +if { $updatemem_debug } { + set error [catch {exec updatemem --debug --force --meminfo $mmi_file --data $elf_file --bit $source_bit_file --proc dummy --out $output_bit_file} result] +} else { + set error [catch {exec updatemem --force --meminfo $mmi_file --data $elf_file --bit $source_bit_file --proc dummy --out $output_bit_file} result] +} + +# Print the stdout from updatemem +puts $result + +# Updatemem returns 0 even when there is an error, so cannot trap on error. Having deleted output file to start, then +# detect if it now exists, else exit. +if { ![file exists $output_bit_file] } { + puts "ERROR - $output_bit_file not made" + return -1 +} else { + puts "\n********************************************" + puts " $output_bit_file correctly generated" + puts "********************************************\n" +} diff --git a/scripts/Murax/arty_a7/make_mcs_file.tcl b/scripts/Murax/arty_a7/make_mcs_file.tcl new file mode 100644 index 0000000..9863a2c --- /dev/null +++ b/scripts/Murax/arty_a7/make_mcs_file.tcl @@ -0,0 +1,31 @@ + +# Input file +set source_bit_file "./latest.bit" + +# Output file +set output_mcs_file "./latest.mcs" + +# Delete target file +file delete -force $output_mcs_file + +# Determine if the user has built the project and has the target source file +# If not, then use the reference bit file shipped with the project +if { ![file exists $source_bit_file] } { + puts "\n********************************************" + puts "INFO - File $source_bit_file doesn't exist as project has not been built\n" + puts "********************************************/n" + error +} + +# Create MCS file for base board QSPI flash memory +write_cfgmem -force -format MCS -size 16 -interface SPIx4 -loadbit " up 0 $source_bit_file" $output_mcs_file + +# Check MCS was correctly made +if { ![file exists $output_mcs_file] } { + puts "ERROR - $output_bit_file not made" + return -1 +} else { + puts "\n********************************************" + puts " $output_mcs_file correctly generated" + puts "********************************************\n" +} diff --git a/scripts/Murax/arty_a7/make_mmi_files.tcl b/scripts/Murax/arty_a7/make_mmi_files.tcl new file mode 100644 index 0000000..d9ecd48 --- /dev/null +++ b/scripts/Murax/arty_a7/make_mmi_files.tcl @@ -0,0 +1,6 @@ +source [file join [file dirname [file normalize [info script]]] vivado_params.tcl] + +open_project -read_only $outputdir/$projectName +open_run impl_1 +source $base/soc_mmi.tcl +puts "mmi files generated" diff --git a/scripts/Murax/arty_a7/make_vivado_project.tcl b/scripts/Murax/arty_a7/make_vivado_project.tcl new file mode 100644 index 0000000..b206ddb --- /dev/null +++ b/scripts/Murax/arty_a7/make_vivado_project.tcl @@ -0,0 +1,46 @@ +#Create output directory and clear contents +source [file join [file dirname [file normalize [info script]]] vivado_params.tcl] + +file mkdir $outputdir +set files [glob -nocomplain "$outputdir/*"] +if {[llength $files] != 0} { + puts "deleting contents of $outputdir" + file delete -force {*}[glob -directory $outputdir *]; # clear folder contents +} else { + puts "$outputdir is empty" +} + +#Create project +create_project -part $part $projectName $outputdir + +#add source files to Vivado project +#add_files -fileset sim_1 ./path/to/testbench.vhd +#add_files [glob ./path/to/sources/*.vhd] +#add_files -fileset constrs_1 ./path/to/constraint/constraint.xdc +#add_files [glob ./path/to/library/sources/*.vhd] +#set_property -library userDefined [glob ./path/to/library/sources/*.vhd] +add_files [glob $base/*.v] +add_files [glob $topv] +add_files -fileset constrs_1 $base/arty_a7.xdc + +#set top level module and update compile order +set_property top toplevel [current_fileset] +update_compile_order -fileset sources_1 +#update_compile_order -fileset sim_1 + +#launch synthesis +launch_runs synth_1 +wait_on_run synth_1 + +#Run implementation and generate bitstream +set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] +launch_runs impl_1 -to_step write_bitstream +wait_on_run impl_1 +puts "Implementation done!" + +#reports generated by default +#open_run impl_1 +#report_timing_summary -check_timing_verbose -report_unconstrained -file report_timing_summary.rpt +#report_utilization -hierarchical -file report_utilization.rpt + +#TODO: add checks about timing, DRC, CDC such that the script give clear indication if design is OK or not diff --git a/scripts/Murax/arty_a7/open_vivado_project.tcl b/scripts/Murax/arty_a7/open_vivado_project.tcl new file mode 100644 index 0000000..4120019 --- /dev/null +++ b/scripts/Murax/arty_a7/open_vivado_project.tcl @@ -0,0 +1,4 @@ +source [file join [file dirname [file normalize [info script]]] vivado_params.tcl] + +open_project -read_only $outputdir/$projectName +start_gui diff --git a/scripts/Murax/arty_a7/soc_mmi.tcl b/scripts/Murax/arty_a7/soc_mmi.tcl new file mode 100644 index 0000000..33ea686 --- /dev/null +++ b/scripts/Murax/arty_a7/soc_mmi.tcl @@ -0,0 +1,151 @@ +#script to update the init values of RAM without re-synthesis + +if {![info exists mmi_file]} { + # Set MMI output file name + set mmi_file "soc.mmi" +} +if {![info exists part]} { + set part "xc7a35ticsg324-1L" +} + +# Function to swap bits +proc swap_bits { bit } { + + if { $bit > 23 } {return [expr {24 + (31 - $bit)}]} + if { $bit > 15 } {return [expr {16 + (23 - $bit)}]} + if { $bit > 7 } {return [expr {8 + (15 - $bit)}]} + return [expr {7 - $bit}] +} + +# If run from batch file, will need to open project, then open the run +# open_run impl_1 + +# Find all the RAMs, place in a list +set rams [get_cells -hier -regexp {.*core/system_ram/.*} -filter {REF_NAME =~ RAMB36E1}] + +puts "[llength $rams] RAMs in total" +foreach m $rams {puts $m} + +set mems [dict create] +foreach m $rams { + set numbers [regexp -all -inline -- {[0-9]+} $m] + dict set mems $numbers $m +} +set keys [dict keys $mems] +#set keys [lsort -integer $keys] +set rams [] +foreach key $keys { + set m [dict get $mems $key] + puts "$key -> $m" + lappend rams $m +} + +puts "after sort:" +foreach m $rams {puts $m} +puts $rams + +if { [llength $rams] == 0 } { + puts "Error - no memories found" + return -1 +} + +if { [expr {[llength $rams] % 4}] != 0 } { + puts "Error - Number of memories not divisible by 4" + return -1 +} + +set size_bytes [expr {4096*[llength $rams]}] +puts "Instruction memory size $size_bytes" + +# Currently only support memory sizes between 16kB, (one byte per mem), and 128kB, (one bit per mem) +if { ($size_bytes < (4*4096)) || ($size_bytes > (32*4096)) } { + puts "Error - Memory size of $size_bytes out of range" + puts " Script only supports memory sizes between 16kB and 128kB" + return -1 +} + +# Create and open target mmi file +set fp [open $mmi_file {WRONLY CREAT TRUNC}] +if { $fp == 0 } { + puts "Error - Unable to open $mmi_file for writing" + return -1 +} + +# Write the file header +puts $fp "" +puts $fp "" +puts $fp " " +puts $fp " " +puts $fp " " + +# Calculate the expected number of bits per memory +set mem_bits [expr {32/[llength $rams]}] + +puts "mem_bits = $mem_bits" + +set mem_info [dict create] + +set i 0 +foreach ram $rams { + # Get the RAM location + set loc_val [get_property LOC [get_cells $ram]] + regexp -- {(RAMB36_)([0-9XY]+)} $loc_val full ram_name loc_xy + + set memi [dict create ram $ram loc $loc_xy] + + set numbers [regexp -all -inline -- {[0-9]+} $ram] + if { [llength $numbers] == 2 } { + dict lappend mem_info [lindex $numbers 0] $memi + } else { + dict lappend mem_info [expr $i/4] $memi + } + incr i +} + +set sorted_mem_info [dict create] +foreach {idx mems} $mem_info { + foreach mem [lreverse $mems] { + dict lappend sorted_mem_info $idx $mem + } +} +foreach mems $sorted_mem_info { + foreach mem $mems { + puts $mem + } +} + +set lsb 0 +set memlen [ expr 4096*8 / $mem_bits ] +foreach {idx mems} $sorted_mem_info { + puts "idx=$idx" + foreach mem $mems { + puts "mem=$mem" + set ram [dict get $mem ram] + set loc [dict get $mem loc] + set msb [expr $lsb+$mem_bits-1] + set addr_start 0 + set addr_end [expr $memlen-1] + puts "ram=$ram loc=$loc lsb=$lsb msb=$msb addr_start=$addr_start addr_end=$addr_end" + puts $fp " " + puts $fp " " + puts $fp " " + puts $fp " " + puts $fp " " + puts $fp " " + + set lsb [expr ($msb+1)%32] + } +} + +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp "" + +close $fp diff --git a/scripts/Murax/arty_a7/vivado_params.tcl b/scripts/Murax/arty_a7/vivado_params.tcl new file mode 100644 index 0000000..343058d --- /dev/null +++ b/scripts/Murax/arty_a7/vivado_params.tcl @@ -0,0 +1,5 @@ +set outputdir ./vivado_project +set part "xc7a35ticsg324-1L" +set base ".." +set projectName "fpga" +set topv "$base/../../../Murax.v" diff --git a/scripts/Murax/arty_a7/write_flash.tcl b/scripts/Murax/arty_a7/write_flash.tcl new file mode 100644 index 0000000..845bff7 --- /dev/null +++ b/scripts/Murax/arty_a7/write_flash.tcl @@ -0,0 +1,26 @@ + +open_hw +connect_hw_server +open_hw_target +current_hw_device [get_hw_devices xc7a35t_0] +refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xc7a35t_0] 0] + +create_hw_cfgmem -hw_device [lindex [get_hw_devices] 0] -mem_dev [lindex [get_cfgmem_parts {s25fl128sxxxxxx0-spi-x1_x2_x4}] 0] +set_property PROBES.FILE {} [get_hw_devices xc7a35t_0] +set_property FULL_PROBES.FILE {} [get_hw_devices xc7a35t_0] +refresh_hw_device [lindex [get_hw_devices xc7a35t_0] 0] +set_property PROGRAM.ADDRESS_RANGE {use_file} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.FILES [list "latest.mcs" ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.PRM_FILE {} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] + +if {![string equal [get_property PROGRAM.HW_CFGMEM_TYPE [lindex [get_hw_devices xc7a35t_0] 0]] [get_property MEM_TYPE [get_property CFGMEM_PART [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]]]] } { create_hw_bitstream -hw_device [lindex [get_hw_devices xc7a35t_0] 0] [get_property PROGRAM.HW_CFGMEM_BITFILE [ lindex [get_hw_devices xc7a35t_0] 0]]; program_hw_devices [lindex [get_hw_devices xc7a35t_0] 0]; }; +program_hw_cfgmem -hw_cfgmem [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] + +close_hw_target +close_hw diff --git a/scripts/Murax/arty_a7/write_fpga.tcl b/scripts/Murax/arty_a7/write_fpga.tcl new file mode 100644 index 0000000..e3214f8 --- /dev/null +++ b/scripts/Murax/arty_a7/write_fpga.tcl @@ -0,0 +1,10 @@ +open_hw +connect_hw_server +open_hw_target +current_hw_device [get_hw_devices xc7a35t_0] +refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xc7a35t_0] 0] +set_property PROBES.FILE {} [get_hw_devices xc7a35t_0] +set_property FULL_PROBES.FILE {} [get_hw_devices xc7a35t_0] +set_property PROGRAM.FILE {latest.bit} [get_hw_devices xc7a35t_0] +program_hw_devices [get_hw_devices xc7a35t_0] +disconnect_hw_server