Commit ff11ebb6 authored by Théotime BOLLENGIER's avatar Théotime BOLLENGIER
Browse files

video

parent aa37b811
......@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
'lib/argen/constraint_io_locations.rb',
'lib/argen/graphics/place_and_route_viewer.rb',
'lib/argen/graphics/resources_to_svg.rb',
'lib/argen/graphics/state_viewer.rb',
'lib/argen/hdl_arch_writer.rb',
'lib/argen/high_level_arch_generator/argen_arch_writer.rb',
'lib/argen/high_level_arch_generator/vpr_architecture_writer.rb',
......@@ -63,6 +64,8 @@ Gem::Specification.new do |s|
'share/bin/resources_to_svg.rb',
'share/bin/resource_usage_analyzer.rb',
'share/bin/rewrite_placement_with_IO_locations.rb',
'share/bin/state_viewer.rb',
'share/bin/vcd_to_video.rb',
'share/bin/VirtBitgen.rb',
'share/bin/VirtSta.rb',
'share/bin/vpr_par_reader.rb',
......
......@@ -19,7 +19,7 @@ $bin_path = File.expand_path('../../share/bin', __FILE__) + '/'
def help_str
str = $description_string
str += "\nUsage: #{File.basename($0)} <command> <cmd_args> ...\nCommand must be one of:\n"
str += Dir[$bin_path + '*.rb'].collect{|n| " #{File.basename(n, '.rb')}"}.sort.join("\n")
str += Dir[$bin_path + '*.rb'].collect{|n| " #{File.basename(n, '.rb')}"}.sort{|a, b| a.downcase <=> b.downcase}.join("\n")
str += "\n\nTo get help on a specific command: #{File.basename($0)} <command> --help"
str
end
......@@ -44,9 +44,8 @@ end
cmd = "ruby #{exec_path}"
if ARGV.length > 1 then
cmd += ' '
cmd += ARGV[1..-1].join(' ')
Process.exec('ruby', exec_path, *ARGV[1..-1])
else
Process.exec('ruby', exec_path)
end
Process::exec cmd
This diff is collapsed.
require 'optparse'
require_relative '../../lib/argen/version.rb'
require_relative '../../lib/argen/par_loader.rb'
require_relative '../../lib/argen/graphics/state_viewer.rb'
$copyright = "Copyright (C) 2017-2019 ENSTA Bretagne"
$authors = [
["Théotime Bollengier", "<theotime.bollengier@ensta-bretagne.fr>"]
]
$program_name = File.basename(__FILE__, '.*')
$program_version = "1.0"
$description = "This program generates a graphical representation of the state of a placed and routed netlist on its target architecture at a given clock cycle from a simulation."
$description_string = "\nWelcome to #{$program_name} #{$program_version}, a component of the ArGen framework.\n#{$description}\n#{$copyright}\n#{$authors.collect.with_index{|a, i| "#{(i == 0) ? "Author#{($authors.length > 1) ? 's':''}: " : " #{($authors.length > 1) ? ' ':''} "}#{a.first} #{a.last}\n"}.join}"
STDOUT.sync = true
STDERR.sync = true
options = {}
optparse = OptionParser.new do |opts|
opts.banner = "Usage: #{File.basename($0)} [options]"
options[:par] = nil
opts.on('-p', '--par FILE', 'Placement and routing input file') do |s|
options[:par] = s
end
options[:trcnav] = nil
opts.on('-t', '--traces FILE', 'TraceNav dump input file') do |s|
options[:trcnav] = s
end
options[:basename] = nil
opts.on('-b', '--basename FILE', "Base name of the output images") do |s|
options[:basename] = s
end
options[:path] = nil
opts.on('--overlay_IP_path PATH', "Path of the overlay IP module from the top_level") do |s|
options[:path] = s
end
options[:offset] = 0
opts.on('--offset NUM', "Do not generate the first NUM images") do |s|
options[:offset] = s.to_i
end
options[:jump] = 1
opts.on('--jump NUM', "Generate only every NUM images") do |s|
options[:jump] = s.to_i
end
options[:format] = :svgz
opts.on('-f', '--format FORMAT', "Output image format. Can be either 'svg', 'svgz' or 'png'") do |s|
options[:format] = s.downcase.to_sym
end
options[:negate] = false
opts.on('-d', '--dark', 'Use dark color scheme') do
options[:negate] = true
end
options[:nonum] = false
opts.on('-n', '--no_num', "Don't draw numbers (such as pin numbers)") do
options[:nonum] = true
end
options[:width] = 1920
opts.on('-W', '--max_width INTEGER', 'Maximum width (for PNG)') do |n|
options[:width] = n.to_i
end
options[:height] = 1080
opts.on('-H', '--max_height INTEGER', 'Maximum height (for PNG)') do |n|
options[:height] = n.to_i
end
options[:multi] = nil
opts.on('-m', '--multithread NBTHREADS', "Use multiple threads") do |s|
options[:multi] = s.to_i.abs
end
options[:startTime] = nil
opts.on('--start_time FLOAT', "Start generating images from FLOAT s simulation time") do |s|
options[:startTime] = s.to_f.abs
end
options[:stopTime] = nil
opts.on('--stop_time FLOAT', "Stop generating images from FLOAT s simulation time") do |s|
options[:stopTime] = s.to_f.abs
end
options[:quiet] = false
opts.on('-q', '--quiet', 'Be quiet') do
options[:quiet] = true
end
opts.on('-h', '--help', 'Display this help') do
puts opts
puts $description_string
exit
end
end
begin
optparse.parse!
rescue Exception => e
if e.class == SystemExit then
exit 0
else
abort e.message + "\n" + optparse.to_s
end
end
STDERR.puts "WARNING: Unused commandline arguments: #{ARGV.join(' ')}" unless (ARGV.empty? or (ARGV.length == 1 and ARGV.first == "FoRvIdEo"))
for_video = ARGV.include?("FoRvIdEo")
if options[:par].nil? then
STDERR.puts "ERROR: you must specify an ArGen placement and routing file."
abort optparse.to_s
end
if options[:trcnav].nil? then
STDERR.puts "ERROR: you must specify a TraceNav dump file."
abort optparse.to_s
end
if options[:basename].nil? then
STDERR.puts "ERROR: you must specify the basename of the output images."
abort optparse.to_s
end
if options[:path].nil? then
STDERR.puts "ERROR: you must specify the path of the overlay IP in the module hierarchy."
abort optparse.to_s
end
if options[:format] then
if options[:format] != :svg and options[:format] != :svgz and options[:format] != :png then
STDERR.puts "ERROR: Format must be either svg, svgz or png."
abort optparse.to_s
end
end
if options[:offset] < 0 then
STDERR.puts "ERROR: Offset must be positive."
abort optparse.to_s
end
if options[:jump] < 1 then
STDERR.puts "ERROR: Offset must be strictly positive."
abort optparse.to_s
end
if options[:width] < 1 then
STDERR.puts "ERROR: Maximum width must be strictly positive."
abort optparse.to_s
end
options[:width] = 3840 if options[:width] > 3840
if options[:height] < 1 then
STDERR.puts "ERROR: Maximum height must be strictly positive."
abort optparse.to_s
end
options[:height] = 3840 if options[:height] > 3840
if options[:multi] then
nbth = options[:multi]
if nbth < 2 then
STDERR.puts "ERROR: number of threads must be greater than 1."
abort optparse.to_s
end
cmd = "#{$0} --par '#{options[:par]}' --traces '#{options[:trcnav]}' --basename '#{options[:basename]}' --overlay_IP_path '#{options[:path]}' --format #{options[:format].to_s}"
cmd += " --dark" if options[:negate]
cmd += " --no_num" if options[:nonum]
cmd += " --max_width #{options[:width]}" if options[:format] == :png
cmd += " --max_height #{options[:height]}" if options[:format] == :png
cmd += " --start_time #{options[:startTime]}" if options[:startTime]
cmd += " --stop_time #{options[:stopTime]}" if options[:stopTime]
cmd += " --quiet"
cmd += " --jump #{nbth}"
threads = nbth.times.collect do |i|
Thread.new { system(cmd + " --offset #{i}") }
end
threads.each { |thr| thr.join }
exit
end
arch = ArGen::Architecture::Arch::read_par(options[:par])
arch.write_architecture_resources_state_from_simulation_trace_dump(
trcnav: options[:trcnav],
basename: options[:basename],
path: options[:path],
offset: options[:offset],
jump: options[:jump],
format: options[:format],
negate: options[:negate],
nonum: options[:nonum],
width: options[:width],
height: options[:height],
startTime: options[:startTime],
stopTime: options[:stopTime],
quiet: options[:quiet],
for_video: for_video
)
require 'optparse'
require 'tmpdir'
require 'thread'
require 'open3'
require_relative '../../lib/argen/version.rb'
$copyright = "Copyright (C) 2017-2019 ENSTA Bretagne"
$authors = [
["Théotime Bollengier", "<theotime.bollengier@ensta-bretagne.fr>"]
]
$program_name = File.basename(__FILE__, '.*')
$program_version = ArGen::VERSION
$description = "This program generates a video from the simulation output (VCD) of an overlay running a netlist."
$description_string = "\nWelcome to #{$program_name} #{$program_version}, a component of the ArGen framework.\n#{$description}\n#{$copyright}\n#{$authors.collect.with_index{|a, i| "#{(i == 0) ? "Author#{($authors.length > 1) ? 's':''}: " : " #{($authors.length > 1) ? ' ':''} "}#{a.first} #{a.last}\n"}.join}"
options = {}
optparse = OptionParser.new do |opts|
opts.banner = "Usage: #{File.basename($0)} [options]"
options[:par] = nil
opts.on('-p', '--par FILE', 'Placement and routing input file') do |s|
options[:par] = s
end
options[:trcnav] = nil
opts.on('-v', '--vcd FILE', 'Simulation VCD dump input file') do |s|
options[:trcnav] = s
end
options[:output] = nil
opts.on('-o', '--output FILE', "Name of the output video") do |s|
options[:output] = s
end
options[:path] = nil
opts.on('--overlay_IP_path PATH', "Path of the overlay IP module from the top_level") do |s|
options[:path] = s
end
options[:negate] = false
opts.on('-d', '--dark', 'Use dark color scheme') do
options[:negate] = true
end
options[:nonum] = false
opts.on('-n', '--no_num', "Don't draw numbers (such as pin numbers)") do
options[:nonum] = true
end
options[:width] = 1920
opts.on('-W', '--max_width INTEGER', 'Maximum width (for PNG)') do |n|
options[:width] = n.to_i
end
options[:height] = 1080
opts.on('-H', '--max_height INTEGER', 'Maximum height (for PNG)') do |n|
options[:height] = n.to_i
end
options[:multi] = 1
opts.on('-m', '--multithread NBTHREADS', "Use multiple threads") do |s|
options[:multi] = s.to_i.abs
end
options[:startTime] = nil
opts.on('--start_time FLOAT', "Start generating images from FLOAT s simulation time") do |s|
options[:startTime] = s.to_f.abs
end
options[:stopTime] = nil
opts.on('--stop_time FLOAT', "Stop generating images from FLOAT s simulation time") do |s|
options[:stopTime] = s.to_f.abs
end
options[:framerate] = 18
opts.on('-r', '--framerate INT', "Video frames per second.") do |s|
options[:framerate] = s.to_i.abs
end
options[:tracenavPath] = 'tracenav'
opts.on('--tracenav_path STRING', "TraceNav executable path.") do |s|
options[:tracenavPath] = s
end
options[:stateviewerPath] = 'argen state_viewer'
opts.on('--state_viewer_path STRING', "state_viewer executable path.") do |s|
options[:stateviewerPath] = s
end
opts.on('-h', '--help', 'Display this help') do
puts opts
puts $description_string
exit
end
end
begin
optparse.parse!
rescue Exception => e
if e.class == SystemExit then
exit 0
else
abort e.message + "\n" + optparse.to_s
end
end
STDERR.puts "WARNING: Unused commandline arguments: #{ARGV.join(' ')}" unless ARGV.empty?
if options[:par].nil? then
STDERR.puts "ERROR: you must specify an ArGen placement and routing file."
abort optparse.to_s
end
if options[:trcnav].nil? then
STDERR.puts "ERROR: you must VCD dump input file."
abort optparse.to_s
end
if options[:output].nil? then
STDERR.puts "ERROR: you must specify the video output name."
abort optparse.to_s
end
if options[:path].nil? then
STDERR.puts "ERROR: you must specify the path of the overlay IP in the module hierarchy."
abort optparse.to_s
end
if options[:width] < 1 then
STDERR.puts "ERROR: Maximum width must be strictly positive."
abort optparse.to_s
end
options[:width] = 3840 if options[:width] > 3840
if options[:height] < 1 then
STDERR.puts "ERROR: Maximum height must be strictly positive."
abort optparse.to_s
end
options[:height] = 3840 if options[:height] > 3840
options[:framerate] = 1 if options[:framerate] < 1
options[:framerate] = 60 if options[:framerate] > 60
if options[:multi] < 1 then
options[:multi] = 1
end
nbth = options[:multi]
STDOUT.sync = true
STDERR.sync = true
Dir.mktmpdir do |dir|
puts "Temporary directory: \"#{dir}\""
trcnaveFile = File.join(dir, 'dump.trcnav')
abort "Cannot make TraceNav dump file" unless system("#{options[:tracenavPath]} dump '#{options[:trcnav]}' '#{trcnaveFile}'")
queue = Queue.new
cmd = options[:stateviewerPath]
cmd += " --par '#{options[:par]}'"
cmd += " --traces '#{trcnaveFile}'"
cmd += " --basename #{File.join(dir, 'img')}"
cmd += " --overlay_IP_path '#{options[:path]}'"
cmd += " --format png"
cmd += " --dark" if options[:negate]
cmd += " --no_num" if options[:nonum]
cmd += " --max_width #{options[:width]}"
cmd += " --max_height #{options[:height]}"
cmd += " --start_time #{options[:startTime]}" if options[:startTime]
cmd += " --stop_time #{options[:stopTime]}" if options[:stopTime]
cmd += " --quiet"
cmd += " --jump #{nbth}"
cmd += " FoRvIdEo"
threads = nbth.times.collect do |i|
Thread.new do
Open3.popen2(cmd + " --offset #{i}") do |stdin, stdout, wait_thr|
stdin.close
until stdout.eof do
l = stdout.gets
queue.push(l) if l =~ /^.*img_\d{8,8}\.png$/
end
end
queue << 'END'
end
end
ffmpeg_cmd = "ffmpeg -y -framerate #{options[:framerate]} -f image2pipe -i - -r:v 30 -c:v libx264 -preset fast -crf 18 -pix_fmt yuv420p #{options[:output]}"
puts '-'*ffmpeg_cmd.length
puts ffmpeg_cmd
puts '-'*ffmpeg_cmd.length
#ffmpeg_stdin, ffmpeg_wait_threads = Open3.pipeline_w(ffmpeg_cmd)
ffmpeg_stdin, ffmpeg_stdout, ffmpeg_wait_threads = Open3.pipeline_rw(ffmpeg_cmd + " 2>&1")
threads << ffmpeg_wait_threads.first
name_buffer = []
last_processed_img_num = -1
terminated_threads = 0
loop do
begin
print ffmpeg_stdout.read_nonblock(4096)
rescue
end
deq = queue.pop().chomp
if deq =~ /^END$/ then
terminated_threads += 1
break if terminated_threads == nbth
end
next unless deq =~ /\d{8,8}\.png/
name_buffer << deq
loop do
break if name_buffer.empty?
name_buffer.sort!
first = name_buffer.first
fi = first.match(/.*?(\d{8,8})\.png$/)[1].to_i
break if fi != last_processed_img_num + 1
first = name_buffer.shift
ffmpeg_stdin.write(File.binread(first))
File.unlink(first)
last_processed_img_num += 1
end
end
ffmpeg_stdin.close
## still read ffmpeg output ##
threads.each { |thr| thr.join }
queue.close
end
puts "Video writen to file \"#{options[:output]}\"."
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment