#-----------------------------------------------------------------------------
# Title      : Vidado Generate mmi File
#-----------------------------------------------------------------------------
# File       : viv_generate_bd_mmi.tcl
# Author     : Peter Jansweijer <peterj@nikhef.nl>
# Company    : Nikhef
# Created    : 2018-01-24
# Last update: 2022-03-22
# Platform   : FPGA-generics
# Standard   : VHDL
#-----------------------------------------------------------------------------
# Description:
#
# Generates a Memory Mapping Information (MMI) file
#-----------------------------------------------------------------------------
#
# 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
#
#-----------------------------------------------------------------------------

set BB FALSE

set mmi_file ${proj_name}.mmi

set fn $bmm_file
set mmi_fn $mmi_file
puts "INFO: Creating file $mmi_fn"		
set fileID [open $fn r]

if [catch {open $mmi_fn w} fileID_mmi] {
	puts "ERROR: Could not open file $mmi_fn"
	close $fileID
	exit
}

puts $fileID_mmi "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
puts $fileID_mmi "<MemInfo Version=\"1\" Minor=\"5\">"

while {[gets $fileID line] >= 0 } {	
  # Remove any white spaces
  set line [string trimleft $line]
  
  if {[scan $line "ADDRESS_SPACE %s %s \[%x:%x\]" name mem_type a_begin a_end] == 4} {
    puts $fileID_mmi "  <Processor Endianness=\"Little\" InstPath=\"${name}\">"
    puts $fileID_mmi "    <AddressSpace Name=\"${name}\" Begin=\"${a_begin}\" End=\"${a_end}\">"
	} else {
		#puts "ERROR: Script not expecting this input. Please contact Xilinx"
  }

  if {[scan $line "ADDRESS_RANGE %s" ram_type] == 1} {
    # updatemem gives error on RAMB32.
    # Overrule and set ram_type to RAMB36.
    set ram_type "RAMB36"
    continue
	} else {
		#puts "ERROR: Script not expecting this input. Please contact Xilinx"
  }
  
  if {[string match "*END_BUS_BLOCK*" $line]} {
    set BB FALSE
    puts $fileID_mmi "      </BusBlock>"
	puts $fileID_mmi "    </AddressSpace>"
    puts $fileID_mmi "  </Processor>"
	} elseif {[string match "*BUS_BLOCK*" $line]} {
		set BB TRUE
    puts $fileID_mmi "      <BusBlock>"
	}

	if { $BB eq "TRUE" } {
		if {[scan $line "%s \[%d:%d\] \[%d:%d\]" inst msb lsb a_start a_stop] == 5} {
			set BRAM_site [get_property SITE [get_cells $inst]]
			set expression [regexp {_(.*)} $BRAM_site match bmm_string]
			#puts "INFO: Located BRAM at site $BRAM_site"
      puts $fileID_mmi "        <BitLane MemType=\"${ram_type}\" Placement=\"${bmm_string}\">"
      puts $fileID_mmi "          <DataWidth MSB=\"${msb}\" LSB=\"${lsb}\"/>"
      puts $fileID_mmi "          <AddressRange Begin=\"${a_start}\" End=\"${a_stop}\"/>"
      puts $fileID_mmi "          <Parity ON=\"false\" NumBits=\"0\"/>"
      puts $fileID_mmi "        </BitLane>"
		} else {
		#puts "ERROR: Script not expecting this input. Please contact Xilinx"
		}
  }
}

puts $fileID_mmi "  <Config>"
# Important! Option Name must be "Part", otherwise update_mem fails:
#    ERROR: [Updatemem 57-44]  device is not supported by update_mem.
puts $fileID_mmi "    <Option Name=\"Part\" Val=\"${device}\"/>"
puts $fileID_mmi "  </Config>"
# Important! DRC section must be present, otherwise update_mem fails:
#    Unknown exception.
puts $fileID_mmi "  <DRC>"
puts $fileID_mmi "    <Rule Name=\"RDADDRCHANGE\" Val=\"false\"/>"
puts $fileID_mmi "  </DRC>"
puts $fileID_mmi "</MemInfo>"

close $fileID_mmi
close $fileID