origen_stil 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d72b98b73cdeeca00b3fdf509c61faed891f84bc26e0e8eac2e35819cb19fefa
4
- data.tar.gz: 79ae1508faa458453fc5f537f0b8a666e07cadb21a6a8af62caab1a375a77934
3
+ metadata.gz: 259036f2835904086a3ee116686b8deea693701480214760345f255b7f5a8b11
4
+ data.tar.gz: d7eb35222e5ac396c59f03274464321c71f82487ba0f334d8d65db471cbda997
5
5
  SHA512:
6
- metadata.gz: 9c14bd4cd23e893324f202256eef34b2bd4eed81f2ca28167905fbbbe124f36f90392bb828f6ec07be94698025519570f2e33c7e7626a01f00d0489bc2e4995a
7
- data.tar.gz: c2dd4d2176e1a10480a2f19a45fc922a7ff61c0e9077a83e825569852021fab91e9088d3236719643060f42f32853523184fd32cc00a93addef808c7dfdd52a4
6
+ metadata.gz: c04ff6b66af25e716fbd228266d1ccad13ebd921ab01490fedb4126db563b4787c39d973f6b547898ae6f8ce709c7131482b2fa4ad0d4dde1c73900d96b0cb1f
7
+ data.tar.gz: 30e9d17e1cae9969b10b63edb997587ae31fa41a8f3c3fd1e6229f0079a9a61da38061f79748516dbea2587b6a3964417b2fe41460d72a41374db6883bdb6ed2
@@ -33,42 +33,39 @@ when "tags"
33
33
  # control flowing back to Origen
34
34
  exit 0
35
35
 
36
- ## Example of how to make a command to run unit tests, this simply invokes RSpec on
37
- ## the spec directory
38
- #when "specs"
39
- # require "rspec"
40
- # exit RSpec::Core::Runner.run(['spec'])
36
+ # Example of how to make a command to run unit tests, this simply invokes RSpec on
37
+ # the spec directory
38
+ when "specs"
39
+ require "rspec"
40
+ exit RSpec::Core::Runner.run(['spec'])
41
41
 
42
- ## Example of how to make a command to run diff-based tests
43
- #when "examples", "test"
44
- # Origen.load_application
45
- # status = 0
46
- #
47
- # # Compiler tests
48
- # ARGV = %w(templates/example.txt.erb -t debug -r approved)
49
- # load "origen/commands/compile.rb"
50
- # # Pattern generator tests
51
- # #ARGV = %w(some_pattern -t debug -r approved)
52
- # #load "#{Origen.top}/lib/origen/commands/generate.rb"
53
- #
54
- # if Origen.app.stats.changed_files == 0 &&
55
- # Origen.app.stats.new_files == 0 &&
56
- # Origen.app.stats.changed_patterns == 0 &&
57
- # Origen.app.stats.new_patterns == 0
58
- #
59
- # Origen.app.stats.report_pass
60
- # else
61
- # Origen.app.stats.report_fail
62
- # status = 1
63
- # end
64
- # puts
65
- # if @command == "test"
66
- # Origen.app.unload_target!
67
- # require "rspec"
68
- # result = RSpec::Core::Runner.run(['spec'])
69
- # status = status == 1 ? 1 : result
70
- # end
71
- # exit status # Exit with a 1 on the event of a failure per std unix result codes
42
+ # Example of how to make a command to run diff-based tests
43
+ when "examples", "test"
44
+ Origen.load_application
45
+ status = 0
46
+
47
+ # Pattern generator tests
48
+ ARGV = %w(example3 -r approved -e v93k)
49
+ load "#{Origen.top}/lib/origen/commands/generate.rb"
50
+
51
+ if Origen.app.stats.changed_files == 0 &&
52
+ Origen.app.stats.new_files == 0 &&
53
+ Origen.app.stats.changed_patterns == 0 &&
54
+ Origen.app.stats.new_patterns == 0
55
+
56
+ Origen.app.stats.report_pass
57
+ else
58
+ Origen.app.stats.report_fail
59
+ status = 1
60
+ end
61
+ puts
62
+ if @command == "test"
63
+ Origen.app.unload_target!
64
+ require "rspec"
65
+ result = RSpec::Core::Runner.run(['spec'])
66
+ status = status == 1 ? 1 : result
67
+ end
68
+ exit status # Exit with a 1 on the event of a failure per std unix result codes
72
69
 
73
70
  # Always leave an else clause to allow control to fall back through to the
74
71
  # Origen command handler.
@@ -79,8 +76,8 @@ else
79
76
  @application_commands = <<-EOT
80
77
  tags Build a tags file for this app
81
78
  build Build/compile the latest grammar file(s)
79
+ specs Run the specs (tests), -c will enable coverage
80
+ examples Run the examples (tests), -c will enable coverage
81
+ test Run both specs and examples, -c will enable coverage
82
82
  EOT
