Class: Origen::Tester::Ultraflex::Parser::Descriptions

Inherits:
Object
  • Object
show all
Defined in:
lib/origen/tester/ultraflex/parser/descriptions.rb

Overview

Extracts embedded test and flow descriptions (comments) from test program source files

Constant Summary

SCRATCH_DIR =
"#{Origen.root}/.j750_scratch"

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Descriptions) initialize(options = {})

Returns a new instance of Descriptions



26
27
28
29
30
31
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 26

def initialize(options = {})
  @parser = options[:parser]
  FileUtils.rm_rf(SCRATCH_DIR) if File.exist?(SCRATCH_DIR)
  parse_program
  true
end

Instance Attribute Details

- (Object) parser

Returns the value of attribute parser



10
11
12
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 10

def parser
  @parser
end

- (Object) source_directories

Returns the value of attribute source_directories



10
11
12
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 10

def source_directories
  @source_directories
end

- (Object) template_directories

Returns the value of attribute template_directories



10
11
12
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 10

def template_directories
  @template_directories
end

Instance Method Details

- (Object) compile_program

Compile a scratch version of the program for parsing



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 167

def compile_program
  if template_directories.size > 0
    unless @program_compiled
      Origen.log.info ''
      Origen.log.info 'Extracting embedded comments:'
      Origen.log.info ''
      copy_templates_to_scratch
      markup_template_comments
      # Compile the flow file, with Ruby comments now preserved and marked up
      Origen.app.runner.generate(compile: true, patterns: uncompiled_dir, output: compiled_dir,
                               check_for_changes: false, collect_stats: false, quiet: true)
      Origen.log.info ''
    end
    @program_compiled = true
  else
    false
  end
end

- (Object) compiled_dir



234
235
236
237
238
239
240
241
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 234

def compiled_dir
  @compiled_dir ||= "#{SCRATCH_DIR}/compiled"
  unless @compiled_dir_created
    FileUtils.mkdir_p(@compiled_dir) unless File.exist?(@compiled_dir)
    @compiled_dir_created = true
  end
  @compiled_dir
end

- (Object) copy_source_files_to_scratch

Copy all flow and instance source files to the scratch dir



201
202
203
204
205
206
207
208
209
210
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 201

def copy_source_files_to_scratch
  source_directories.each do |dir|
    Origen.file_handler.resolve_files(dir) do |file|
      subdir = file.relative_path_from(Pathname.new(dir)).dirname.to_s
      cpydir = "#{ungenerated_dir}/#{subdir}"
      FileUtils.mkdir_p(cpydir) unless File.exist?(cpydir)
      FileUtils.copy(file, cpydir)
    end
  end
end

- (Object) copy_templates_to_scratch

Copy all flow and instance template files to the scratch dir



187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 187

def copy_templates_to_scratch
  uncompiled_dir(true)
  template_directories.each do |dir|
    Origen.file_handler.resolve_files(dir) do |file|
      subdir = file.relative_path_from(Pathname.new(dir)).dirname.to_s
      cpydir = "#{uncompiled_dir}/#{subdir}"
      FileUtils.mkdir_p(cpydir) unless File.exist?(cpydir)
      FileUtils.copy(file, cpydir) if flow_or_instance_file?(file)
    end
  end
  `chmod -R 777 #{uncompiled_dir}/*` unless Dir["#{uncompiled_dir}/*"].empty?
end

- (Object) extract_flow_line_descriptions



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 97

def extract_flow_line_descriptions
  Origen.file_handler.resolve_files(compiled_dir) do |file|
    if flow_file?(file)
      f = file.basename('.txt').to_s
      comments = []
      header_line = true
      File.readlines(file).each do |line|
        if header_line
          header_line = false if line =~ /^\s*Label/
        else
          if line =~ /^<comment>(.*)/
            comments << Regexp.last_match[1].gsub("\r", '')
          else
            t = FlowLine.extract_test(line)
            if t
              lookup.add_for_test_usage(t, file, comments)
            end
            comments = []
          end
        end
      end
    end
  end
