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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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)
[View source]

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

[View source]

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)
[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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)
[View source]

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

[View source]

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

[View source]

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

[View source]

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.

[View source]

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

[View source]

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

[View source]

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)

[View source]

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

[View source]

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