###############################################################################
# mem2bram.tcl      15-Dec-2017
# $1	The first paramter is the filename to be used for input and output

# The names of the input MEM file and the output bram file:
puts "MEM input file name = [set mem_file "$1.mem"]"
puts "BRAM output file name = [set bram_file "$1.bram"]"

# The format used by the White Rabbit community (memory_loader_pkg.vhd)
# 32 bit binary data, one address per line

puts "BRAM file word length = [set wordlength 32] bits"
puts "DPRAM_Size = [set dpram_size [expr {131072/4}]], 32 bit words"

###############################################################################

set addr_ptr 0

if {[file exists $mem_file]} {
  set mem_fileptr [open $mem_file]
  set bram_fileptr [open $bram_file w]
  set lineCount 0
	while {[gets $mem_fileptr line] >= 0} {
		set lineElements [llength $line]
		# Skip empty and comment lines (preceeded by "//")
    if { $lineElements != 0 && [lindex $line 0] != "//"} {
      for {set x 0} {$x < $lineElements} {incr x} { 
        set lineElem [lindex $line $x]
        
        # Addresses are preceeded with a "@" character
        if { [string index $lineElem 0] == "@"} {
          set addr [scan $lineElem "@%x"]
          # If the BRAM file address pointer did not yet reach the addresses value
          # in the MEM file yhen fill the BRAM file with "0" until the BRAM file
          # address pointer is lined up.
          while {$addr_ptr < $addr} {
            set bramline [format "%032b" 0]
            puts $bram_fileptr $bramline
            incr addr_ptr
          }
        } else {
          # Scan a byte from the MEM file
          # every modulo wordlength/8 bytes a new address is written
          if { $x % int($wordlength/8) == 0} {
            set bramline ""
            }
          append bramline [format "%08b" [scan $lineElem "%x"]]
          
          # If this is the last line element then...
          if { $x == $lineElements - 1} {
            # check whether all bytes were read from the BRAM line
            # i.e. the byte pointer points to the last byte of the word
            if { $x % int($wordlength/8) != int($wordlength/8)- 1} {
              puts $bram_fileptr "Warning: word length and bytes per line ($lineElements) are inconsistent!"
              puts "Warning: word length and bytes per line ($lineElements) are inconsistent!"
            }
          }
          # when all bytes are scanned then write them to file
          if { $x % int($wordlength/8) == int($wordlength/8)- 1} {
            puts $bram_fileptr $bramline
            incr addr_ptr
          }
        }
      }      
   	}
  }
  # Append the loader file with zeros until the full dpram_size is filled
  while {$addr_ptr < $dpram_size} {
    set bramline [format "%032b" 0]
    puts $bram_fileptr $bramline
    incr addr_ptr
  }

  close $mem_fileptr
  close $bram_fileptr
} else {
    puts "WARNING $mem_file not found..."
}

###############################################################################

