origen_stil 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: []