origen_stil 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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