origen_verilog 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
+ SHA1:
3
+ metadata.gz: 21754cb54ea4c8ce9b073264a796f2ff18e79740
4
+ data.tar.gz: 99caa65a1e1128d1cce33889e2333fc2c8df6b5a
5
+ SHA512:
6
+ metadata.gz: 80d9f2446499b1be8cdc77cfb2d33ae04a3a01f2a26de74535653354648b2b1108840f557295b07c98314d303aae69c37cdc0557000fa410cfdd2443ac15e5db
7
+ data.tar.gz: d34de4b2019034a6dac31b6b316b6e4cfbf8a807e78e27445923813f644d4954853a32bcf0649d196f9ea157952f492ec6572087e51a49e6cc864e4300dd1f12
@@ -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 OrigenVerilogApplication < 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_verilog"
10
+ self.namespace = "OrigenVerilog"
11
+ config.name = "origen_verilog"
12
+ config.initials = "OrigenVerilog"
13
+ # Change this to point to the revision control repository for this plugin
14
+ config.rc_url = "git@github.com:Origen-SDK/origen_verilog.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_verilog"
20
+ #config.web_domain = "http://origen-sdk.org/origen_verilog"
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_verilog.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_verilog"
12
+
13
+ module OrigenVerilogDev
14
+ # Example of how to explicitly require a file
15
+ # require "origen_verilog_dev/my_file"
16
+
17
+ # Load all files in the lib/origen_verilog_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_verilog_dev/**/*.rb").sort.each do |file|
22
+ require file
23
+ end
24
+ end
@@ -0,0 +1,89 @@
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
+ # (Working) example of how to create an application specific comment, here to generate
17
+ # a tags file for you application to enable method definition lookup and similar within
18
+ # editors/IDEs
19
+ when "tags"
20
+ # Here the logic is just written in-line, alternatively it could be written in a
21
+ # dedicated file and required here, e.g.
22
+ #require "origen_verilog/commands/my_command" # Would load file lib/origen_verilog/commands/my_command.rb
23
+ Dir.chdir Origen.root do
24
+ system("ripper-tags -R")
25
+ end
26
+ # You must always exit upon successfully capturing and executing a command to prevent
27
+ # control flowing back to Origen
28
+ exit 0
29
+
30
+ when "build"
31
+ Dir.chdir Origen.root do
32
+ system 'lbin/tt --force grammars/verilog.treetop'
33
+ system 'lbin/tt --force grammars/preprocessor.treetop'
34
+ end
35
+ exit 0
36
+
37
+ ## Example of how to make a command to run unit tests, this simply invokes RSpec on
38
+ ## the spec directory
39
+ when "specs"
40
+ ARGV.unshift "spec"
41
+ require "rspec"
42
+ require "rspec/autorun"
43
+ exit 0 # This will never be hit on a fail, RSpec will automatically exit 1
44
+
45
+ ## Example of how to make a command to run diff-based tests
46
+ #when "examples", "test"
47
+ # Origen.load_application
48
+ # status = 0
49
+ #
50
+ # # Compiler tests
51
+ # ARGV = %w(templates/example.txt.erb -t debug -r approved)
52
+ # load "origen/commands/compile.rb"
53
+ # # Pattern generator tests
54
+ # #ARGV = %w(some_pattern -t debug -r approved)
55
+ # #load "#{Origen.top}/lib/origen/commands/generate.rb"
56
+ #
57
+ # if Origen.app.stats.changed_files == 0 &&
58
+ # Origen.app.stats.new_files == 0 &&
59
+ # Origen.app.stats.changed_patterns == 0 &&
60
+ # Origen.app.stats.new_patterns == 0
61
+ #
62
+ # Origen.app.stats.report_pass
63
+ # else
64
+ # Origen.app.stats.report_fail
65
+ # status = 1
66
+ # end
67
+ # puts
68
+ # if @command == "test"
69
+ # Origen.app.unload_target!
70
+ # require "rspec"
71
+ # result = RSpec::Core::Runner.run(['spec'])
72
+ # status = status == 1 ? 1 : result
73
+ # end
74
+ # exit status # Exit with a 1 on the event of a failure per std unix result codes
75
+
76
+ # Always leave an else clause to allow control to fall back through to the
77
+ # Origen command handler.
78
+ else
79
+ # You probably want to also add the your commands to the help shown via
80
+ # origen -h, you can do this by assigning the required text to @application_commands
81
+ # before handing control back to Origen.
82
+ @application_commands = <<-EOT
83
+ tags Build a tags file for this app
84
+ build Build/compile the latest grammar files
85
+ specs Run the specs (tests), -c will enable coverage
86
+ EOT
87
+ # examples Run the examples (tests), -c will enable coverage
88
+ # test Run both specs and examples, -c will enable coverage
89
+ end
data/config/version.rb ADDED
@@ -0,0 +1,8 @@
1
+ module OrigenVerilog
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,34 @@
1
+ require 'origen'
2
+ require_relative '../config/application.rb'
3
+ module OrigenVerilog
4
+ # THIS FILE SHOULD ONLY BE USED TO LOAD RUNTIME DEPENDENCIES
5
+ # If this plugin has any development dependencies (e.g. dummy DUT or other models that are only used
6
+ # for testing), then these should be loaded from config/boot.rb
7
+
8
+ autoload :Parser, 'origen_verilog/parser'
9
+ autoload :Node, 'origen_verilog/node'
10
+ autoload :Processor, 'origen_verilog/processor'
11
+ autoload :TopLevel, 'origen_verilog/top_level'
12
+
13
+ module Verilog
14
+ autoload :Parser, 'origen_verilog/verilog/parser'
15
+ autoload :Node, 'origen_verilog/verilog/node'
16
+ autoload :Processor, 'origen_verilog/verilog/processor'
17
+ autoload :Writer, 'origen_verilog/verilog/writer'
18
+ autoload :Evaluator, 'origen_verilog/verilog/evaluator'
19
+ end
20
+ module Preprocessor
21
+ autoload :Parser, 'origen_verilog/preprocessor/parser'
22
+ autoload :Node, 'origen_verilog/preprocessor/node'
23
+ autoload :Processor, 'origen_verilog/preprocessor/processor'
24
+ autoload :Writer, 'origen_verilog/preprocessor/writer'
25
+ end
26
+
27
+ # Returns an AST for the given file
28
+ def self.parse_file(file, options = {})
29
+ # Evaluates all compiler directives
30
+ ast = Preprocessor::Parser.parse_file(file).process
31
+ # Now parse as verilog
32
+ Verilog::Parser.parse(ast.to_s)
33
+ end
34
+ end
@@ -0,0 +1,115 @@
1
+ require 'ast'
2
+ require 'treetop'
3
+ module OrigenVerilog
4
+ class Node < ::AST::Node
5
+ attr_reader :input, :interval, :file
6
+
7
+ # Returns the value at the root of an AST node like this:
8
+ #
9
+ # node # => (module-def
10
+ # (module-name
11
+ # (SCALAR-ID "Instrument"))
12
+ #
13
+ # node.value # => "Instrument"
14
+ #
15
+ # No error checking is done and the caller is responsible for calling
16
+ # this only on compatible nodes
17
+ def value
18
+ val = children.first
19
+ val = val.children.first while val.respond_to?(:children)
20
+ val
21
+ end
22
+
23
+ # Returns the first child node of the given type that is found
24
+ def find(type)
25
+ nodes = find_all(type)
26
+ nodes.first
27
+ end
28
+
29
+ # Returns an array containing all child nodes of the given type(s)
30
+ def find_all(*types)
31
+ Extractor.new.process(self, types)
32
+ end
33
+
34
+ def line_number
35
+ input.line_of(interval.first)
36
+ end
37
+
38
+ def text_value
39
+ input[interval]
40
+ end
41
+
42
+ def directory
43
+ if file
44
+ Pathname.new(file).dirname
45
+ end
46
+ end
47
+
48
+ protected
49
+
50
+ # I'd rather see the true symbol
51
+ def fancy_type
52
+ @type
53
+ end
54
+ end
55
+
56
+ class Extractor
57
+ include ::AST::Processor::Mixin
58
+
59
+ attr_reader :types
60
+ attr_reader :results
61
+
62
+ def process(node, types = nil)
63
+ if types
64
+ @types = types
65
+ @results = []
66
+ # node = AST::Node.new(:wrapper, node) unless node.respond_to?(:to_ast)
67
+ end
68
+ super(node) if node.respond_to?(:to_ast)
69
+ results
70
+ end
71
+
72
+ def handler_missing(node)
73
+ @results << node if types.include?(node.type)
74
+ process_all(node.children)
75
+ end
76
+ end
77
+ end
78
+
79
+ # Some helpers to create the to_ast methods in syntax nodes
80
+ module Treetop
81
+ def self.origen_verilog_parser=(klass)
82
+ @origen_verilog_parser = klass
83
+ end
84
+
85
+ def self.origen_verilog_parser
86
+ @origen_verilog_parser
87
+ end
88
+
89
+ module Runtime
90
+ class SyntaxNode
91
+ def n(type, *children)
92
+ properties = children.pop if children.last.is_a?(Hash)
93
+ properties ||= {}
94
+ properties[:input] ||= input
95
+ properties[:interval] ||= interval
96
+ properties[:file] ||= file
97
+ Treetop.origen_verilog_parser.node.new(type, children, properties || {})
98
+ end
99
+
100
+ def elements_to_ast(elmnts = elements)
101
+ elmnts.map do |e|
102
+ if e.respond_to?(:to_ast)
103
+ e.to_ast
104
+ elsif e.nonterminal? && !e.elements.empty?
105
+ elements_to_ast(e.elements)
106
+ end
107
+ end.compact.flatten
108
+ end
109
+
110
+ def file
111
+ Treetop.origen_verilog_parser.file
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,43 @@
1
+ require 'treetop'
2
+ require 'origen_verilog/node'
3
+ module OrigenVerilog
4
+ class Parser
5
+ def self.parse_file(path, options = {})
6
+ parse(File.read(path), options.merge(file: path))
7
+ end
8
+
9
+ def self.parse(data, options = {})
10
+ # This will be appended to all nodes if supplied
11
+ @file = options[:file]
12
+ Treetop.origen_verilog_parser = self
13
+ tree = parser.parse(data)
14
+
15
+ # If the AST is nil then there was an error during parsing
16
+ # we need to report a simple error message to help the user
17
+ if tree.nil? && !options[:quiet]
18
+ parser.failure_reason =~ /^(Expected .+) (after|at)/m
19
+ @last_error_msg = []
20
+ @last_error_msg << "#{Regexp.last_match(1).gsub("\n", '$NEWLINE')}:" if Regexp.last_match(1)
21
+ if parser.failure_line >= data.lines.to_a.size
22
+ @last_error_msg << 'EOF'
23
+ else
24
+ @last_error_msg << data.lines.to_a[parser.failure_line - 1].gsub("\t", ' ')
25
+ end
26
+ @last_error_msg << "#{'~' * (parser.failure_column - 1)}^"
27
+ puts "Failed parsing Verilog file: #{file}"
28
+ puts @last_error_msg
29
+ end
30
+ if tree
31
+ tree.to_ast
32
+ end
33
+ end
34
+
35
+ def self.last_error_msg
36
+ @last_error_msg || []
37
+ end
38
+
39
+ def self.file
40
+ @file
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ module OrigenVerilog
2
+ module Preprocessor
3
+ class Node < OrigenVerilog::Node
4
+ def process(file = nil, env = {})
5
+ file, env = nil, file if file.is_a?(Hash)
6
+ ast = Processor.new.run(self, env)
7
+ if file
8
+ Writer.new.run(file, ast)
9
+ else
10
+ ast
11
+ end
12
+ end
13
+
14
+ def to_s
15
+ Writer.new.to_s(self)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'treetop'
2
+ module OrigenVerilog
3
+ module Preprocessor
4
+ # Responsible for parsing a Verilog file to an AST
5
+ class Parser < OrigenVerilog::Parser
6
+ def self.node
7
+ OrigenVerilog::Preprocessor::Node
8
+ end
9
+
10
+ def self.parser
11
+ @parser ||= begin
12
+ require "#{Origen.root!}/grammars/verilog"
13
+ require "#{Origen.root!}/grammars/preprocessor"
14
+ GrammarParser.new
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,115 @@
1
+ module OrigenVerilog
2
+ module Preprocessor
3
+ class Processor < OrigenVerilog::Processor
4
+ def run(ast, env)
5
+ @env = env
6
+ process(ast)
7
+ end
8
+
9
+ def on_include(node)
10
+ path = node.to_a[0]
11
+ file = path if File.exist?(path)
12
+ unless file
13
+ dir = ([Dir.pwd] + Array(env[:source_dirs])).find do |dir|
14
+ f = File.join(dir, path)
15
+ File.exist?(f)
16
+ end
17
+ file = File.join(dir, path) if dir
18
+ end
19
+ unless file
20
+ puts "The file #{path} could not be found!"
21
+ puts "#{node.file}:#{node.line_number}"
22
+ exit 1
23
+ end
24
+ inline process(Parser.parse_file(file)).children
25
+ end
26
+
27
+ def on_define(node)
28
+ n = node.find(:name)
29
+ name = n.to_a[0]
30
+ if a = n.find(:arguments)
31
+ args = a.to_a
32
+ end
33
+ if n = node.find(:text)
34
+ text = n.to_a.first
35
+ end
36
+ env[name] = Define.new(name: name, args: args, text: text)
37
+ nil
38
+ end
39
+
40
+ def on_undef(node)
41
+ env[node.to_a[0]] = nil
42
+ end
43
+
44
+ def on_ifdef(node)
45
+ elsif_nodes = node.find_all(:elsif)
46
+ else_node = node.find(:else)
47
+ enable, *nodes = *node
48
+ if node.type == :ifdef ? env[enable] : !env[enable]
49
+ inline(process_all(nodes))
50
+ else
51
+ elsif_nodes.each do |elsif_node|
52
+ enable, *nodes = *elsif_node
53
+ if env[enable]
54
+ return inline(process_all(nodes))
55
+ end
56
+ end
57
+ if else_node
58
+ inline(process_all(else_node.children))
59
+ end
60
+ end
61
+ end
62
+ alias_method :on_ifndef, :on_ifdef
63
+
64
+ def on_macro_reference(node)
65
+ if define = env[node.to_a[0]]
66
+ if a = node.find(:arguments)
67
+ args = a.to_a
68
+ end
69
+ node.updated(:text_block, [define.value(node, args)])
70
+
71
+ else
72
+ puts "A reference has been made to macro #{node.to_a[0]} but it hasn't been defined yet!"
73
+ puts "#{node.file}:#{node.line_number}"
74
+ exit 1
75
+ end
76
+ end
77
+
78
+ def on_else(node)
79
+ # Do nothing, will be processed by the ifdef handler if required
80
+ end
81
+ alias_method :on_elsif, :on_else
82
+
83
+ private
84
+
85
+ class Define
86
+ attr_reader :name, :args, :text
87
+
88
+ def initialize(options)
89
+ @name = options[:name]
90
+ @args = options[:args] || []
91
+ @text = options[:text]
92
+ end
93
+
94
+ def value(node, arguments)
95
+ return '' unless text
96
+ arguments = Array(arguments)
97
+ unless args.size == arguments.size
98
+ puts "Macro #{node.to_a[0]} required #{args.size} arguments, but only #{arguments.size} have been given!"
99
+ puts "#{node.file}:#{node.line_number}"
100
+ exit 1
101
+ end
102
+ t = text
103
+ args.each_with_index do |a, i|
104
+ t = t.gsub(a, arguments[i])
105
+ end
106
+ t
107
+ end
108
+ end
109
+
110
+ def env
111
+ @env
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,35 @@
1
+ module OrigenVerilog
2
+ module Preprocessor
3
+ class Writer < OrigenVerilog::Processor
4
+ # Write the given ast to the given file
5
+ def run(file, ast)
6
+ File.open(file, 'w') do |file|
7
+ @file = file
8
+ process(ast)
9
+ end
10
+ end
11
+
12
+ # Write the given ast to a string and returns it
13
+ def to_s(ast)
14
+ @file = ''
15
+ process(ast)
16
+ @file
17
+ end
18
+
19
+ def on_text_block(node)
20
+ if f.is_a?(String)
21
+ f << node.to_a[0]
22
+ else
23
+ f.write(node.to_a[0])
24
+ end
25
+ end
26
+ alias_method :on_comment, :on_text_block
27
+
28
+ private
29
+
30
+ def f
31
+ @file
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,67 @@
1
+ require 'ast'
2
+ module OrigenVerilog
3
+ # The base processor, this provides a default handler for
4
+ # all node types and will not make any changes to the AST,
5
+ # i.e. an equivalent AST will be returned by the process method.
6
+ #
7
+ # Child classes of this should be used to implement additional
8
+ # processors to modify or otherwise work with the AST.
9
+ #
10
+ # @see http://www.rubydoc.info/gems/ast/2.0.0/AST/Processor
11
+ class Processor
12
+ include ::AST::Processor::Mixin
13
+
14
+ def run(node)
15
+ process(node)
16
+ end
17
+
18
+ # Override the default implementation of this, to allow arrays
19
+ # to be returned and when a handler returns nil the node is removed
20
+ def process(node)
21
+ return if node.nil?
22
+ return node unless node.respond_to?(:to_ast)
23
+
24
+ node = node.to_ast
25
+
26
+ # Invoke a specific handler
27
+ on_handler = :"on_#{node.type}"
28
+ if respond_to? on_handler
29
+ new_node = send on_handler, node
30
+ else
31
+ new_node = handler_missing(node)
32
+ end
33
+
34
+ new_node if new_node
35
+ end
36
+
37
+ # Some of our processors remove a wrapping node from the AST, returning
38
+ # a node of type :inline containing the children which should be inlined.
39
+ # Here we override the default version of this method to deal with handlers
40
+ # that return an inline node in place of a regular node.
41
+ def process_all(nodes)
42
+ results = []
43
+ nodes.to_a.each do |node|
44
+ n = process(node)
45
+ if n
46
+ if n.is_a?(Inline)
47
+ results += n
48
+ else
49
+ results << n
50
+ end
51
+ end
52
+ end
53
+ results
54
+ end
55
+
56
+ def handler_missing(node)
57
+ node.updated(nil, process_all(node.children))
58
+ end
59
+
60
+ def inline(nodes)
61
+ Inline.new(nodes)
62
+ end
63
+
64
+ class Inline < ::Array
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,28 @@
1
+ module OrigenVerilog
2
+ class TopLevel
3
+ include Origen::TopLevel
4
+
5
+ attr_reader :name
6
+
7
+ def initialize(options = {})
8
+ @name = options[:ast].to_a[0]
9
+
10
+ options[:ast].pins.each do |node|
11
+ name = node.to_a.last
12
+ if node.type == :input_declaration
13
+ direction = :input
14
+ elsif node.type == :ouput_declaration
15
+ direction = :output
16
+ else
17
+ direction = :io
18
+ end
19
+ if r = node.find(:range)
20
+ size = r.to_a[0] - r.to_a[1] + 1
21
+ else
22
+ size = 1
23
+ end
24
+ add_pin name, direction: direction, size: size
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module OrigenVerilog
2
+ module Verilog
3
+ class Evaluator < OrigenVerilog::Processor
4
+ def run(ast)
5
+ ast.updated(nil, process_all(ast.children))
6
+ end
7
+
8
+ def on_decimal_number(node)
9
+ process(node.value)
10
+ end
11
+
12
+ def on_constant_primary(node)
13
+ process(node.value)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ module OrigenVerilog
2
+ module Verilog
3
+ class Node < OrigenVerilog::Node
4
+ def process(file = nil, env = {})
5
+ file, env = nil, file if file.is_a?(Hash)
6
+ ast = Processor.new.run(self, env)
7
+ if file
8
+ Writer.new.run(file, ast)
9
+ else
10
+ ast
11
+ end
12
+ end
13
+
14
+ # Returns an array containing the names of all top-level modules in
15
+ # the AST
16
+ def module_names
17
+ find_all(:module_declaration).map { |n| n.to_a[0] }
18
+ end
19
+
20
+ # Returns an array containing the AST node for all modules in the AST
21
+ def modules
22
+ find_all(:module_declaration)
23
+ end
24
+
25
+ # Returns the AST node for the module with the given name
26
+ def module(name)
27
+ find_all(:module_declaration).find { |n| n.to_a[0].to_s == name.to_s }
28
+ end
29
+
30
+ # Returns an array containing all input, output and inout AST nodes
31
+ def pins
32
+ find_all(:input_declaration, :output_declaration, :inout_declaration)
33
+ end
34
+
35
+ # Evaluates all functions and turns numbers into Ruby literals
36
+ def evaluate
37
+ Evaluator.new.run(self)
38
+ end
39
+
40
+ def to_top_level
41
+ unless type == :module_declaration
42
+ fail 'Currently only modules support the to_model method'
43
+ end
44
+ TopLevel.new(ast: evaluate)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,18 @@
1
+ require 'treetop'
2
+ module OrigenVerilog
3
+ module Verilog
4
+ # Responsible for parsing a Verilog file to an AST
5
+ class Parser < OrigenVerilog::Parser
6
+ def self.node
7
+ OrigenVerilog::Verilog::Node
8
+ end
9
+
10
+ def self.parser
11
+ @parser ||= begin
12
+ require "#{Origen.root!}/grammars/verilog"
13
+ GrammarParser.new
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module OrigenVerilog
2
+ module Verilog
3
+ class Processor < OrigenVerilog::Processor
4
+ def run(ast, env)
5
+ @env = env
6
+ process(ast)
7
+ end
8
+
9
+ private
10
+
11
+ def env
12
+ @env
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ module OrigenVerilog
2
+ module Verilog
3
+ class Writer < OrigenVerilog::Processor
4
+ end
5
+ end
6
+ end
@@ -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,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: origen_verilog
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: 2017-12-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ast
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: treetop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - stephen.f.mcginty@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - bin/fix_my_workspace
49
+ - config/application.rb
50
+ - config/boot.rb
51
+ - config/commands.rb
52
+ - config/version.rb
53
+ - lib/origen_verilog.rb
54
+ - lib/origen_verilog/node.rb
55
+ - lib/origen_verilog/parser.rb
56
+ - lib/origen_verilog/preprocessor/node.rb
57
+ - lib/origen_verilog/preprocessor/parser.rb
58
+ - lib/origen_verilog/preprocessor/processor.rb
59
+ - lib/origen_verilog/preprocessor/writer.rb
60
+ - lib/origen_verilog/processor.rb
61
+ - lib/origen_verilog/top_level.rb
62
+ - lib/origen_verilog/verilog/evaluator.rb
63
+ - lib/origen_verilog/verilog/node.rb
64
+ - lib/origen_verilog/verilog/parser.rb
65
+ - lib/origen_verilog/verilog/processor.rb
66
+ - lib/origen_verilog/verilog/writer.rb
67
+ - lib/tasks/origen_verilog.rake
68
+ - templates/web/index.md.erb
69
+ - templates/web/layouts/_basic.html.erb
70
+ - templates/web/partials/_navbar.html.erb
71
+ - templates/web/release_notes.md.erb
72
+ homepage:
73
+ licenses: []
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '2'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 1.8.11
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.5.2
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: A parser and generator for Verilog (IEEE 1364)
95
+ test_files: []