1

调用vsim命令时,如何让 ModelSim 自动使用顶层 VHDL 实体(或多个实体)?我正在编写一个用于运行 VHDL 模拟的通用脚本。

目前我正在做以下编译和模拟:

vcom design.vhd testbench.vhd
vsim -c -do "onElabError resume; run -all; exit" MY_TB

我怎样才能让 ModelSimMY_TB在不明确指定的情况下自动模拟。

使用 Verilog 可以自动使用顶级模块:

vlog -writetoplevels my.tops design.v testbench.v
vsim -c -do "onElabError resume; run -all; exit" -f my.tops
4

1 回答 1

1

我的方法是在 Ruby 中创建一个脚本。很容易找到实体/架构名称,然后调用 Modelsim。解决方案的概要是:

  1. 打开 VHDL 文件:
    file_contents = File.read(file_name)

  2. 使用正则表达式查找实体和架构名称:
    match = file_contents.match(/entity (.*) is/)
    entity = match && match[1]
    match = file_contents.match(/architecture (.*) of/)
    architecture = match && match[1]

  3. 在命令行模式下调用 Modelsim:
    vsim -do {run -all; quit} -lib /temp/work -c entity_name(architecture_name)

我在下面包含了我的整个脚本以供参考。我认为它的亮点是:

  • vhdl -m→ 通过编译目录中的所有 VHDL 文件来“制作”项目
  • vhdl -f texttext在 VHDL 文件中查找
  • vhdl -s filename→ 模拟filename

    # vhdl.rb: Swiss army knife for VHDL-related tasks.
    #   vhdl --compile file_name     # Compile file with ModelSim
    #   vhdl --simulate file_name    # Simulate file with ModelSim
    #   vhdl --find text             # Find text in VHDL source files
    #   vhdl --make dir              # Compile all files in dir
    
    require 'optparse'
    require 'pathname'
    
    begin
      gem 'colorize' # gem install colorize
      require 'colorize'
    rescue Gem::LoadError
      puts "Gem 'colorize' is not installed. You can install it by typing:\ngem install colorize"
    end
    
    WORK = Pathname.new("/temp/work")
    
    def ensure_library_work_exists
      if WORK.exist?
        puts "Found library work at #{WORK.expand_path}"
      else
        puts "Creating library work at #{WORK.expand_path}..."
        system('mkdir \temp\work')
        system('vlib /temp/work')
      end
    end 
    
    def compile(file_name)
      ensure_library_work_exists
      puts "Compiling #{file_name}..."
      puts cmd_line = "vcom -2008 -work #{WORK} #{file_name}"
      system(cmd_line)
    end
    
    def simulate(file_name)
      ensure_library_work_exists
      puts "Simulating #{file_name}..."
      compile(file_name)
      entity, architecture = find_entity_architecture(file_name)
      if entity && architecture
        cmd_line = "vsim -lib #{WORK} -c #{$entity || entity}(#{$architecture || architecture}) -do \"run -all; quit\""
        system(cmd_line)
      end 
    end
    
    def find_entity_architecture(file_name)
      file_contents = File.read(file_name)
    
      match = file_contents.match(/entity (.*) is/)
      entity = match && match[1]
    
      match = file_contents.match(/architecture (.*) of/)
      architecture = match && match[1]
    
      [ entity, architecture ]
    end
    
    def find_text(text)
      puts cmd_line = "findstr /sni /C:\"#{text}\" *.vhd *.vhdl"
      system(cmd_line)
    end
    
    $before_context = 1
    $after_context = 3
    
    def find_filenames(path)
      filenames = Dir["#{path}/**/*.vhd"]
      puts "Found #{filenames.count} VHDL files"
      filenames
    end
    
    def grep_text(text)
      filenames = find_filenames(".")
      filenames.each do |filename|
        output = `grep #{text} #{filename} --recursive --line-number --before-context=#{$before_context} --after-context=#{$after_context}`
        last_output_was_blank = true
        if output.empty?
          print ".".green
          last_output_was_blank = true
        else
          puts() if last_output_was_blank
          puts filename.green, output
          last_output_was_blank = false
        end
      end
    end
    
    def compile_vhdl_file(file_name)
      vcom_output = `vcom -2008 -work #{WORK} #{file_name}`
      if vcom_output.match(/\*\* Error/)
        error_message = vcom_output[/(\*\* Error.*$)/m]
        raise error_message
      end
      puts vcom_output
    end
    
    def make(path)
      ensure_library_work_exists
      filenames = Dir["#{path}/**/*.vhd"]
      puts "Found #{filenames.count} VHDL files:"
      puts filenames.join(" ").green
    
      pass_number = 0  
      failed_filenames = []
      begin
        pending_files_count = filenames.count - failed_filenames.count
        puts ">>> Starting pass #{pass_number} -- pending #{pending_files_count}, failed #{failed_filenames.count}".yellow 
        previously_failed_filenames = failed_filenames.dup
        failed_filenames.clear
        filenames.each do |filename|
          begin
            compile_vhdl_file(filename)
          rescue
            puts "#{$!}".red
            failed_filenames << filename
          end
        end
        pass_number += 1
      end while failed_filenames.any? and (failed_filenames != previously_failed_filenames)
    
      if failed_filenames.any?
        puts "*** Error: Failed to compile:".red
        puts failed_filenames.join("\n").red
        exit
      end
    end
    
    OptionParser.new do |o|
      o.on('-e', '--ent entity_name') { |entity| $entity = entity }
      o.on('-a', '--arch architecture_name') { |architecture| $architecture = architecture }
      o.on('-c', '--compile file') { |file| compile(file) }
      o.on('-s', '--simulate file') { |file| simulate(file) }
      o.on('-f', '--find text') { |text| find_text(text) }
      o.on('-b', '--before-context before_context') { |lines_count| $before_context = lines_count }
      o.on('-t', '--after-context after_context') { |lines_count| $after_context = lines_count }
      o.on('-g', '--grep text') { |text| grep_text(text) }
      o.on('-m', '--make [dir]') { |dir| make(dir || '.') }
      o.parse!
    end
    
于 2014-01-07T00:03:52.203 回答