verilog_gen 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -0
  3. data/README.md +22 -1
  4. data/Rakefile +20 -0
  5. data/bin/hdl_equal +82 -0
  6. data/bin/vgen +57 -1
  7. data/bin/vscan +354 -0
  8. data/demos/router/Makefile +11 -0
  9. data/demos/router/build/chip1_router.rb +50 -0
  10. data/demos/router/build/chip2_router.rb +33 -0
  11. data/demos/router/build/generic_router.rb +96 -0
  12. data/demos/router/rtl/fifo_ctrl.v +93 -0
  13. data/demos/router/rtl/flop_delay.v +37 -0
  14. data/demos/router/rtl/generic_mem.v +38 -0
  15. data/demos/router/rtl/router_ctrl.v +73 -0
  16. data/demos/router/rtl/rr_arb.v +55 -0
  17. data/demos/router/vendors/vendor1/mem_16nm_bist_ctrl.v +56 -0
  18. data/demos/router/vendors/vendor1/mem_16nm_ram4x64.v +50 -0
  19. data/demos/router/vendors/vendor1/mem_16nm_ram8x64.v +50 -0
  20. data/demos/router/vendors/vendor2/mem_16nm_bist_ctrl.v +56 -0
  21. data/demos/router/vendors/vendor2/mem_16nm_ram12x73.v +50 -0
  22. data/demos/router/vendors/vendor2/mem_16nm_ram4x73.v +50 -0
  23. data/docs/demo.md +142 -0
  24. data/docs/sst.md +76 -0
  25. data/features/cucumber.yml +1 -0
  26. data/features/hdl_equal/hello.feature +9 -0
  27. data/features/hdl_equal/leaf_compare.feature +11 -0
  28. data/features/hdl_equal/neg_compare.feature +17 -0
  29. data/features/hdl_equal/port_width_compare.feature +17 -0
  30. data/features/sprint1/hello.feature +9 -0
  31. data/features/sprint1/hier_connect_1.feature +81 -0
  32. data/features/sprint1/hier_connect_2.feature +91 -0
  33. data/features/sprint1/hier_connect_3.feature +90 -0
  34. data/features/sprint1/inhibit_port.feature +41 -0
  35. data/features/sprint1/input_connect.feature +79 -0
  36. data/features/sprint1/leaf_rename.feature +41 -0
  37. data/features/sprint1/new_leaf_design.erb +52 -0
  38. data/features/sprint1/output_connect.feature +79 -0
  39. data/features/sprint1/regex_port_rewrites.feature +43 -0
  40. data/features/sprint1/subrange_port.feature +43 -0
  41. data/features/sprint1/swap_leaf.feature +122 -0
  42. data/features/sprint1/tie_port.feature +40 -0
  43. data/features/sprint1/unused_port.feature +41 -0
  44. data/features/sprint1/vector_split.feature +41 -0
  45. data/features/sprint1/wire_connect.feature +46 -0
  46. data/features/sprint2/expression_net.feature +41 -0
  47. data/features/sprint2/fifo.feature +61 -0
  48. data/features/sprint2/wire_expression.feature +48 -0
  49. data/features/step_definitions/vgen_steps.rb +3 -0
  50. data/features/support/env.rb +3 -1
  51. data/features/vgen/add_child.feature +60 -0
  52. data/features/vgen/fifo_ctrl.feature +24 -0
  53. data/features/vgen/hello.feature +9 -0
  54. data/features/vgen/leaf_node.feature +15 -0
  55. data/features/vgen/output_dir.feature +19 -0
  56. data/features/vgen/simple_node.feature +24 -0
  57. data/features/vgen/thin_hookup.feature +22 -0
  58. data/features/vscan/bad_path.feature +9 -0
  59. data/features/vscan/class_override.feature +23 -0
  60. data/features/vscan/class_override_path.feature +23 -0
  61. data/features/vscan/complex_expressions.feature +47 -0
  62. data/features/vscan/data_types_2001.feature +36 -0
  63. data/features/vscan/data_types_sv.feature +53 -0
  64. data/features/vscan/hello.feature +9 -0
  65. data/features/vscan/hiearchy_path.feature +23 -0
  66. data/features/vscan/illegal_argument.feature +9 -0
  67. data/features/vscan/inout.feature +23 -0
  68. data/features/vscan/interface_nested.feature +53 -0
  69. data/features/vscan/interface_nested_no_out.feature +48 -0
  70. data/features/vscan/interface_param_default.feature +41 -0
  71. data/features/vscan/interface_param_override.feature +27 -0
  72. data/features/vscan/interface_port.feature +41 -0
  73. data/features/vscan/interface_sv.feature +35 -0
  74. data/features/vscan/leaf_1995.feature +27 -0
  75. data/features/vscan/leaf_2001.feature +25 -0
  76. data/features/vscan/leaf_negative_1995.feature +24 -0
  77. data/features/vscan/leaf_sv.feature +25 -0
  78. data/features/vscan/localparam_2001.feature +38 -0
  79. data/features/vscan/missing_parameter.feature +24 -0
  80. data/features/vscan/multiple_class.feature +9 -0
  81. data/features/vscan/multiple_flavors.feature +64 -0
  82. data/features/vscan/multiple_modules.feature +60 -0
  83. data/features/vscan/name_mismatch.feature +24 -0
  84. data/features/vscan/net_type.feature +67 -0
  85. data/features/vscan/parameter_override.feature +43 -0
  86. data/features/vscan/parameters_1995.feature +43 -0
  87. data/features/vscan/parameters_2001.feature +38 -0
  88. data/features/vscan/read_only.feature +19 -0
  89. data/features/vscan/reverse_vectors_1995.feature +33 -0
  90. data/features/vscan/single_line_1995.feature +24 -0
  91. data/features/vscan/vectors_1995.feature +33 -0
  92. data/features/vscan/vectors_2001.feature +29 -0
  93. data/features/vscan/vectors_sv.feature +31 -0
  94. data/lib/templates/helpers.rb +85 -0
  95. data/lib/templates/v2k_template.erb +6 -0
  96. data/lib/verilog_gen.rb +8 -3
  97. data/lib/verilog_gen/hdl_module.rb +274 -0
  98. data/lib/verilog_gen/hookup.rb +153 -0
  99. data/lib/verilog_gen/pin.rb +39 -0
  100. data/lib/verilog_gen/port.rb +109 -0
  101. data/lib/verilog_gen/proxy.rb +33 -0
  102. data/lib/verilog_gen/string.rb +38 -0
  103. data/lib/verilog_gen/version.rb +1 -1
  104. data/spec/fixture/generic_mem.v +38 -0
  105. data/spec/hdl_child_array_spec.rb +29 -0
  106. data/spec/hdl_hier_spec.rb +45 -0
  107. data/spec/hdl_hookup.spec +37 -0
  108. data/spec/hdl_module_spec.rb +117 -0
  109. data/spec/hdl_output_spec.rb +88 -0
  110. data/spec/hdl_port_spec.rb +35 -0
  111. data/spec/hdl_remove_child.spec +37 -0
  112. data/spec/pin_spec.rb +37 -0
  113. data/spec/port_spec.rb +90 -0
  114. data/spec/proxy_spec.rb +41 -0
  115. data/spec/spec_helper.rb +2 -0
  116. data/verilog_gen.gemspec +1 -1
  117. metadata +194 -8
  118. data/features/hello.feature +0 -8
  119. data/features/support/aruba.rb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6704b1a822e219b49e5f613a69d19a068810b62