83
- # specs Run the specs (tests), -c will enable coverage
84
- # examples Run the examples (tests), -c will enable coverage
85
- # test Run both specs and examples, -c will enable coverage
86
83
  end
@@ -1,8 +1,7 @@
1
1
  module OrigenSTIL
2
2
  MAJOR = 0
3
- MINOR = 2
4
- BUGFIX = 1
3
+ MINOR = 3
4
+ BUGFIX = 0
5
5
  DEV = nil
6
-
7
6
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
8
7
  end
@@ -254,7 +254,7 @@ module OrigenSTIL
254
254
  elements[1]
255
255
  end
256
256
 
257
- def sigref_expression
257
+ def expression_subset
258
258
  elements[2]
259
259
  end
260
260
 
@@ -311,7 +311,7 @@ module OrigenSTIL
311
311
  r5 = _nt_s
312
312
  s3 << r5
313
313
  if r5
314
- r6 = _nt_sigref_expression
314
+ r6 = _nt_expression_subset
315
315
  s3 << r6
316
316
  if r6
317
317
  r7 = _nt_s
@@ -352,153 +352,104 @@ module OrigenSTIL
352
352
  r0
353
353
  end
354
354
 
355
- def _nt_expression
355
+ def _nt_expression_subset
356
356
  start_index = index
357
- if node_cache[:expression].has_key?(index)
358
- cached = node_cache[:expression][index]
357
+ if node_cache[:expression_subset].has_key?(index)
358
+ cached = node_cache[:expression_subset][index]
359
359
  if cached
