module OrigenTesters
module SmartestBasedTester
module SMT8
# This currently defines what subdirectory of the pattern output directory that
# patterns will be output to
def subdirectory
File.join(package_namespace, 'patterns')
end
# An internal method called by Origen to create the pattern header
def pattern_header(options = {})
options = {
}.merge(options)
@program_lines = []
@program_action_lines = []
if zip_patterns
@program_lines << ''
@program_lines << ''
end
@program_lines << ' '
pin_list = ordered_pins.map do |p|
if Origen.app.pin_pattern_order.include?(p.id)
# specified name overrides pin name
if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
p.id.to_s # groups or aliases can be lower case
else
p.id.to_s.upcase # pins must be uppercase
end
else
if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
p.name.to_s # groups or aliases can be lower case
else
p.name.to_s.upcase # pins must be uppercase
end
end
end.join(',')
@program_lines << " "
end
# An internal method called by Origen to generate the pattern footer
def pattern_footer(options = {})
options = {
end_in_ka: false
}.merge(options)
if options[:end_in_ka]
Origen.log.warning '93K keep alive not yet implemented!'
ss 'WARNING: 93K keep alive not yet implemented!'
end
@program_footer_lines = []
@program_footer_lines << '' if zip_patterns
end
# @api private
def open_and_write_pattern(filename)
pat_name = Pathname.new(filename).basename.to_s
@gen_vec = 0
@vector_number = 0
@vector_lines = []
@comment_lines = []
# @program_lines was already created with the pattern_header
yield
write_gen_vec
@program_lines << ' '
if zip_patterns
tmp_dir = filename.gsub('.', '_')
FileUtils.mkdir_p(tmp_dir)
program_file = File.join(tmp_dir, 'Program.sprg')
vector_file = File.join(tmp_dir, 'Vectors.vec')
comments_file = File.join(tmp_dir, 'Comments.cmt')
File.open(program_file, 'w') do |f|
(@program_lines + @program_action_lines + @program_footer_lines).each do |line|
f.puts line
end
end
File.open(vector_file, 'w') { |f| @vector_lines.each { |l| f.puts l } }
File.open(comments_file, 'w') { |f| @comment_lines.each { |l| f.puts l } }
Dir.chdir tmp_dir do
`zip #{pat_name} Program.sprg Vectors.vec Comments.cmt`
FileUtils.mv pat_name, filename
end
else
File.open filename, 'w' do |f|
f.puts ''
f.puts ' '
(@program_lines + @program_action_lines + @program_footer_lines).each do |line|
f.puts ' ' + line
end
f.puts ' '
f.puts ' '
@vector_lines.each { |l| f.puts ' ' + l }
f.puts ' '
f.puts ' '
@comment_lines.each { |l| f.puts ' ' + l }
f.puts ' '
f.puts ''
end
end
ensure
FileUtils.rm_rf(tmp_dir) if zip_patterns && File.exist?(tmp_dir)
end
# @api private
#
# The SMT8 microcode is implemented as a post conversion of the SMT7 microcode, rather than
# generating SMT8 microcode originally.
# This is generally an easier implementation and since they both run on the same h/ware there
# should always be a 1:1 feature mapping between the 2 systems.
def track_and_format_comment(comment)
if comment =~ /^SQPG/
if comment =~ /^SQPG PADDING/
# A gen vec should not be used for MRPT vectors, the padding instruction marks the end of them
@gen_vec = 0
else
write_gen_vec
if comment =~ /^SQPG JSUB ([^;]+);/
@program_lines << " "
elsif comment =~ /^SQPG MACT (\d+);/
@program_lines << " "
elsif comment =~ /^SQPG MRPT (\d+);/
@program_lines << " "
elsif comment =~ /^SQPG LBGN (\d+);/
@program_lines << " "
elsif comment =~ /^SQPG LEND;/
@program_lines << " "
elsif comment =~ /^SQPG RETC (\d) (\d);/
@program_lines << " "
@program_lines << " "
@program_lines << " "
@program_lines << ' '
else
Origen.log.warning "This SMT7 microcode was not converted to SMT8: #{comment}"
end
end
end
end
# This is an internal method use by Origen which returns a fully formatted vector
# You can override this if you wish to change the output formatting at vector level
def format_vector(vec)
has_microcode = vec.microcode && !vec.microcode.empty?
has_repeat = vec.repeat && vec.repeat > 1
if has_microcode || has_repeat
# Close out current gen_vec group
write_gen_vec
if has_repeat
@program_lines << " "
@program_lines << " "
@program_lines << ' '
@gen_vec -= 1
end
if has_microcode
puts vec.microcode
end
end
unless Origen.mode.simulation? || !inline_comments || $_testers_no_inline_comments
header_comments = []
repeat_comment = ''
vec.comments.each_with_index do |comment, i|
if comment =~ /^#/
if comment =~ /^#(R\d+)$/
repeat_comment = Regexp.last_match(1) + ' '
# Throw away the ############# headers and footers
elsif comment !~ /^# ####################/
comment = comment.strip.sub(/^# (## )?/, '')
if comment == ''
# Throw away empty lines at the start/end, but preserve them in the middle
unless header_comments.empty? || i == vec.comments.size - 1
header_comments << comment
end
else
header_comments << comment
end
end
end
end
if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
comment = "#{vec.number}:#{vec.cycle}"
comment += ': ' if !header_comments.empty? || !vec.inline_comment.empty?
else
comment = ''
end
# comment += header_comments.join("\cm") unless header_comments.empty?
# Seems that SMT8 does not support the above newline char, so identify split lines with something else
comment += header_comments.join('----') unless header_comments.empty?
unless vec.inline_comment.empty?
comment += "\cm" unless header_comments.empty?
comment += "(#{vec.inline_comment})"
end
c = "#{repeat_comment}#{comment}"
@comment_lines << "#{@vector_number} #{c}"[0, 3000] unless c.empty?
end
if vec.pin_vals
@vector_lines << vec.pin_vals.gsub(' ', '')
@vector_number += 1
@gen_vec += 1
end
end
# @api private
def write_gen_vec
if @gen_vec > 0
@program_lines << " "
@gen_vec = 0
end
end
end
end
end