4
- data.tar.gz: 717d1f7e1ed314da94394d46ae698253c6c955e3
3
+ metadata.gz: b1e2281d2daf631007d3ed1204c712bbdf24f6d8
4
+ data.tar.gz: 4a858282aaacc79cd2309f05b3d97083ad301438
5
5
  SHA512:
6
- metadata.gz: 081b28ce4d838b57a8cf8cce2d3bd13646a0a596f94b2612e6d616585ca9dcbd7fd8d11fbe54768b0d82c5ed116e5ba43b1f243e3de139178beeb6b68eea48e9
7
- data.tar.gz: 43a1dd83ad58d83fe6e65f476d29ac13721f1c5d918cbdf80e36e082c2e7011e65e2b1786050e0d0b5fb7173d8eed6733033e67d7b9af096b57dbb44450a6c4a
6
+ metadata.gz: df11fbfda6ee4d390b7c5698c95cf619d0a778ee5dfd6d8c11a02cc128f1bb464b6a5636ec99968df0001fe2d455aed2b7b6bbf97cd6176a174f9fba83af5309
7
+ data.tar.gz: 5c5369b66f49fa986a16977770387c9cc7fd6a02a0b82d225afb9ce0cda8076e5cc70652a103bcd4bf5caa84c835e77f07ca4546c0071f52b65aa6c1e04b43b9
data/Gemfile CHANGED
@@ -1,6 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  ruby '2.0.0'
4
+ group :development do
5
+ gem 'yard'
6
+ end
7
+
4
8
  group :test do