360
- node_cache[:expression][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
360
+ node_cache[:expression_subset][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
361
361
  @index = cached.interval.end
362
362
  end
363
363
  return cached
364
364
  end
365
365
 
366
366
  i0 = index
367
- r1 = _nt_sigref_expression
367
+ r1 = _nt_add
368
368
  if r1
369
369
  r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
370
370
  r0 = r1
371
371
  else
372
- r2 = _nt_time_expression
372
+ r2 = _nt_subtract
373
373
  if r2
374
374
  r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
375
375
  r0 = r2
376
376
  else
377
- @index = i0
378
- r0 = nil
379
- end
380
- end
381
-
382
- node_cache[:expression][start_index] = r0
383
-
384
- r0
385
- end
386
-
387
- def _nt_sigref_expression
388
- start_index = index
389
- if node_cache[:sigref_expression].has_key?(index)
390
- cached = node_cache[:sigref_expression][index]
391
- if cached
392
- node_cache[:sigref_expression][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
393
- @index = cached.interval.end
394
- end
395
- return cached
396
- end
397
-
398
- s0, i0 = [], index
399
- loop do
400
- i1 = index
401
- r2 = _nt_add
402
- if r2
403
- r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
404
- r1 = r2
405
- else
406
- r3 = _nt_subtract
377
+ r3 = _nt_name
407
378
  if r3
408
379
  r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
409
- r1 = r3
380
+ r0 = r3
410
381
  else
411
- r4 = _nt_name
382
+ r4 = _nt_paren_expression
412
383
  if r4
413
384
  r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true
414
- r1 = r4
385
+ r0 = r4
415
386
  else
416
- r5 = _nt_paren_expression
417
- if r5
418
- r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true
419
- r1 = r5
420
- else
421
- @index = i1
422
- r1 = nil
423
- end
387
+ @index = i0
388
+ r0 = nil
424
389
  end
425
390
  end
426
391
  end
427
- if r1
428
- s0 << r1
429
- else
430
- break
431
- end
432
- end
433
- if s0.empty?
434
- @index = i0
435
- r0 = nil
436
- else
437
- r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
438
392
  end
439
393
 
440
- node_cache[:sigref_expression][start_index] = r0
394
+ node_cache[:expression_subset][start_index] = r0
441
395
 
442
396
  r0
443
397
  end
444
398
 
445
- def _nt_time_expression
399
+ def _nt_expression
446
400
  start_index = index
447
- if node_cache[:time_expression].has_key?(index)
448
- cached = node_cache[:time_expression][index]
401
+ if node_cache[:expression].has_key?(index)
402
+ cached = node_cache[:expression][index]
449
403
  if cached
450
- node_cache[:time_expression][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
404
+ node_cache[:expression][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
451
405
  @index = cached.interval.end
452
406
  end
453
407
  return cached
454
408
  end
455
409
 
456
- s0, i0 = [], index
457
- loop do
458
- i1 = index
459
- r2 = _nt_add
410
+ i0 = index
411
+ r1 = _nt_add
412
+ if r1
413
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
414
+ r0 = r1
415
+ else
416
+ r2 = _nt_subtract
460
417
  if r2
461
418
  r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
462
- r1 = r2
419
+ r0 = r2
463
420
  else
464
- r3 = _nt_subtract
421
+ r3 = _nt_multiply
465
422
  if r3
466
423
  r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
467
- r1 = r3
424
+ r0 = r3
468
425
  else
469
- r4 = _nt_multiply
426
+ r4 = _nt_divide
470
427
  if r4
471
428
  r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true
472
- r1 = r4
429
+ r0 = r4
473
430
  else
474
- r5 = _nt_divide
431
+ r5 = _nt_number_with_unit
475
432
  if r5
476
433
  r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true
477
- r1 = r5
434
+ r0 = r5
478
435
  else
479
- r6 = _nt_number_with_unit
436
+ r6 = _nt_number
480
437
  if r6
481
438
  r6 = SyntaxNode.new(input, (index-1)...index) if r6 == true
482
- r1 = r6
439
+ r0 = r6
483
440
  else
484
- r7 = _nt_number
441
+ r7 = _nt_name
485
442
  if r7
486
443
  r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true
487
- r1 = r7
444
+ r0 = r7
488
445
  else
489
- r8 = _nt_name
446
+ r8 = _nt_paren_expression
490
447
  if r8
491
448
  r8 = SyntaxNode.new(input, (index-1)...index) if r8 == true
492
- r1 = r8
449
+ r0 = r8
493
450
  else
494
- r9 = _nt_paren_expression
495
- if r9
496
- r9 = SyntaxNode.new(input, (index-1)...index) if r9 == true
497
- r1 = r9
498
- else
499
- @index = i1
500
- r1 = nil
501
- end
451
+ @index = i0
452
+ r0 = nil
502
453
  end
503
454
  end
504
455
  end
@@ -506,20 +457,9 @@ module OrigenSTIL
506
457
  end
507
458
  end
508
459
  end
509
- if r1
510
- s0 << r1
511
- else
512
- break
513
- end
514
- end
515
- if s0.empty?
516
- @index = i0
517
- r0 = nil
518
- else
519
- r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
520
460
  end
521
461
 
522
- node_cache[:time_expression][start_index] = r0
462
+ node_cache[:expression][start_index] = r0
523
463
 
524
464
  r0
525
465
  end
@@ -946,7 +886,7 @@ module OrigenSTIL
946
886
  elements[1]
947
887
  end
948
888
 
949
- def time_expression
889
+ def expression
950
890
  elements[2]
951
891
  end
952
892
 
@@ -986,7 +926,7 @@ module OrigenSTIL
986
926
  r2 = _nt_s
987
927
  s0 << r2
988
928
  if r2
989
- r3 = _nt_time_expression
929
+ r3 = _nt_expression
990
930
  s0 << r3
991
931
  if r3
992
932
  r4 = _nt_s
@@ -7954,7 +7894,7 @@ module OrigenSTIL
7954
7894
 
7955
7895
  module Name2
7956
7896
  def to_ast
7957
- text_value
7897
+ n :name, text_value
7958
7898
  end
7959
7899
  end
7960
7900
 
@@ -9032,6 +8972,16 @@ module OrigenSTIL
9032
8972
  end
9033
8973
  end
9034
8974
 
8975
+ module Number3
8976
+ def to_ast
8977
+ if text_value.to_f == text_value.to_i
8978
+ text_value.to_i
8979
+ else
8980
+ text_value.to_f
8981
+ end
8982
+ end
8983
+ end
8984
+
9035
8985
  def _nt_number
9036
8986
  start_index = index
9037
8987
  if node_cache[:number].has_key?(index)
@@ -9048,6 +8998,8 @@ module OrigenSTIL
9048
8998
  if r1
9049
8999
  r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
9050
9000
  r0 = r1
9001
+ r0.extend(Number3)
9002
+ r0.extend(Number3)
9051
9003
  else
9052
9004
  i2, s2 = index, []
9053
9005
  r3 = _nt_signed_integer
@@ -9076,6 +9028,8 @@ module OrigenSTIL
9076
9028
  if r2
9077
9029
  r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
9078
9030
  r0 = r2
9031
+ r0.extend(Number3)
9032
+ r0.extend(Number3)
9079
9033
  else
9080
9034
  i6, s6 = index, []
9081
9035
  r7 = _nt_signed_integer
@@ -9104,6 +9058,8 @@ module OrigenSTIL
9104
9058
  if r6
9105
9059
  r6 = SyntaxNode.new(input, (index-1)...index) if r6 == true
9106
9060
  r0 = r6
9061
+ r0.extend(Number3)
9062
+ r0.extend(Number3)
9107
9063
  else
9108
9064
  i10, s10 = index, []
9109
9065
  r11 = _nt_signed_integer
@@ -9146,6 +9102,8 @@ module OrigenSTIL
9146
9102
  if r10
9147
9103
  r10 = SyntaxNode.new(input, (index-1)...index) if r10 == true
9148
9104
  r0 = r10
9105
+ r0.extend(Number3)
9106
+ r0.extend(Number3)
9149
9107
  else
9150
9108
  @index = i0
9151
9109
  r0 = nil
@@ -22,11 +22,12 @@ module OrigenSTIL
22
22
  end
23
23
 
24
24
  module Processor
25
- autoload :Base, 'origen_stil/processor/base'
26
- autoload :Pins, 'origen_stil/processor/pins'
27
- autoload :PinGroups, 'origen_stil/processor/pin_groups'
28
- autoload :Pattern, 'origen_stil/processor/pattern'
29
- autoload :Timesets, 'origen_stil/processor/timesets'
25
+ autoload :Base, 'origen_stil/processor/base'
26
+ autoload :Pins, 'origen_stil/processor/pins'
27
+ autoload :PinGroups, 'origen_stil/processor/pin_groups'
28
+ autoload :Pattern, 'origen_stil/processor/pattern'
29
+ autoload :Timesets, 'origen_stil/processor/timesets'
30
+ autoload :Expression, 'origen_stil/processor/expression'
30
31
  end
31
32
 
32
33
  autoload :Pattern, 'origen_stil/pattern'
@@ -63,6 +64,11 @@ module OrigenSTIL
63
64
  def self.patterns
64
65
  @patterns ||= {}
65
66
  end
67
+
68
+ # @api private
69
+ def self.unquote(str)
70
+ str.gsub(/\A("|')|("|')\Z/, '')
71
+ end
66
72
  end
67
73
 
68
74
  STIL = OrigenSTIL unless defined?(STIL)
@@ -8,23 +8,31 @@ module OrigenSTIL
8
8
  fail "STIL source file not found: #{path}"
9
9
  end
10
10
  @path = path
11
+ @loop = Struct.new(:id, :count, :status, :source_line_number, :number_of_lines, :braces, :lines)
12
+ @n = 0
11
13
  end
12
14
 
13
15
  def execute(options = {})
14
- timeset = nil
16
+ options = {
17
+ set_timesets: false,
18
+ add_pins: true
19
+ }.merge(options)
20
+ @exec_options = options
21
+ @n = 0
22
+ add_pins if options[:add_pins]
15
23
  Processor::Pattern.new.run(ast) do |pattern_name|
16
- each_vector(pattern_name, options) do |vector|
17
- if options[:set_timesets] && vector[:timeset] && vector[:timeset] != timeset
18
- tester.set_timeset(vector[:timeset], timesets[vector[:timeset]][:period] || 0)
19
- timeset = vector[:timeset]
20
- end
21
- vector[:comments].each { |comment| cc comment }
22
- vector[:pindata].each do |pin, data|
23
- pin = dut.pins(pin)
24
- data = data.gsub(/\s+/, '')
25
- pin.vector_formatted_value = data
24
+ i = 0
25
+ open = false
26
+ File.foreach(path) do |line|
27
+ if open
28
+ # Stop at next pattern or EOF
29
+ break if line =~ /^\s*Pattern/
30
+
31
+ consume_line(line, i)
32
+ else
33
+ open = true if line =~ /^\s*Pattern "?'?#{pattern_name}"?'?\s*{/
26
34
  end
27
- vector[:repeat].cycles
35
+ i += 1
28
36
  end
29
37
  end
30
38
  end
@@ -69,53 +77,128 @@ module OrigenSTIL
69
77
  @timesets ||= Processor::Timesets.new.run(ast, options)
70
78
  end
71
79
 
72
- # Yields each vector in the given pattern to the caller as a Hash with the
73
- # structure shown in these examples:
74
- #
75
- # { timeset: "wave1",
76
- # comments: ["blah, blah", "blah blah blah"],
77
- # pindata: { "ALL" => "10011011101" },
78
- # repeat: 1,
79
- # }
80
- #
81
- # { timeset: nil,
82
- # comments: [],
83
- # pindata: { "portA" => "10011011101", "portB" => "10010" },
84
- # repeat: 1000
85
- # }
86
- #
87
- def each_vector(pattern_name, options = {})
88
- open = false
89
- vector = { timeset: nil, comments: [], pindata: {}, repeat: 1 }
90
- File.foreach(path) do |line|
91
- if open
92
- # Stop at next pattern or EOF
93
- break if line =~ /^\s*Pattern/
94
- if line =~ /^\s*Ann\s*{\*\s*(.*)\s*\*}/
95
- vector[:comments] << Regexp.last_match(1)
96
- elsif line =~ /(?:^|.*:)\s*(?:W|WaveformTable)\s+(.*)\s*;/
97
- vector[:timeset] = Regexp.last_match(1)
98
- elsif line =~ /(?:^|.*:)\s*Loop\s+(\d+)(\s|{)/
99
- vector[:repeat] = Regexp.last_match(1).to_i
100
- elsif line =~ /(?:^|.*:)\s*(?:V|Vector)\s+{(.*)}/
101
- Regexp.last_match(1).strip.split(';').each do |assignment|
102
- assignment = assignment.split(/\s*=\s*/)
103
- vector[:pindata][assignment[0]] = assignment[1]
80
+ private
81
+
82
+ # vector[:repeat].cycles
83
+ def consume_line(line, source_line_number)
84
+ if @open_loop
85
+ execute_loop(line)
86
+ else
87
+ if line =~ /(.*)(?:^|.*:)\s*Loop\s+(\d+)(.*)/
88
+ # :id, :count, :status, :source_line_number, :number_of_lines, :braces, :lines)
89
+ @open_loop = @loop.new(Regexp.last_match(1), Regexp.last_match(2).to_i, :pending, source_line_number, 0, 0, [])
90
+ execute_loop(Regexp.last_match(3))
91
+
92
+ else
93
+ execute_line(line, source_line_number)
94
+ end
95
+ end
96
+ end
97
+
98
+ def execute_loop(line)
99
+ # This is the number of lines that the source code spans, not necessarily the number
100
+ # of active lines in the loop
101
+ @open_loop.number_of_lines += 1
102
+ content = ''
103
+ comment = nil
104
+ line.each_char do |c|
105
+ # Stop processing the remainder if the line when a comment is encountered
106
+ if c == '/'
107
+ break if comment == '/'
108
+ comment = '/'
109
+ next
110
+ else
111
+ comment = nil
112
+ end
113
+ if @open_loop.status == :pending
114
+ next if c == ' ' || c == "\t" || c == "\n"
115
+ if c == '{'
116
+ @open_loop.status = :open
117
+ @open_loop.braces += 1
118
+ else
119
+ fail "No start of loop character '{' around line #{@open_loop.source_line_number}"
120
+ end
121
+ elsif @open_loop.status == :open
122
+ if c == '{'
123
+ @open_loop.braces += 1
124
+ content += c
125
+ elsif c == '}'
126
+ @open_loop.braces -= 1
127
+ if @open_loop.braces == 0
128
+ @open_loop.status = :done
129
+ content = content.strip
130
+ unless content.empty?
131
+ @open_loop.lines << content
132
+ content = ''
133
+ end
134
+ else
135
+ content += c
104
136
  end
105
- yield vector
106
- vector = { timeset: nil, comments: [], pindata: {}, repeat: 1 }
137
+ else
138
+ content += c
107
139
  end
108
140
  else
109
- open = true if line =~ /^\s*Pattern #{pattern_name}\s*{/
141
+ content += c
110
142
  end
111
143
  end
144
+
145
+ if @open_loop.status == :done
146
+ lp = @open_loop
147
+ @open_loop = nil
148
+ # If loop being used like a repeat
149
+ if lp.lines.size == 1 && lp.lines.first =~ /(?:^|.*:)\s*(?:V|Vector)\s+{(.*)}/
150
+ execute_line(lp.lines.first, lp.source_line_number, lp.count)
151
+ else
152
+ tester.loop_vectors "lp#{@n}", lp.count do
153
+ lp.lines.each { |line| consume_line(line, lp.source_line_number) }
154
+ end
155
+ end
156
+ # Consume any remaining content on the line after the loop closed
157
+ unless content.strip.empty?
158
+ consume_line(content, lp.source_line_number + lp.number_of_lines - 1)
159
+ end
160
+ else
161
+ content = content.strip
162
+ @open_loop.lines << content unless content.empty?
163
+ end
112
164
  end
113
165
 
114
- def each_vector_with_index(pattern_name, options = {})
115
- i = 0
116
- each_vector(pattern_name, options) do |vec|
117
- yield vec, i
118
- i += 1
166
+ # Sends any understood operations from the given line to the current tester
167
+ def execute_line(line, source_line_number, cycles = 1)
168
+ # These are in order of more likely occurrence for speed, i.e. assume that most
169
+ # pattern lines are vectors...
170
+ if line =~ /(?:^|.*:)\s*(?:V|Vector)\s+{(.*)}/
171
+ Regexp.last_match(1).strip.split(';').each do |assignment|
172
+ assignment = assignment.split(/\s*=\s*/)
173
+ pin = dut.pins(OrigenSTIL.unquote(assignment[0]))
174
+ data = assignment[1].gsub(/\s+/, '')
175
+ pin.vector_formatted_value = data
176
+ end
177
+ cycles.cycles
178
+
179
+ # Pattern comments
180
+ elsif line =~ /^\s*Ann\s*{\*\s*(.*)\s*\*}/
181
+ cc Regexp.last_match(1)
182
+
183
+ # Source comments
184
+ elsif line =~ /\s*\/\/.*/
185
+ # Just ignore source comments
186
+
187
+ # Change of timeset
188
+ elsif line =~ /(?:^|.*:)\s*(?:W|WaveformTable)\s+(.*)\s*;/
189
+ if @exec_options[:set_timesets]
190
+ timeset = OrigenSTIL.unquote(Regexp.last_match(1))
191
+ if timeset != @current_timeset
192
+ tester.set_timeset(timeset, timesets[timeset][:period_in_ns])
193
+ @current_timeset = timeset
194
+ end
195
+ end
196
+
197
+ else
198
+ line = line.strip
199
+ unless line.empty? || line == '}' # End of pattern
200
+ Origen.log.warning "Skipped Pattern line #{source_line_number}: #{line}"
201
+ end
119
202
  end
120
203
  end
121
204
  end
@@ -1,3 +1,4 @@
1
+ require 'ast'
1
2
  module OrigenSTIL
2
3
  module Processor
3
4
  class Base
@@ -0,0 +1,70 @@
1
+ module OrigenSTIL
2
+ module Processor
3
+ # Evaluates an expression to a final answer
4
+ class Expression < Base
5
+ # Given node should be a top-level expression node, like a :time_expr
6
+ def run(node, options = {})
7
+ process(node).value
8
+ end
9
+
10
+ def on_number_with_unit(node)
11
+ val = node.find(:value).value
12
+ if p = node.find(:prefix)
13
+ case p.value
14
+ when 'E'
15
+ val = val * 1_000_000_000_000_000_000
16
+ when 'P'
17
+ val = val * 1_000_000_000_000_000
18
+ when 'T'
19
+ val = val * 1_000_000_000_000
20
+ when 'G'
21
+ val = val * 1_000_000_000
22
+ when 'M'
23
+ val = val * 1_000_000
24
+ when 'k'
25
+ val = val * 1000
26
+ when 'm'
27
+ val = val / 1000.0
28
+ when 'u'
29
+ val = val / 1_000_000.0
30
+ when 'n'
31
+ val = val / 1_000_000_000.0
32
+ when 'p'
33
+ val = val / 1_000_000_000_000.0
34
+ when 'f'
35
+ val = val / 1_000_000_000_000_000.0
36
+ when 'a'
37
+ val = val / 1_000_000_000_000_000_000.0
38
+ else
39
+ fail "Unknown number prefix #{p.value}"
40
+ end
41
+ end
42
+ val
43
+ end
44
+
45
+ def on_parens(node)
46
+ process_all(node.children).first
47
+ end
48
+
49
+ def on_multiply(node)
50
+ a, b = *process_all(node.children)
51
+ a * b
52
+ end
53
+
54
+ def on_divide(node)
55
+ a, b = *process_all(node.children)
56
+ a / (b * 1.0)
57
+ end
58
+
59
+ def on_add(node)
60
+ a, b = *process_all(node.children)
61
+ a + b
62
+ end
63
+
64
+ def on_subtract(node)
65
+ a, b = *process_all(node.children)
66
+ a - b
67
+ end
68
+ end
69
+ end
70
+ end
@@ -19,6 +19,7 @@ module OrigenSTIL
19
19
 
20
20
  def on_pattern_burst(node)
21
21
  name, pat_list = *node
22
+ name = name.value if name.try(:type) == :name
22
23
  if pat_list
23
24
  @bursts[name] = []
24
25
  @current_burst = @bursts[name]
@@ -27,7 +28,9 @@ module OrigenSTIL
27
28
  end
28
29
 
29
30
  def on_pat_list_item(node)
30
- @current_burst << node.to_a[0]
31
+ name = node.to_a[0]
32
+ name = name.value if name.try(:type) == :name
33
+ @current_burst << name
31
34
  end
32
35
  end
33
36
  end
@@ -11,25 +11,57 @@ module OrigenSTIL
11
11
  end
12
12
  end
13
13
 
14
+ def on_signal_groups(node)
15
+ groups = node.children
16
+ if groups.first.type == :name
17
+ groups = groups.dup
18
+ # Not doing anything with named groups currently
19
+ @current_signal_group_domain = groups.shift.value
20
+ groups.freeze
21
+ Origen.log.warning "Signal groups for domain \"#{@current_signal_group_domain}\" are being ignored (support for named signal groups is not implemented yet)"
22
+ # process_all(groups)
23
+ else
24
+ @current_signal_group_domain = nil
25
+ process_all(groups)
26
+ end
27
+ end
28
+
14
29
  def on_signal_group(node)
15
30
  name, expr = *node
31
+ name = OrigenSTIL.unquote(name.value)
32
+ @current_signal_group = name
16
33
  unless model.has_pin?(name)
17
34
  ids = process(expr).to_a[0]
18
35
  model.add_pin_group name.to_sym, *ids
19
36
  end
20
37
  end
21
38
 
39
+ def on_name(node)
40
+ id = node.value
41
+ if model.has_pin?(id)
42
+ # Expand any references to another pin group
43
+ id = id.to_sym
44
+ if dut.pin_groups.ids.map(&:to_sym).include?(id)
45
+ model.pin(id).map(&:id)
46
+ else
47
+ [id]
48
+ end
49
+ else
50
+ fail "Pin #{id} referenced at #{node.file}:#{node.line_number} but DUT does not have this pin/pin_group"
51
+ end
52
+ end
53
+
22
54
  def on_add(node)
23
55
  lhs, rhs = *node
24
56
  Array(process(lhs)) + Array(process(rhs))
25
57
  end
26
58
 
27
59
  def on_subtract(node)
28
- fail 'Subract not implemented yet!'
60
+ fail 'Subtraction in pin groups is not supported yet'
29
61
  end
30
62
 
31
- def on_paren(node)
32
- fail 'Parenthesis not implemented yet!'
63
+ def on_parens(node)
64
+ process_all(node.children).first
33
65
  end
34
66
  end
35
67
  end
@@ -11,6 +11,7 @@ module OrigenSTIL
11
11
 
12
12
  def on_signal(node)
13
13
  name, direction = *node
14
+ name = OrigenSTIL.unquote(name)
14
15
  if direction == 'In'
15
16
  direction = :input
16
17
  elsif direction == 'Out'
@@ -36,6 +37,12 @@ module OrigenSTIL
36
37
  end
37
38
  end
38
39
  end
40
+
41
+ private
42
+
43
+ def unquote(str)
44
+ str.gsub(/\A("|')|("|')\Z/, '')
45
+ end
39
46
  end
40
47
  end
41
48
  end
@@ -11,9 +11,15 @@ module OrigenSTIL
11
11
 
12
12
  def on_waveform_table(node)
13
13
  name = node.to_a[0]
14
- # Pass on resolving the period for now, could involve parameter cross referencing
15
- period = node.find(:period)
14
+ name = name.value if name.try(:type) == :name
16
15
  @timesets[name] = {}
16
+ if period = node.find(:period)
17
+ @timesets[name][:period_in_ns] = process_all(period.children).first * 1_000_000_000
18
+ end
19
+ end
20
+
21
+ def on_time_expr(node)
22
+ Expression.new.run(node)
17
23
  end
18
24
  end
19
25
  end
@@ -0,0 +1,7 @@
1
+ Pattern.create do
2
+ tester.set_timeset('func', 100)
3
+ file = "#{Origen.root}/examples/example3.stil"
4
+ OrigenSTIL.add_pins(file)
5
+ dut.pin_pattern_order(*dut.pins.map { |id, pin| id })
6
+ OrigenSTIL.execute(file)
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: origen_stil
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen McGinty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-11 00:00:00.000000000 Z
11
+ date: 2020-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: origen
@@ -59,7 +59,6 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - bin/fix_my_workspace
63
62
  - config/application.rb
64
63
  - config/boot.rb
65
64
  - config/commands.rb
@@ -68,6 +67,7 @@ files:
68
67
  - lib/origen_stil.rb
69
68
  - lib/origen_stil/pattern.rb
70
69
  - lib/origen_stil/processor/base.rb
70
+ - lib/origen_stil/processor/expression.rb
71
71
  - lib/origen_stil/processor/pattern.rb
72
72
  - lib/origen_stil/processor/pin_groups.rb
73
73
  - lib/origen_stil/processor/pins.rb
@@ -75,6 +75,7 @@ files:
75
75
  - lib/origen_stil/syntax/node.rb
76
76
  - lib/origen_stil/syntax/parser.rb
77
77
  - lib/tasks/origen_stil.rake
78
+ - pattern/example3.rb
78
79
  - templates/web/index.md.erb
79
80
  - templates/web/layouts/_basic.html.erb
80
81
  - templates/web/partials/_navbar.html.erb
@@ -98,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
99
  version: 1.8.11
99
100
  requirements: []
100
101
  rubyforge_project:
101
- rubygems_version: 2.7.6
102
+ rubygems_version: 2.7.7
102
103
  signing_key:
103
104
  specification_version: 4
104
105
  summary: Helpers to consume and generate test IP in STIL format (IEEE 1450)
@@ -1,100 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $VERBOSE = nil # Don't care about world writable dir warnings and the like
3
-
4
- if $_fix_my_workspace_version_check
5
- $_fix_my_workspace_version = '0.7.0'
6
- else
7
- if File.exist?(File.expand_path('../../lib/origen.rb', __FILE__))
8
- # If this script is being run from within an origen-core workspace, use that Origen-core,
9
- # not the system-installed origen-core version.
10
- $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
11
- require 'origen'
12
- else
13
- # Use system-installed Origen (the gem in system Ruby)
14
- require 'origen'
15
- end
16
-
17
- if !Origen.site_config.gem_manage_bundler
18
- puts 'Sorry but you have opted to manage Bundler yourself via your Origen site config, and this means'
19
- puts 'that I cannot make certain assumptions about how your workspace is configured.'
20
- puts 'You will need to either resolve this problem yourself, or else change the value of'
21
- puts 'gem_mange_bundler to true.'
22
- puts 'See here for more details on how to do that: http://origen-sdk.org/origen/guides/starting/company/'
23
-
24
- else
25
- ENV['BUNDLE_GEMFILE'] = File.join(Origen.root, 'Gemfile')
26
- ENV['BUNDLE_PATH'] = File.expand_path(Origen.site_config.gem_install_dir)
27
- ENV['BUNDLE_BIN'] = File.join(Origen.root, 'lbin')
28
-
29
- # Force copy system gems to local gems
30
- if Origen.site_config.gem_use_from_system
31
- local_gem_dir = "#{ENV['BUNDLE_PATH']}/ruby/#{Pathname.new(Gem.dir).basename}"
32
- gem_dir = Pathname.new(Gem.dir)
33
-
34
- Origen.site_config.gem_use_from_system.each do |gem, version|
35
- begin
36
- # This will raise an error if the system doesn't have this gem installed, that
37
- # will be rescued below
38
- spec = Gem::Specification.find_by_name(gem, version)
39
-
40
- local_dir = File.join(local_gem_dir, Pathname.new(spec.gem_dir).relative_path_from(gem_dir))
41
- FileUtils.mkdir_p local_dir
42
- FileUtils.cp_r("#{spec.gem_dir}/.", local_dir)
43
-
44
- local_file = Pathname.new(File.join(local_gem_dir, Pathname.new(spec.cache_file).relative_path_from(gem_dir)))
45
- FileUtils.mkdir_p local_file.dirname
46
- FileUtils.cp(spec.cache_file, local_file)
47
-
48
- if spec.extension_dir && File.exist?(spec.extension_dir)
49
- local_dir = File.join(local_gem_dir, Pathname.new(spec.extension_dir).relative_path_from(gem_dir))
50
- FileUtils.mkdir_p local_dir
51
- FileUtils.cp_r("#{spec.extension_dir}/.", local_dir)
52
- end
53
-
54
- local_file = Pathname.new(File.join(local_gem_dir, Pathname.new(spec.spec_file).relative_path_from(gem_dir)))
55
- FileUtils.mkdir_p local_file.dirname
56
- FileUtils.cp(spec.spec_file, local_file)
57
-
58
- rescue Gem::LoadError
59
- # This just means that one of the gems that should be copied from the system
60
- # was not actually installed in the system, so nothing we can do about that here
61
- end
62
- end
63
- end
64
-
65
- # Delete lbin
66
- FileUtils.rm_rf(ENV['BUNDLE_BIN']) if File.exist?(ENV['BUNDLE_BIN'])
67
-
68
- # Run bundler with correct switches
69
- cmd = "bundle install --gemfile #{ENV['BUNDLE_GEMFILE']} --binstubs #{ENV['BUNDLE_BIN']} --path #{ENV['BUNDLE_PATH']}"
70
- `chmod o-w #{Origen.root}` # Stops some annoying world writable warnings during install
71
- `chmod o-w #{Origen.root}/bin` if File.exist?("#{Origen.root}/bin")
72
- `chmod o-w #{Origen.root}/.bin` if File.exist?("#{Origen.root}/.bin")
73
-
74
- # Try again, this time updating the bundle
75
- if system(cmd)
76
- fixed = true
77
- elsif system 'bundle update'
78
- fixed = true
79
- end
80
-
81
- if File.exist?(ENV['BUNDLE_BIN'])
82
- `chmod o-w #{ENV['BUNDLE_BIN']}`
83
-
84
- # Make .bat versions of all executables, Bundler should really be doing this when running
85
- # on windows
86
- if Origen.os.windows?
87
- Dir.glob("#{ENV['BUNDLE_BIN']}/*").each do |bin|
88
- unless bin =~ /.bat$/
89
- bat = "#{bin}.bat"
90
- unless File.exist?(bat)
91
- File.open(bat, 'w') { |f| f.write('@"ruby.exe" "%~dpn0" %*') }
92
- end
93
- end
94
- end
95
- end
96
- end
97
-
98
- system 'origen -v' if fixed
99
- end
100
- end