end

- (Object) extract_flow_summaries



69
70
71
72
73
74
75
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 69

def extract_flow_summaries
  Origen.file_handler.resolve_files(compiled_dir) do |file|
    if flow_file?(file)
      lookup.add_for_flow(file, parse_flow_summary(file))
    end
  end
end

- (Object) extract_test_instance_descriptions

Parses a compiled template for marked up comments



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 78

def extract_test_instance_descriptions
  Origen.file_handler.resolve_files(compiled_dir) do |file|
    if instance_file?(file)
      comments = []
      File.readlines(file).each do |line|
        if line =~ /^<comment>(.*)/
          comments << Regexp.last_match[1].gsub("\r", '')
        else
          fields = line.split("\t")
          unless ['Test Instances', '', 'Test Name'].include? fields[1]
            lookup.add_for_test_definition(fields[1], comments)
          end
          comments = []
        end
      end
    end
  end
end

- (Boolean) flow_file?(file)

Returns:

  • (Boolean)


285
286
287
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 285

def flow_file?(file)
  flow_or_instance_file?(file, instance: false)
end

- (Object) flow_line(options = {})

Returns the description of the given test from the test flow



46
47
48
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 46

def flow_line(options = {})
  lookup.for_test_usage(options[:name], options[:flow])
end

- (Boolean) flow_or_instance_file?(file, options = {})

Returns true if the given file looks like a Ultraflex flow file, works for templates to

Returns:

  • (Boolean)


254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 254