5
9
  gem 'rspec'
6
10
  gem 'cucumber'
data/README.md CHANGED
@@ -1,6 +1,27 @@
1
1
  # VerilogGen
2
2
 
3
- TODO: Write a gem description
3
+ Allows the user to declaratively create a verilog design. Using this tool
4
+ the user can create a logical model of the design. running the script will
5
+ render the logical view of the design.
6
+ Then for creating different views of the design (corresponding to different
7
+ chips, technologies, ...etc) the user inherits from the logical model. It
8
+ manipulates the logical instance hierarchy by adding/deleting/swapping the
9
+ modules. It then calls the 'vgen' script which creates the ports of the
10
+ modules due to the change.
11
+
12
+ To render it the script uses a default erb template. It is possible for the
13
+ user to use a custom template to insert custom system verilog logic.
14
+
15
+ Create a class HdlModule that corresponds to a verilog module. The class
16
+ HdlModule knows the ports and the instances of the design. The script vgen
17
+ can create the ports of the design by using the following default rule.
18
+ A. if there are multiple outputs then it is a primary output whose width
19
+ is the sum of all the busses.
20
+ B. If there is one output then it is an internal wire.
21
+ C. If there is 0 output then it is an primary input. The width of the port
22
+ is the largest width of the input pin.
23
+ If the user actually wanted the inputs to form a sub bus then user
24
+ would connect the ports to the pin manually.
4
25
 
5
26
  ## Installation
6
27
 
data/Rakefile CHANGED
@@ -1 +1,21 @@
1
1
  require "bundler/gem_tasks"
