# A template to simplify building and running examples.  This
# file is meant to be embedded in another Rakefile, which bears
# the responsibility of defining the following variables.
#
# = Required variables
#
# SIMULATOR_SOURCES::   Array of paths to (1) source files or (2)
#                       directories that contain source files
#                       which must be loaded by the simulator.
#
# SIMULATOR_ARGUMENTS:: A hash table containing keys for each simulator task
#                       (same as Rakefile task names) and values containing
#                       command-line arguments for each simulator.
#
#--
# Copyright 2006 Suraj N. Kurapati
# See the file named LICENSE for details.

require 'ruby-vpi/util'

# check for required variables
  vars = %w[SIMULATOR_SOURCES SIMULATOR_ARGUMENTS]

  unless vars.all? {|v| eval "defined? #{v}"}
    raise ArgumentError, "#{vars.join(' and ')} must be defined."
  end

# auto-detect and set default parameters
  runnerPath = caller.grep(/runner.rake/).first.rstrip_from(':')
  @target    = File.basename(runnerPath).rstrip_from('_')

  task :setup

# resolve paths to sources by searching include directories
  @sources = SIMULATOR_SOURCES.to_a.uniq
  @incdirs = @sources.select {|s| File.directory? s}
  @sources -= @incdirs

  @sources.map! do |src|
    unless File.exist? src
      @incdirs.each do |dir|
        path = File.join(dir, src)

        if File.exist? path
          src = path
          break
        end
      end
    end

    src
  end

# prepare hook for rb_load_file() in main.c
  ENV['RUBYVPI_BOOT_LOADER'] = File.join(File.dirname(__FILE__), 'runner_boot_loader.rb')
  ENV['RUBYVPI_BOOT_TARGET'] = @target

# check if the machine is 64-bit
  @archIs64 = -1.size == 8


require 'rake/clean'
require 'ruby-vpi'
require 'ruby-vpi/rake'

OBJECT_PATH = File.join(File.dirname(__FILE__), '..', '..', 'obj')
LOADER_FUNC = 'vlog_startup_routines_bootstrap'


# Returns the path to the Ruby-VPI object file for the given simulator.
def object_file_path aSimId # :nodoc:
  path = File.expand_path File.join(OBJECT_PATH, "#{aSimId}.so")

  unless File.exist? path
    raise "Object file #{path.inspect} is missing. Rebuild Ruby-VPI."
  end

  path
end

# Returns an array of include-directory options.
def expand_incdir_options aSimId # :nodoc:
  prefix = aSimId == :ivl ? '-I' : '+incdir+'
  @incdirs.map {|i| prefix + i}
end


desc "Show a list of available tasks."
task :default do
  Rake.application.options.show_task_pattern = //
  Rake.application.display_tasks_and_comments
end


desc "Simulate with #{RubyVPI::SIMULATORS[:cver].name}."
task :cver => :setup do
  sh 'cver',
    "+loadvpi=#{object_file_path(:cver)}:#{LOADER_FUNC}",
    SIMULATOR_ARGUMENTS[:cver],
    expand_incdir_options(:cver),
    @sources
end

CLOBBER.include 'verilog.log'


desc "Simulate with #{RubyVPI::SIMULATORS[:ivl].name}."
task :ivl => :setup do
  cp object_file_path(:ivl), 'ruby-vpi.vpi'
  sh %w[iverilog -mruby-vpi],
    SIMULATOR_ARGUMENTS[:ivl],
    expand_incdir_options(:ivl),
    @sources
  sh 'vvp -M. a.out'
end

CLEAN.include 'ruby-vpi.vpi', 'a.out'


desc "Simulate with #{RubyVPI::SIMULATORS[:vcs].name}."
task :vcs => :setup do
  sh %w[vcs -R +v2k +vpi +cli],
    '-P', File.join(File.dirname(__FILE__), 'pli.tab'),
    '-load', "#{object_file_path(:vcs)}:#{LOADER_FUNC}",
    ('-full64' if @archIs64),
    SIMULATOR_ARGUMENTS[:vcs],
    expand_incdir_options(:vcs),
    @sources
end

CLEAN.include 'csrc', 'simv*'


desc "Simulate with #{RubyVPI::SIMULATORS[:vsim].name}."
task :vsim => :setup do
  sh 'vlib work'
  sh 'vlog', expand_incdir_options(:vsim), @sources
  sh %w[vsim -c],
    '-do', 'run -all; exit',
    '-pli', object_file_path(:vsim),
    SIMULATOR_ARGUMENTS[:vsim],
    @target
end

CLEAN.include 'work', 'vsim.wlf'
CLOBBER.include 'transcript'


desc "Simulate with #{RubyVPI::SIMULATORS[:ncsim].name}."
task :ncsim => :setup do
  sh %w[ncverilog +access+rwc +plinowarn],
    "+loadvpi=#{object_file_path(:ncsim)}:#{LOADER_FUNC}",
    ('+nc64bit' if @archIs64),
    SIMULATOR_ARGUMENTS[:ncsim],
    expand_incdir_options(:ncsim),
    @sources
end

CLEAN.include 'INCA_libs'
CLOBBER.include 'ncverilog.log', 'ncsim.log'