origen_stil 0.2.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 49fbe57cd39de26d9c87fd212bd26eb551337803c161c63cfa1b828afa3a83e5
4
+ data.tar.gz: 3ca1ac84591f6473d30b33f54971ef06a3a4ed26edf8e0a6d6541bd20de580c9
5
+ SHA512:
6
+ metadata.gz: 1e3ec82d5dd20c6fb008d6849ec15e787206fa757dbc5ad3a48d5939994358162866eafc07e11c539683dc6b38ed977f2c466735dd2f7cf1f9260343f48fb8c1
7
+ data.tar.gz: 50b3486742351da2e69ee5277147bc3f67d3ac6c1154cb5f73ceedbdc33370e141cd480215b97a8154e06f3576692579302d4f88d47a153815cab84548e329f2
@@ -0,0 +1,100 @@
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
@@ -0,0 +1,103 @@
1
+ require 'origen'
2
+ class OrigenSTILApplication < Origen::Application
3
+
4
+ # See http://origen-sdk.org/origen/api/Origen/Application/Configuration.html
5
+ # for a full list of the configuration options available
6
+
7
+ # These attributes should never be changed, the duplication here will be resolved in future
8
+ # by condensing these attributes that do similar things
9
+ self.name = "origen_stil"
10
+ self.namespace = "OrigenSTIL"
11
+ config.name = "origen_stil"
12
+ config.initials = "OrigenSTIL"
13
+ # Change this to point to the revision control repository for this plugin
14
+ config.rc_url = "https://github.com/Origen-SDK/origen_stil.git"
15
+ config.release_externally = true
16
+
17
+ # To enable deployment of your documentation to a web server (via the 'origen web'
18
+ # command) fill in these attributes.
19
+ #config.web_directory = "git@github.com:Origen-SDK/Origen-SDK.github.io.git/origen_stil"
20
+ #config.web_domain = "http://origen-sdk.org/origen_stil"
21
+
22
+ # When false Origen will be less strict about checking for some common coding errors,
23
+ # it is recommended that you leave this to true for better feedback and easier debug.
24
+ # This will be the default setting in Origen v3.
25
+ config.strict_errors = true
26
+
27
+ # See: http://origen-sdk.org/origen/latest/guides/utilities/lint/
28
+ config.lint_test = {
29
+ # Require the lint tests to pass before allowing a release to proceed
30
+ run_on_tag: true,
31
+ # Auto correct violations where possible whenever 'origen lint' is run
32
+ auto_correct: true,
33
+ # Limit the testing for large legacy applications
34
+ #level: :easy,
35
+ # Run on these directories/files by default
36
+ #files: ["lib", "config/application.rb"],
37
+ }
38
+
39
+ config.semantically_version = true
40
+
41
+ # An example of how to set application specific LSF parameters
42
+ #config.lsf.project = "msg.te"
43
+
44
+ # An example of how to specify a prefix to add to all generated patterns
45
+ #config.pattern_prefix = "nvm"
46
+
47
+ # An example of how to add header comments to all generated patterns
48
+ #config.pattern_header do
49
+ # cc "This is a pattern created by the example origen application"
50
+ #end
51
+
52
+ # By default all generated output will end up in ./output.
53
+ # Here you can specify an alternative directory entirely, or make it dynamic such that
54
+ # the output ends up in a setup specific directory.
55
+ #config.output_directory do
56
+ # "#{Origen.root}/output/#{$dut.class}"
57
+ #end
58
+
59
+ # Similarly for the reference files, generally you want to setup the reference directory
60
+ # structure to mirror that of your output directory structure.
61
+ #config.reference_directory do
62
+ # "#{Origen.root}/.ref/#{$dut.class}"
63
+ #end
64
+
65
+ # This will automatically deploy your documentation after every tag
66
+ #def after_release_email(tag, note, type, selector, options)
67
+ # command = "origen web compile --remote --api"
68
+ # Dir.chdir Origen.root do
69
+ # system command
70
+ # end
71
+ #end
72
+
73
+ # Ensure that all tests pass before allowing a release to continue
74
+ #def validate_release
75
+ # if !system("origen specs") || !system("origen examples")
76
+ # puts "Sorry but you can't release with failing tests, please fix them and try again."
77
+ # exit 1
78
+ # else
79
+ # puts "All tests passing, proceeding with release process!"
80
+ # end
81
+ #end
82
+
83
+ # To enabled source-less pattern generation create a class (for example PatternDispatcher)
84
+ # to generate the pattern. This should return false if the requested pattern has been
85
+ # dispatched, otherwise Origen will proceed with looking up a pattern source as normal.
86
+ #def before_pattern_lookup(requested_pattern)
87
+ # PatternDispatcher.new.dispatch_or_return(requested_pattern)
88
+ #end
89
+
90
+ # If you use pattern iterators you may come across the case where you request a pattern
91
+ # like this:
92
+ # origen g example_pat_b0.atp
93
+ #
94
+ # However it cannot be found by Origen since the pattern name is actually example_pat_bx.atp
95
+ # In the case where the pattern cannot be found Origen will pass the name to this translator
96
+ # if it exists, and here you can make any substitutions to help Origen find the file you
97
+ # want. In this example any instances of _b\d, where \d means a number, are replaced by
98
+ # _bx.
99
+ #config.pattern_name_translator do |name|
100
+ # name.gsub(/_b\d/, "_bx")
101
+ #end
102
+
103
+ end
data/config/boot.rb ADDED
@@ -0,0 +1,24 @@
1
+ # This file is used to boot your plugin when it is running in standalone mode
2
+ # from its own workspace - i.e. when the plugin is being developed.
3
+ #
4
+ # It will not be loaded when the plugin is imported by a 3rd party app - in that
5
+ # case only lib/origen_stil.rb is loaded.
6
+ #
7
+ # Therefore this file can be used to load anything extra that you need to boot
8
+ # the development environment for this app. For example, this is typically used
9
+ # to load some additional test classes to use your plugin APIs so that they can
10
+ # be tested and/or interacted with in the console.
11
+ require "origen_stil"
12
+
13
+ module OrigenSTILDev
14
+ # Example of how to explicitly require a file
15
+ # require "origen_stil_dev/my_file"
16
+
17
+ # Load all files in the lib/origen_stil_dev directory.
18
+ # Note that there is no problem from requiring a file twice (Ruby will ignore
19
+ # the second require), so if you have a file that must be required first, then
20
+ # explicitly require it up above and then let this take care of the rest.
21
+ Dir.glob("#{File.dirname(__FILE__)}/../lib/origen_stil_dev/**/*.rb").sort.each do |file|
22
+ require file
23
+ end
24
+ end
@@ -0,0 +1,86 @@
1
+ # This file should be used to extend the origen with application specific commands
2
+
3
+ # Map any command aliases here, for example to allow 'origen ex' to refer to a
4
+ # command called execute you would add a reference as shown below:
5
+ aliases ={
6
+ # "ex" => "execute",
7
+ }
8
+
9
+ # The requested command is passed in here as @command, this checks it against
10
+ # the above alias table and should not be removed.
11
+ @command = aliases[@command] || @command
12
+
13
+ # Now branch to the specific task code
14
+ case @command
15
+
16
+ when "build"
17
+ Dir.chdir Origen.root do
18
+ system 'lbin/tt --force grammars/stil.treetop'
19
+ end
20
+ exit 0
21
+
22
+ # (Working) example of how to create an application specific comment, here to generate
23
+ # a tags file for you application to enable method definition lookup and similar within
24
+ # editors/IDEs
25
+ when "tags"
26
+ # Here the logic is just written in-line, alternatively it could be written in a
27
+ # dedicated file and required here, e.g.
28
+ #require "origen_stil/commands/my_command" # Would load file lib/origen_stil/commands/my_command.rb
29
+ Dir.chdir Origen.root do
30
+ system("ripper-tags -R")
31
+ end
32
+ # You must always exit upon successfully capturing and executing a command to prevent
33
+ # control flowing back to Origen
34
+ exit 0
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'])
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
72
+
73
+ # Always leave an else clause to allow control to fall back through to the
74
+ # Origen command handler.
75
+ else
76
+ # You probably want to also add the your commands to the help shown via
77
+ # origen -h, you can do this by assigning the required text to @application_commands
78
+ # before handing control back to Origen.
79
+ @application_commands = <<-EOT
80
+ tags Build a tags file for this app
81
+ build Build/compile the latest grammar file(s)
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
+ end
data/config/version.rb ADDED
@@ -0,0 +1,8 @@
1
+ module OrigenSTIL
2
+ MAJOR = 0
3
+ MINOR = 2
4
+ BUGFIX = 0
5
+ DEV = nil
6
+
7
+ VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
8
+ end
@@ -0,0 +1,122 @@
1
+ module OrigenSTIL
2
+ class Pattern
3
+ # Path to the STIL file on disk
4
+ attr_reader :path
5
+
6
+ def initialize(path, options = {})
7
+ unless File.exist?(path)
8
+ fail "STIL source file not found: #{path}"
9
+ end
10
+ @path = path
11
+ end
12
+
13
+ def execute(options = {})
14
+ timeset = nil
15
+ 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
26
+ end
27
+ vector[:repeat].cycles
28
+ end
29
+ end
30
+ end
31
+
32
+ # Returns frontmatter as an AST, note that this does not contain any
33
+ # vector-level information from Pattern blocks at the end of the file
34
+ def ast
35
+ @ast ||= Syntax::Parser.parse_file(path)
36
+ end
37
+
38
+ # Returns the contents of the file before the first Pattern block
39
+ # as a string
40
+ def frontmatter
41
+ @frontmatter ||= begin
42
+ fm = ''
43
+ File.foreach(path) do |line|
44
+ break if line =~ /^\s*Pattern /
45
+ fm << line
46
+ end
47
+ fm
48
+ end
49
+ end
50
+
51
+ # Add the pins defined in the STIL file to the DUT, unless it has them already.
52
+ # This will also call the add_pin_groups method automatically unless option
53
+ # :pin_group is set to false
54
+ def add_pins(options = {})
55
+ options = {
56
+ pin_groups: true
57
+ }.merge(options)
58
+ Processor::Pins.new.run(ast, dut, options)
59
+ add_pin_groups(options) unless options[:pin_groups] = false
60
+ end
61
+
62
+ def add_pin_groups(options = {})
63
+ Processor::PinGroups.new.run(ast, dut, options)
64
+ end
65
+
66
+ # Returns a hash containing all timesets (WaveformTables) defined in the STIL file
67
+ # { 'Waveset1' => { period_in_ns: 1000 } }
68
+ def timesets(options = {})
69
+ @timesets ||= Processor::Timesets.new.run(ast, options)
70
+ end
71
+
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]
104
+ end
105
+ yield vector
106
+ vector = { timeset: nil, comments: [], pindata: {}, repeat: 1 }
107
+ end
108
+ else
109
+ open = true if line =~ /^\s*Pattern #{pattern_name}\s*{/
110
+ end
111
+ end
112
+ end
113
+
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
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,16 @@
1
+ module OrigenSTIL
2
+ module Processor
3
+ class Base
4
+ include AST::Processor::Mixin
5
+
6
+ def handler_missing(node)
7
+ node.updated(nil, process_all(node.children))
8
+ end
9
+
10
+ def process(node)
11
+ return node unless node.respond_to?(:to_ast)
12
+ super
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ module OrigenSTIL
2
+ module Processor
3
+ class Pattern < Base
4
+ # Yields back the names of pattern blocks to be run as defined
5
+ # in the PatternExec and PatternBurst blocks within the given node
6
+ def run(node, options = {})
7
+ @bursts = {}
8
+ process(node)
9
+ if e = node.find(:pattern_exec)
10
+ e.find_all(:pattern_burst).each do |pb|
11
+ @bursts[pb.to_a[0]].each do |pattern|
12
+ yield pattern
13
+ end
14
+ end
15
+ else
16
+ fail 'No PatternExec block in the given AST!'
17
+ end
18
+ end
19
+
20
+ def on_pattern_burst(node)
21
+ name, pat_list = *node
22
+ if pat_list
23
+ @bursts[name] = []
24
+ @current_burst = @bursts[name]
25
+ process(pat_list)
26
+ end
27
+ end
28
+
29
+ def on_pat_list_item(node)
30
+ @current_burst << node.to_a[0]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ module OrigenSTIL
2
+ module Processor
3
+ class PinGroups < Base
4
+ attr_reader :model
5
+
6
+ # Adds pin groups from the given node to the given model
7
+ def run(node, model, options = {})
8
+ @model = model
9
+ node.find_all(:signal_groups).each do |signal_groups|
10
+ process(signal_groups)
11
+ end
12
+ end
13
+
14
+ def on_signal_group(node)
15
+ name, expr = *node
16
+ unless model.has_pin?(name)
17
+ ids = process(expr).to_a[0]
18
+ model.add_pin_group name.to_sym, *ids
19
+ end
20
+ end
21
+
22
+ def on_add(node)
23
+ lhs, rhs = *node
24
+ Array(process(lhs)) + Array(process(rhs))
25
+ end
26
+
27
+ def on_subtract(node)
28
+ fail 'Subract not implemented yet!'
29
+ end
30
+
31
+ def on_paren(node)
32
+ fail 'Parenthesis not implemented yet!'
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,41 @@
1
+ module OrigenSTIL
2
+ module Processor
3
+ class Pins < Base
4
+ attr_reader :model
5
+
6
+ # Adds pins from the given node to the given model
7
+ def run(node, model, options = {})
8
+ @model = model
9
+ process(node)
10
+ end
11
+
12
+ def on_signal(node)
13
+ name, direction = *node
14
+ if direction == 'In'
15
+ direction = :input
16
+ elsif direction == 'Out'
17
+ direction = :output
18
+ elsif direction == 'InOut'
19
+ direction = :io
20
+ else
21
+ direction = nil
22
+ end
23
+ # Currently does not add pins defined as "Supply" or "Pseudo"
24
+ if direction
25
+ # No need to do anything if it already responds to this pin name
26
+ unless model.has_pin?(name)
27
+ # Otherwise might need to add an alias for different casing being used
28
+ if model.has_pin?(name.downcase)
29
+ model.add_pin_alias(name.to_sym, name.downcase)
30
+ elsif model.has_pin?(name.upcase)
31
+ model.add_pin_alias(name.to_sym, name.upcase)
32
+ # Need to add a new pin
33
+ else
34
+ model.add_pin(name.to_sym, direction: direction)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ module OrigenSTIL
2
+ module Processor
3
+ class Timesets < Base
4
+ # Extract WaveformTables from the given AST and return as a hash of
5
+ # timesets and attributes
6
+ def run(node, options = {})
7
+ @timesets = {}
8
+ process(node)
9
+ @timesets
10
+ end
11
+
12
+ def on_waveform_table(node)
13
+ name = node.to_a[0]
14
+ # Pass on resolving the period for now, could involve parameter cross referencing
15
+ period = node.find(:period)
16
+ @timesets[name] = {}
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,116 @@
1
+ require 'ast'
2
+ require 'treetop'
3
+ module OrigenSTIL
4
+ module Syntax
5
+ class Node < ::AST::Node
6
+ attr_reader :input, :interval, :file, :number_of_lines
7
+
8
+ # Returns the value at the root of an AST node like this:
9
+ #
10
+ # node # => (module-def
11
+ # (module-name
12
+ # (SCALAR-ID "Instrument"))
13
+ #
14
+ # node.value # => "Instrument"
15
+ #
16
+ # No error checking is done and the caller is responsible for calling
17
+ # this only on compatible nodes
18
+ def value
19
+ val = children.first
20
+ val = val.children.first while val.respond_to?(:children)
21
+ val
22
+ end
23
+
24
+ # Returns the first child node of the given type that is found
25
+ def find(type)
26
+ nodes = find_all(type)
27
+ nodes.first
28
+ end
29
+
30
+ # Returns an array containing all child nodes of the given type(s)
31
+ def find_all(*types)
32
+ Extractor.new.process(self, types)
33
+ end
34
+
35
+ def line_number
36
+ input.line_of(interval.first)
37
+ end
38
+
39
+ def text_value
40
+ input[interval]
41
+ end
42
+
43
+ def directory
44
+ if file
45
+ Pathname.new(file).dirname
46
+ end
47
+ end
48
+
49
+ protected
50
+
51
+ # I'd rather see the true symbol
52
+ def fancy_type
53
+ @type
54
+ end
55
+ end
56
+
57
+ class Extractor
58
+ include ::AST::Processor::Mixin
59
+
60
+ attr_reader :types
61
+ attr_reader :results
62
+
63
+ def process(node, types = nil)
64
+ if types
65
+ @types = types
66
+ @results = []
67
+ # node = AST::Node.new(:wrapper, node) unless node.respond_to?(:to_ast)
68
+ end
69
+ super(node) if node.respond_to?(:to_ast)
70
+ results
71
+ end
72
+
73
+ def handler_missing(node)
74
+ @results << node if types.include?(node.type)
75
+ process_all(node.children)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ # Some helpers to create the to_ast methods in syntax nodes
82
+ module Treetop
83
+ module Runtime
84
+ class SyntaxNode
85
+ def n(type, *children)
86
+ properties = children.pop if children.last.is_a?(Hash)
87
+ properties ||= {}
88
+ properties[:input] ||= input
89
+ properties[:interval] ||= interval
90
+ properties[:file] ||= file
91
+ OrigenSTIL::Syntax::Node.new(type, children, properties)
92
+ end
93
+
94
+ def elements_to_ast(elmnts = elements)
95
+ elmnts.map do |e|
96
+ if e.respond_to?(:to_ast)
97
+ e.to_ast
98
+ elsif e.nonterminal? && !e.elements.empty?
99
+ elements_to_ast(e.elements)
100
+ end
101
+ end.compact.flatten
102
+ end
103
+
104
+ def number_of_lines(elmnts = elements)
105
+ elmnts.inject(0) do |sum, e|
106
+ lines = e.text_value.split("\n").size
107
+ sum + lines
108
+ end
109
+ end
110
+
111
+ def file
112
+ OrigenSTIL::Syntax::Parser.file
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,53 @@
1
+ require 'treetop'
2
+ require 'origen_stil/syntax/node'
3
+ module OrigenSTIL
4
+ module Syntax
5
+ class Parser
6
+ def self.parser
7
+ @parser ||= begin
8
+ require "#{Origen.root!}/grammars/stil"
9
+ GrammarParser.new
10
+ end
11
+ end
12
+
13
+ def self.parse_file(path, options = {})
14
+ stil = OrigenSTIL::Pattern.new(path)
15
+ parse(stil.frontmatter, options.merge(file: stil.path))
16
+ end
17
+
18
+ def self.parse(data, options = {})
19
+ @file = options[:file]
20
+ tree = parser.parse(data)
21
+
22
+ # If the AST is nil then there was an error during parsing,
23
+ # we need to report a simple error message to help the user
24
+ if tree.nil? && !options[:quiet]
25
+ parser.failure_reason =~ /^(Expected .+) (after|at)/m
26
+ @last_error_msg = []
27
+ @last_error_msg << "#{Regexp.last_match(1).gsub("\n", '$NEWLINE')}:" if Regexp.last_match(1)
28
+ if parser.failure_line >= data.lines.to_a.size
29
+ @last_error_msg << 'EOF'
30
+ else
31
+ @last_error_msg << data.lines.to_a[parser.failure_line - 1].gsub("\t", ' ')
32
+ end
33
+ @last_error_msg << "#{'~' * (parser.failure_column - 1)}^"
34
+ Origen.log.error "Failed parsing STIL file: #{file}"
35
+ @last_error_msg.each do |line|
36
+ Origen.log.error line.rstrip
37
+ end
38
+ end
39
+ if tree
40
+ tree.to_ast
41
+ end
42
+ end
43
+
44
+ def self.last_error_msg
45
+ @last_error_msg || []
46
+ end
47
+
48
+ def self.file
49
+ @file
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,68 @@
1
+ require 'origen'
2
+
3
+ Origen.register_acronym 'STIL'
4
+
5
+ require_relative '../config/application.rb'
6
+
7
+ module OrigenSTIL
8
+ # THIS FILE SHOULD ONLY BE USED TO LOAD RUNTIME DEPENDENCIES
9
+ # If this plugin has any development dependencies (e.g. dummy DUT or other models that are only used
10
+ # for testing), then these should be loaded from config/boot.rb
11
+
12
+ # Example of how to explicitly require a file
13
+ # require "origen_stil/my_file"
14
+
15
+ # Load all files in the lib/origen_stil directory.
16
+ # Note that there is no problem from requiring a file twice (Ruby will ignore
17
+ # the second require), so if you have a file that must be required first, then
18
+ # explicitly require it up above and then let this take care of the rest.
19
+ module Syntax
20
+ autoload :Node, 'origen_stil/syntax/node'
21
+ autoload :Parser, 'origen_stil/syntax/parser'
22
+ end
23
+
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'
30
+ end
31
+
32
+ autoload :Pattern, 'origen_stil/pattern'
33
+
34
+ # Execute the pattern vectors in the given STIL file, this will also call
35
+ # add_pins to ensure the pins are available so there is no need to call that
36
+ # separately
37
+ def self.execute(path, options = {})
38
+ options = {
39
+ # When true, any timeset changes from the STIL will be translated to tester.set_timeset
40
+ # calls, otherwise they will be ignored
41
+ set_timesets: false
42
+ }.merge(options)
43
+ # Bit of a hack, this is to lock in the current set of pins so that any added
44
+ # by the STIL are not included, the Origen model is in charge of pattern formatting
45
+ tester.current_pin_vals if tester
46
+ add_pins(path, options)
47
+ pattern(path).execute(options)
48
+ end
49
+
50
+ # Add pins (and pin groups) from the given STIL file to the current DUT
51
+ # unless they already exist
52
+ def self.add_pins(path, options = {})
53
+ pattern(path).add_pins(options)
54
+ end
55
+
56
+ # Returns an OrigenSTIL::Pattern instance for the given STIL file
57
+ def self.pattern(path_to_stil_file)
58
+ path = Pathname.new(path_to_stil_file).realpath.cleanpath.to_s
59
+ patterns[path] ||= OrigenSTIL::Pattern.new(path)
60
+ end
61
+
62
+ # @api private
63
+ def self.patterns
64
+ @patterns ||= {}
65
+ end
66
+ end
67
+
68
+ STIL = OrigenSTIL unless defined?(STIL)
@@ -0,0 +1,6 @@
1
+ # You can define any Rake tasks to support your application here (or in any file
2
+ # ending in .rake in this directory).
3
+ #
4
+ # Rake (Ruby Make) is very useful for creating build scripts, see this short video
5
+ # for a quick introduction:
6
+ # http://railscasts.com/episodes/66-custom-rake-tasks
@@ -0,0 +1,37 @@
1
+ % render "layouts/basic.html" do
2
+
3
+ %# HTML tags can be embedded in mark down files if you want to do specific custom
4
+ %# formatting like this, but in most cases that is not required.
5
+ <h1><%= Origen.app.namespace %> <span style="font-size: 14px">(<%= Origen.app.version %>)</span></h1>
6
+
7
+ ### Purpose
8
+
9
+ This plugin...
10
+
11
+ ### How To Install
12
+
13
+ In your Gemfile add:
14
+
15
+ ~~~ruby
16
+ gem "<%= Origen.app.name %>"
17
+ ~~~
18
+
19
+ or if your application is a plugin, then add this to your <code>.gemspec</code>
20
+
21
+ ~~~ruby
22
+ spec.add_runtime_dependency "<%= Origen.app.name %>", ">= <%= Origen.app.version %>"
23
+ ~~~
24
+
25
+ __NOTE:__ In the case of a plugin, you will also need to <code>require '<%= Origen.app.name %>'</code> somewhere in your environment.
26
+
27
+
28
+ ### How To Use
29
+
30
+ Add quickstart documentation here...
31
+
32
+
33
+ ### How To Setup a Development Environment
34
+
35
+ Describe how a developer would setup a new workspace for this plugin...
36
+
37
+ % end
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: <%= options[:title] || Origen.config.name %>
3
+ ---
4
+ <%= render "partials/navbar.html", tab: options[:tab] %>
5
+
6
+ <div class="row">
7
+ %# The markdown attribute is important if you are going to include content written
8
+ %# in markdown, without this is will be included verbatim
9
+ <div class="span12" markdown="1">
10
+ <%= yield %>
11
+
12
+ </div>
13
+ </div>
@@ -0,0 +1,20 @@
1
+ <nav class="navbar navbar-inverse navbar-fixed-top">
2
+ <div class="container">
3
+ <div class="navbar-header">
4
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
5
+ <span class="sr-only">Toggle navigation</span>
6
+ <span class="icon-bar"></span>
7
+ <span class="icon-bar"></span>
8
+ <span class="icon-bar"></span>
9
+ </button>
10
+ <a class="navbar-brand" href="<%= path "/" %>">Home</a>
11
+ </div>
12
+ <div id="navbar" class="collapse navbar-collapse">
13
+ <ul class="nav navbar-nav">
14
+ <li class="<%= options[:tab] == :api ? 'active' : '' %>"><a href="<%= path "/api/" %>">API</a></li>
15
+ <li class="<%= options[:tab] == :release ? 'active' : '' %>"><a href="<%= path "/release_notes" %>">Release Notes</a></li>
16
+ </ul>
17
+ <%= import "origen/web/logo.html" %>
18
+ </div><!--/.nav-collapse -->
19
+ </div>
20
+ </nav>
@@ -0,0 +1,5 @@
1
+ % render "layouts/basic.html", tab: :release do
2
+
3
+ <%= render "#{Origen.root}/doc/history" %>
4
+
5
+ % end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: origen_stil
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Stephen McGinty
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-09-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: origen
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.33.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.33.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: ast
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: treetop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - stephen.mcginty@nxp.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - bin/fix_my_workspace
63
+ - config/application.rb
64
+ - config/boot.rb
65
+ - config/commands.rb
66
+ - config/version.rb
67
+ - lib/origen_stil.rb
68
+ - lib/origen_stil/pattern.rb
69
+ - lib/origen_stil/processor/base.rb
70
+ - lib/origen_stil/processor/pattern.rb
71
+ - lib/origen_stil/processor/pin_groups.rb
72
+ - lib/origen_stil/processor/pins.rb
73
+ - lib/origen_stil/processor/timesets.rb
74
+ - lib/origen_stil/syntax/node.rb
75
+ - lib/origen_stil/syntax/parser.rb
76
+ - lib/tasks/origen_stil.rake
77
+ - templates/web/index.md.erb
78
+ - templates/web/layouts/_basic.html.erb
79
+ - templates/web/partials/_navbar.html.erb
80
+ - templates/web/release_notes.md.erb
81
+ homepage:
82
+ licenses: []
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '2'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 1.8.11
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.7.6
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Helpers to consume and generate test IP in STIL format (IEEE 1450)
104
+ test_files: []