2
+ require "cucumber/rake/task"
3
+ require "rspec/core/rake_task"
4
+ require 'yard'
5
+
6
+ # Generate documentation
7
+ YARD::Rake::YardocTask.new
8
+
9
+ # Passing vscan tests.
10
+ # Ignore all work in progress (wip) and those under debug (jsd)
11
+ Cucumber::Rake::Task.new('vscan_test') do |task|
12
+ task.cucumber_opts = ["-r features", "features/vscan", " --tags ~@wip"]
13
+ end
14
+
15
+ # Run the vscan tests which are not yet implemented.
16
+ Cucumber::Rake::Task.new('vscan_wip') do |task|
17
+ task.cucumber_opts = ["-r features", "features/vscan", " --tags @wip"]
18
+ end
19
+
20
+ # Run the rspec tests.
21
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Compare the equality of 2 hdl module classes.
4
+ # The 2 classes are in separate files.
5
+
6
+ require 'pp'
7
+
8
+ if ARGV.size != 2
9
+ puts "error: you must specify 2 ruby hdl modules to compare."
10
+ exit 1
11
+ end
12
+
13
+ $LOAD_PATH.unshift File.expand_path("../../lib")
14
+ $LOAD_PATH.unshift File.expand_path("../lib")
15
+
16
+ require_relative "../lib/verilog_gen"
17
+
18
+ # Evaluate the class in 2 separate namespaces
19
+ # @return [Array] List of all derived class of hdl modules
20
+ def create_hdl_classes(ns, filename)
21
+ content = File.open(filename).read
22
+ eval """
23
+ module #{ns}
24
+ require 'verilog_gen'
25
+ # Hook to detect a subclass
26
+ class VerilogGen::HdlModule
27
+ @instances = []
28
+ def self.inherited(new_subclass)
29
+ @instances << new_subclass
30
+ end
31
+ def self.get
32
+ @instances
33
+ end
34
+ end
35
+ #{content}
36
+ end
37
+ """, binding, __FILE__, __LINE__
38
+ return VerilogGen::HdlModule.get
39
+ end
40
+
41
+ module Lhs; end
42
+ module Rhs; end
43
+
44
+ lhs = create_hdl_classes(Lhs, ARGV[0])
45
+ rhs = create_hdl_classes(Rhs, ARGV[1])
46
+
47
+ if lhs.size == 0
48
+ puts "No Hdl Module detected in source file:#{ARGV[0]}"
49
+ exit 1
50
+ end
51
+
52
+ if rhs.size == 0
53
+ puts "No Hdl Module detected in source file:#{ARGV[1]}"
54
+ exit 1
55
+ end
56
+
57
+ if lhs.size != rhs.size
58
+ puts "Number of entries #{lhs.size} on #{ARGV[0]} do not match
59
+ #{rhs.size} entries in #{ARGV[1]}"
60
+ exit 1
61
+ end
62
+
63
+ lhs.each_index do |i|
64
+ if lhs[i].ports == rhs[i].ports \
65
+ && lhs[i].child_instances == rhs[i].child_instances \
66
+ && lhs[i].module_name == rhs[i].module_name \
67
+ && lhs[i].proxy == rhs[i].proxy \
68
+ && lhs[i].file_name == rhs[i].file_name \
69
+ && lhs[i].parameters == rhs[i].parameters
70
+ exit 0
71
+ else
72
+ puts "Mismatched ports" unless lhs[i].ports == rhs[i].ports
73
+ puts "Mismatched child" unless lhs[i].child_instances == rhs[i].child_instances
74
+ puts "Mismatched mdule_name" unless lhs[i].module_name == rhs[i].module_name
75
+ puts "Mismatched proxy " unless lhs[i].proxy == rhs[i].proxy
76
+ puts "Mismatched file_name. Expect=#{lhs[i].file_name}, \
77
+ Got=#{rhs[i].file_name}" unless lhs[i].file_name == rhs[i].file_name
78
+ puts "Mismatched parameters:#{lhs[i].parameters}:#{rhs[i].parameters}" \
79
+ unless lhs[i].parameters == rhs[i].parameters
80
+ exit 1
81
+ end
82
+ end
data/bin/vgen CHANGED
@@ -1,2 +1,58 @@
1
1
  #!/usr/bin/env ruby
