verilog_gen 0.0.1 → 0.0.2

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.
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
+