def flow_or_instance_file?(file, options = {})
  options = { flow:     true,
              instance: true
  }.merge(options)
  if options[:flow] && options[:instance]
    match = 'Flow|Instances'
  elsif options[:flow]
    match = 'Flow'
  else
    match = 'Instances'
  end
  # Not sure the best way to determine the file type of a partial, just
  # return true for now to play it safe
  return true if file.basename.to_s =~ /^_/
  File.readlines(file).each do |line|
    begin
      unless line =~ /^%/ || line =~ /^\s*<comment>/
        return !!(line =~ /#{match}/)
      end
    rescue Exception => e
      if e.is_a?(ArgumentError) && e.message =~ /invalid byte sequence/
        return false
      else
        puts e.message
        puts e.backtrace
        exit 1
      end
    end
  end
end

- (Object) flow_summary(options = {})

Returns the description for the given flow



34
35
36
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 34

def flow_summary(options = {})
  lookup.for_flow(options[:file])
end

- (Object) generate_program

Generate a scratch version of the program for parsing



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 146

def generate_program
  if source_directories.size > 0
    unless @program_generated
      Origen.log.info ''
      Origen.log.info 'Extracting embedded comments:'
      Origen.log.info ''
      copy_source_files_to_scratch
      markup_source_file_comments
      # Compile the flow file, with Ruby comments now preserved and marked up
      desc = Origen.app.runner.generate(program: true, patterns: ungenerated_dir, output: generated_dir,
                                      check_for_changes: false, collect_stats: false, quiet: true,
                                      collect_descriptions: true)
      Origen.log.info ''
    end
    @program_generated = true
  else
    false
  end
end

- (Object) generate_program_files



122
123
124
125
126
127
128
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 122

def generate_program_files
  a = generate_program
  b = compile_program
  unless a || b
    fail 'No source or template files declared from which to parse descriptions!'
  end
end

- (Object) generated_dir



243
244
245
246
247
248
249
250
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 243

def generated_dir
  @generated_dir ||= "#{SCRATCH_DIR}/generated"
  unless @generated_dir_created
    FileUtils.mkdir_p(@generated_dir) unless File.exist?(@generated_dir)
    @generated_dir_created = true
  end
  @generated_dir
end

- (Boolean) instance_file?(file)

Returns:

  • (Boolean)


289
290
291
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 289

def instance_file?(file)
  flow_or_instance_file?(file, flow: false)
end

- (Object) lookup

All descriptions are stored in this lookup table



15
16
17
18
19
20
21
22
23
24
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 15

def lookup
  return @lookup if @lookup
  # Use the one from the interface if present, program generation will
  # automatically push descriptions in here
  if Origen.interface_present?
    @lookup = Origen.interface.descriptions
  else
    @lookup = Origen::Tester::Parser::DescriptionLookup.new
  end
end

- (Object) markup_source_file_comments

Substitute Ruby line comments so they are preserved by generation



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 317

def markup_source_file_comments
  Origen.file_handler.resolve_files(ungenerated_dir) do |file|
    lines = File.readlines(file)
    File.open(file, 'w') do |f|
      lines.each do |line|
        if line =~ /^\s*#\s?(.*)/ # Remove single leading whitespace from comment if it exists
          comment = Regexp.last_match[1]
          # If comment starts with a '#-' it should be removed by generation
          if line =~ /^\s*#-.*/
            f.write line
          # Otherwise preserve it
          else
            f.write "Origen.interface.comment '#{comment}'\n"
          end
        else
          f.write line
        end
      end
    end
  end
end

- (Object) markup_template_comments

Substitute Ruby line comments so they are preserved by compilation



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 294

def markup_template_comments
  Origen.file_handler.resolve_files(uncompiled_dir) do |file|
    lines = File.readlines(file)
    File.open(file, 'w') do |f|
      lines.each do |line|
        if line =~ /^%\s*#\s?(.*)/ # Remove single leading whitespace from comment if it exists
          comment = Regexp.last_match[1]
          # If comment starts with a '#-' it should be removed by compilation
          if line =~ /^%\s*#-.*/
            f.write line
          # Otherwise preserve it
          else
            f.write "<comment>#{comment}\n"
          end
        else
          f.write line
        end
      end
    end
  end
end

- (Object) parse_flow_summary(file)

Parses the given flow file for summary text and returns it, summary text must be the very first thing in the file. Returns an array of strings each representing a line of text.



133
134
135
136
137
138
139
140
141
142
143
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 133

def parse_flow_summary(file)
  desc = []
  File.readlines(file).each do |line|
    if line =~ /%?\s*<comment>(.*)/
      desc << Regexp.last_match[1].gsub("\r", '')
    else
      break
    end
  end
  desc
end

- (Object) parse_program



50
51
52
53
54
55
56
57
58
59
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 50

def parse_program
  Origen.file_handler.preserve_state do
    generate_program_files
    # Comments must be extracted manually for any compiled files, for
    # generated files the comments will already be in the lookup
    extract_flow_summaries
    extract_test_instance_descriptions
    extract_flow_line_descriptions
  end
end

- (Object) test_instance(options = {})

Returns the description of the given test from the test instance sheet declaration



40
41
42
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 40

def test_instance(options = {})
  lookup.for_test_definition(options[:name])
end

- (Object) uncompiled_dir(force_make = false)



212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 212

def uncompiled_dir(force_make = false)
  @uncompiled_dir ||= "#{SCRATCH_DIR}/uncompiled"
  if force_make
    FileUtils.rm_rf(@uncompiled_dir) if File.exist?(@uncompiled_dir)
    @uncompiled_dir_created = false
  end
  unless @uncompiled_dir_created
    FileUtils.mkdir_p(@uncompiled_dir) unless File.exist?(@uncompiled_dir)
    @uncompiled_dir_created = true
  end
  @uncompiled_dir
end

- (Object) ungenerated_dir



225
226
227
228
229
230
231
232
# File 'lib/origen/tester/ultraflex/parser/descriptions.rb', line 225

def ungenerated_dir
  @ungenerated_dir ||= "#{SCRATCH_DIR}/ungenerated"
  unless @ungenerated_dir_created
    FileUtils.mkdir_p(@ungenerated_dir) unless File.exist?(@ungenerated_dir)
    @ungenerated_dir_created = true
  end
  @ungenerated_dir
end