2
- puts "Verilog Rtl Generator"
2
+ require 'pp'
3
+ require 'optparse'
4
+ require 'fileutils'
5
+
6
+ # FIXME: Required till we install the gem
7
+ $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
8
+
9
+ # By default load the build directory
10
+ $LOAD_PATH.unshift("#{FileUtils.pwd}/build")
11
+
12
+ require 'verilog_gen'
13
+
14
+ options = {}
15
+ option_parser = OptionParser.new do |opts|
16
+ executable_name = File.basename($PROGRAM_NAME)
17
+ opts.banner = "Verilog RTL Generator
18
+
19
+ Usage: #{executable_name} [options] ruby_build_script
20
+ "
21
+ opts.on("-t top", "--top", "top level class name") do |top|
22
+ options[:top_class_name] = top
23
+ end
24
+ opts.on("-o outdir", "--outdir", "output directory name") do |outdir|
25
+ options[:output_dirname] = outdir
26
+ FileUtils.mkdir_p outdir
27
+ end
28
+ end
29
+
30
+ option_parser.parse!
31
+ unless options.key?(:top_class_name)
32
+ puts "error: you must supply the top level class name."
33
+ exit 1
34
+ end
35
+
36
+ options[:output_dirname] = "." unless options.key?(:output_dirname)
37
+
38
+ if ARGV.empty?
39
+ puts "error: you must supply the ruby build script."
40
+ exit 1
41
+ else
42
+ eval(File.open(ARGV[0]).read)
43
+ klass = Object.const_get(options[:top_class_name])
44
+
45
+ # Connect the ports and pins
46
+ VerilogGen.hookup klass
47
+
48
+ # Write out all the subclasses of hdl modules.
49
+ VerilogGen::HdlModule.get_subclasses.each do |sub_class|
50
+ unless sub_class.proxy
51
+ output_file = "#{options[:output_dirname]}/#{sub_class.module_name}.v"
52
+ File.open(output_file, 'w') do |fh|
53
+ fh.write(sub_class.render)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,354 @@
1
+ #!/usr/bin/perl
2
+ ## ----------------------------------------------------------------------
3
+ ## This script converts a verilog file into a ruby includable file which
4
+ ## contains the structure which defines the module definition of the given
5
+ ## verilog file.
6
+ ##
7
+ ## Input: Path to the verilog file
8
+ ## Parameter override declarations in format PARAM1=value
9
+ ## Class override declared using -class flag
10
+ ## Output: File in same directory as verilog file named <module>.rb
11
+ ## or <class_override>.rb if -class flag specified.
12
+ ##
13
+ ## Examples:
14
+ ## vscan subdir1/leaf.v
15
+ ## vscan PARAM1=7 PARAM2=9 leaf.v
16
+ ## vscan -class trunk leaf.v
17
+ ## ----------------------------------------------------------------------
18
+
19
+ require 5.005;
20
+ use FindBin qw($RealBin);
21
+ use lib "$RealBin/blib/arch";
22
+ use lib "$RealBin/blib/lib";
23
+ use lib "$RealBin";
24
+ use File::Basename;
25
+
26
+ use Verilog::Netlist;
27
+ use strict;
28
+
29
+ my $VERSION = "0.4.0";
30
+ my %PARAMETERS;
31
+ my $class_override = "";
32
+ my $verilog_file = "";
33
+
34
+ while( @ARGV ) {
35
+ my $option = shift @ARGV;
36
+ if( $option =~ /=/ ) {
37
+ ## A parameter is potentially being overwritten
38
+ (my $parameter, my $value) = split( /=/, $option, 2 );
39
+ $PARAMETERS{$parameter} = $value;
40
+ }
41
+ elsif( $option eq "-class" ) {
42
+ die "error: you can't specify more than one class overide.\n" if( $class_override );
43
+ $class_override = shift @ARGV;
44
+ }
45
+ else {
46
+ die "error: too many command line arguments.\n" if( $verilog_file );
47
+ $verilog_file = $option;
48
+ }
49
+ }
50
+ die "error: you must supply a leaf verilog module.\n" unless( $verilog_file );
51
+ die "error: file $verilog_file does not exist.\n" unless( -f $verilog_file );
52
+
53
+ ## And then process the Verilog file
54
+ &Convert_Verilog_To_Ruby( $class_override, $verilog_file );
55
+ exit(0);
56
+
57
+ ## --------------------------------------------------
58
+ ## Parse a verilog file and convert it into a ruby executable
59
+ ## that contains the structure which described the Verilog module's
60
+ ## declaration state
61
+ sub Convert_Verilog_To_Ruby {
62
+ my $class_override = shift @_;
63
+ my $in_file = shift @_;
64
+
65
+ ## Prepare for reading in verilog netlists
66
+ my $netlist = new Verilog::Netlist();
67
+ $netlist->read_file( filename=>$in_file );
68
+
69
+ ## And print any startup text needed
70
+ &Print_Header($VERSION);
71
+
72
+ ## Set the class to the override value, and then fix it later if
73
+ ## it wans't overridden:
74
+ my $class = $class_override;
75
+
76
+ ## Process all module declarations in the Verilog file
77
+ foreach my $module ($netlist->modules_sorted) {
78
+
79
+ ## Add the module name and class
80
+ $class = $module->name unless( $class_override );
81
+
82
+ &Print_Module($in_file, $class, $module->name);
83
+
84
+ ## Add override parameters
85
+ &Print_Parameters($module);
86
+
87
+ ## And information for each port
88
+ foreach my $port ($module->ports_sorted) {
89
+ ## if an 'interface', the port->direction is "interface"
90
+ (my $type, my $packed, my $unpacked) = &Parse_Port($port->data_type, $port->array, $module);
91
+ &Print_Port($port->name, $port->direction, $type, $packed, $unpacked);
92
+ }
93
+
94
+ ## Finish with any text required to end file creation
95
+ &Print_Trailer();
96
+ }
97
+
98
+ ## Process all interface declarations in the Verilog file
99
+ foreach my $interface ($netlist->interfaces_sorted) {
100
+
101
+ ## Start printing the class information for the interface
102
+ $class = $interface->name unless( $class_override );
103
+ &Print_Interface($in_file, $class, $interface->name);
104
+
105
+ ## Add override parameters
106
+ &Print_Parameters($interface);
107
+
108
+ ## And 'port' information for each interface
109
+ foreach my $port ($interface->ports_sorted) {
110
+ (my $type, my $packed, my $unpacked) = &Parse_Port($port->data_type, $port->array, $interface);
111
+ &Print_Port($port->name, $port->direction, $type, $packed, $unpacked);
112
+ }
113
+
114
+ ## Finish with any text required to end file creation
115
+ &Print_Trailer();
116
+ }
117
+
118
+ return;
119
+ }
120
+
121
+ ## --------------------------------------------------
122
+ ## A function to parse a port to determine the type of the
123
+ ## port, the packed portion of a vector declaration and the
124
+ ## unpacked portion of an array declaration.
125
+ sub Parse_Port {
126
+ my $packed_string = shift @_;
127
+ my $unpacked_string = shift @_;
128
+ my $module = shift @_;
129
+ my $type;
130
+ my $packed = "";
131
+ my $unpacked = "";
132
+
133
+ ## Remove Verilog comments if any
134
+ $packed_string =~ s/\/\/.*$//;
135
+
136
+ ## First determine the type
137
+ if( $packed_string =~ /^(.*?)\[/ ) {
138
+ $type = $1;
139
+ $type =~ s/\s+//g;
140
+ }
141
+ else {
142
+ ## Remove white spaces
143
+ $packed_string =~ s/\s+//g;
144
+ $type = $packed_string;
145
+ }
146
+ $type = "wire" if( $type eq "" ); ## default to wire if not specified
147
+
148
+ if( $packed_string =~ /:/ ) {
149
+ ## reg, wire, logic, bit:
150
+ ## vector containing parameters, mathematical functions, etc.
151
+ while( $packed_string =~ /\[/ ) {
152
+ $packed_string =~ s/^(.*?)\[//; ## strip everything up to and including [
153
+ (my $substr, $packed_string) = split( /\]/, $packed_string, 2 ); ## Get all to the left of first ]
154
+ ## Break into the LHS and RHS (of the colon)
155
+ (my $lhs, my $rhs) = split( /:/, $substr, 2 );
156
+ ## Convert each side into a numerical value
157
+ $lhs = &Resolve_Expression( $lhs, $module );
158
+ $rhs = &Resolve_Expression( $rhs, $module );
159
+ $packed .= "[$lhs:$rhs]";
160
+ }
161
+ } else {
162
+ ## reg, wire, logic, bit: single-bit
163
+ }
164
+
165
+ ## And then handle the unpacked (array) portion of the signal
166
+ ## Remove Verilog comments if any
167
+ $unpacked_string =~ s/\/\/.*$//;
168
+
169
+ while( $unpacked_string =~ /\[/ ) {
170
+ $unpacked_string =~ s/^(.*?)\[//; ## strip everything up to and including [
171
+ (my $substr, $unpacked_string) = split( /\]/, $unpacked_string, 2 ); ## Get all to the left of first ]
172
+ ## Break into the LHS and RHS (of the colon)
173
+ (my $lhs, my $rhs) = split( /:/, $substr, 2 );
174
+ ## Convert each side into a numerical value
175
+ $lhs = &Resolve_Expression( $lhs, $module );
176
+ $rhs = &Resolve_Expression( $rhs, $module );
177
+ $unpacked .= "[$lhs:$rhs]";
178
+ }
179
+
180
+ return( $type, $packed, $unpacked );
181
+ }
182
+
183
+ ## --------------------------------------------------
184
+ ## Function to replace parameters in a string and then
185
+ ## evaluate the mathematical result of the string post
186
+ ## parameter replacement.
187
+ sub Resolve_Expression {
188
+ my $string = shift @_;
189
+ my $module = shift @_;
190
+
191
+ ## Split the string on interesting Verilog supported mathematical operators
192
+ ## (which are: **, *, +, -, /, %, (, ) ). Note, $clog() is supported deeper
193
+ ## in the code below.
194
+ my @ITEMS = split( /(\*+|\+|\-|\/|\%|\(|\))/, $string );
195
+ ## Then substitute parameters with values (i.e., if one of
196
+ ## the items returned by the 'split' above is a defined
197
+ ## parameter, replace it in the array with the parameters value:
198
+ for( my $i=0; $i<=$#ITEMS; ++$i ) {
199
+ ## Is there an override of item from the command line?
200
+ ## if so, replace with the override value instead
201
+ if( $PARAMETERS{$ITEMS[$i]} ) {
202
+ ## Use override value
203
+ $ITEMS[$i] = $PARAMETERS{$ITEMS[$i]};
204
+ }
205
+ elsif( $ITEMS[$i] eq "\$clog2" ) {
206
+ ## Else, check if the item is a special Verilog function call:
207
+ ## Replace verilog log-base-2 function call with local version
208
+ $ITEMS[$i] = "&Log2";
209
+ }
210
+ else {
211
+ ## Else, check if there there is a net matching the text 'name' of the item?
212
+ my $net = $module->find_net($ITEMS[$i]);
213
+ ## If so, replace the item with the value of the net (parameter)
214
+ if( $net ) {
215
+ ## The value (for paremeters) might themselves be complex expressions
216
+ ## that need to be evaluated, call this function recursively before
217
+ ## proceeding:
218
+ $ITEMS[$i] = &Resolve_Expression( $net->value, $module );
219
+ }
220
+ }
221
+ ## Else, the item is either a number, mathematical operator, or something
222
+ ## that is not supported. Leave it unchanged.
223
+ }
224
+ ## Then evaluate the resultant string as a mathematical function. This will return
225
+ ## a NULL value if the evaluation fails (due to unsupported stuff in expression):
226
+ ## Because this is a PERL EVAL, the &Log2 function call that was placed in the expression
227
+ ## will calculate using the Log2 subroutine located in this program.
228
+ my $result = eval( join( "", @ITEMS ) );
229
+ die "error: I/O declaration using undefined parameter.\n" unless( $result ne "" );
230
+
231
+ return($result);
232
+ }
233
+
234
+ ## --------------------------------------------------
235
+ ## Ruby file header text
236
+ sub Print_Header {
237
+ print "# vscan v${VERSION}\n";
238
+ print "\n";
239
+ return;
240
+ }
241
+
242
+ ## --------------------------------------------------
243
+ ## Ruby file module name processing
244
+ sub Print_Module {
245
+ my $src_file = shift @_;
246
+ my $class_name = shift @_;
247
+ my $module_name = shift @_;
248
+ print "# --------------------------------------------------\n";
249
+ ## Make sure class name is all lower case with first letter capitalized
250
+ $class_name =~ tr/A-Z/a-z/;
251
+ $class_name = ucfirst( $class_name );
252
+ my $file_name = basename($src_file);
253
+ print "class $class_name < VerilogGen::HdlModule\n";
254
+ print " set_proxy true\n";
255
+ print " set_file_name \"${file_name}\"\n";
256
+ print " set_module_name \"${module_name}\"\n";
257
+
258
+ return;
259
+ }
260
+
261
+ ## --------------------------------------------------
262
+ ## Ruby file module name processing
263
+ sub Print_Interface {
264
+ my $src_file = shift @_;
265
+ my $class_name = shift @_;
266
+ my $interface_name = shift @_;
267
+ print "\n";
268
+ print "# --------------------------------------------------\n";
269
+ ## Make sure classs name is all lower case with first letter capitalized
270
+ $class_name =~ tr/A-Z/a-z/;
271
+ $class_name = ucfirst( $class_name );
272
+ print "class $class_name < VerilogGen::HdlInterface\n";
273
+ print " set_proxy true\n";
274
+ print " set_file_name \"${src_file}\"\n";
275
+ print " set_interface_name \"${interface_name}\"\n";
276
+
277
+ return;
278
+ }
279
+
280
+ ## --------------------------------------------------
281
+ ## Print out override parameters specified on the command line
282
+ sub Print_Parameters {
283
+ my $object = shift @_;
284
+
285
+ foreach my $override (sort keys %PARAMETERS) {
286
+ my $net = $object->find_net($override);
287
+ if( $net ) {
288
+ print " set_parameter ${override}: " . $PARAMETERS{$override} . "\n" if( $net->decl_type eq "parameter" );
289
+ }
290
+ }
291
+
292
+ return;
293
+ }
294
+
295
+ ## --------------------------------------------------
296
+ ## Ruby file port data type processing
297
+ sub Print_Port {
298
+ my $port_name = shift @_;
299
+ my $port_dir = shift @_;
300
+ my $port_type = shift @_;
301
+ my $packed_string = shift @_;
302
+ my $unpacked_string = shift @_;
303
+
304
+ ## Convert the port direction into a proper string
305
+ $port_dir = "input" if( $port_dir eq "in" );
306
+ $port_dir = "output" if( $port_dir eq "out" );
307
+ ## if 'inout', already in correct format
308
+
309
+ if( $port_dir eq "interface" ) {
310
+ print " add_interface \"${port_name}\", type: \"${port_type}\"\n";
311
+ }
312
+ else {
313
+ ## Print out the line of interest
314
+ print " add_port \"${port_name}\", direction: \"${port_dir}\", type: \"${port_type}\"";
315
+
316
+ ## Print out the packed side of the array and unpacked side of the array if they exist
317
+ print ", packed: \"${packed_string}\"" if( $packed_string );
318
+ print ", unpacked: \"${unpacked_string}\"" if( $unpacked_string );
319
+
320
+ ## Finish with carriage return
321
+ print "\n";
322
+ }
323
+
324
+ return;
325
+ }
326
+
327
+ ## --------------------------------------------------
328
+ ## Ruby file trailer text
329
+ sub Print_Trailer {
330
+ print "end\n";
331
+ print "\n";
332
+
333
+ return;
334
+ }
335
+
336
+ ## --------------------------------------------------
337
+ ## Log2 function used for signal vector resolution. In order to
338
+ ## match verilog, round up the answer
339
+ sub Log2 {
340
+ my $operand = shift @_;
341
+ my $result = &RoundUp( log($operand)/log(2) );
342
+
343
+ return( $result );
344
+ }
345
+
346
+ ## --------------------------------------------------
347
+ ## Helper function to round up a value
348
+ sub RoundUp {
349
+ my $n = shift @_;
350
+ my $n_roundedup = ($n==int($n)) ? $n : int($n+1);
351
+
352
+ return( $n_roundedup );
353
+ }
354
+