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.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/README.md +22 -1
- data/Rakefile +20 -0
- data/bin/hdl_equal +82 -0
- data/bin/vgen +57 -1
- data/bin/vscan +354 -0
- data/demos/router/Makefile +11 -0
- data/demos/router/build/chip1_router.rb +50 -0
- data/demos/router/build/chip2_router.rb +33 -0
- data/demos/router/build/generic_router.rb +96 -0
- data/demos/router/rtl/fifo_ctrl.v +93 -0
- data/demos/router/rtl/flop_delay.v +37 -0
- data/demos/router/rtl/generic_mem.v +38 -0
- data/demos/router/rtl/router_ctrl.v +73 -0
- data/demos/router/rtl/rr_arb.v +55 -0
- data/demos/router/vendors/vendor1/mem_16nm_bist_ctrl.v +56 -0
- data/demos/router/vendors/vendor1/mem_16nm_ram4x64.v +50 -0
- data/demos/router/vendors/vendor1/mem_16nm_ram8x64.v +50 -0
- data/demos/router/vendors/vendor2/mem_16nm_bist_ctrl.v +56 -0
- data/demos/router/vendors/vendor2/mem_16nm_ram12x73.v +50 -0
- data/demos/router/vendors/vendor2/mem_16nm_ram4x73.v +50 -0
- data/docs/demo.md +142 -0
- data/docs/sst.md +76 -0
- data/features/cucumber.yml +1 -0
- data/features/hdl_equal/hello.feature +9 -0
- data/features/hdl_equal/leaf_compare.feature +11 -0
- data/features/hdl_equal/neg_compare.feature +17 -0
- data/features/hdl_equal/port_width_compare.feature +17 -0
- data/features/sprint1/hello.feature +9 -0
- data/features/sprint1/hier_connect_1.feature +81 -0
- data/features/sprint1/hier_connect_2.feature +91 -0
- data/features/sprint1/hier_connect_3.feature +90 -0
- data/features/sprint1/inhibit_port.feature +41 -0
- data/features/sprint1/input_connect.feature +79 -0
- data/features/sprint1/leaf_rename.feature +41 -0
- data/features/sprint1/new_leaf_design.erb +52 -0
- data/features/sprint1/output_connect.feature +79 -0
- data/features/sprint1/regex_port_rewrites.feature +43 -0
- data/features/sprint1/subrange_port.feature +43 -0
- data/features/sprint1/swap_leaf.feature +122 -0
- data/features/sprint1/tie_port.feature +40 -0
- data/features/sprint1/unused_port.feature +41 -0
- data/features/sprint1/vector_split.feature +41 -0
- data/features/sprint1/wire_connect.feature +46 -0
- data/features/sprint2/expression_net.feature +41 -0
- data/features/sprint2/fifo.feature +61 -0
- data/features/sprint2/wire_expression.feature +48 -0
- data/features/step_definitions/vgen_steps.rb +3 -0
- data/features/support/env.rb +3 -1
- data/features/vgen/add_child.feature +60 -0
- data/features/vgen/fifo_ctrl.feature +24 -0
- data/features/vgen/hello.feature +9 -0
- data/features/vgen/leaf_node.feature +15 -0
- data/features/vgen/output_dir.feature +19 -0
- data/features/vgen/simple_node.feature +24 -0
- data/features/vgen/thin_hookup.feature +22 -0
- data/features/vscan/bad_path.feature +9 -0
- data/features/vscan/class_override.feature +23 -0
- data/features/vscan/class_override_path.feature +23 -0
- data/features/vscan/complex_expressions.feature +47 -0
- data/features/vscan/data_types_2001.feature +36 -0
- data/features/vscan/data_types_sv.feature +53 -0
- data/features/vscan/hello.feature +9 -0
- data/features/vscan/hiearchy_path.feature +23 -0
- data/features/vscan/illegal_argument.feature +9 -0
- data/features/vscan/inout.feature +23 -0
- data/features/vscan/interface_nested.feature +53 -0
- data/features/vscan/interface_nested_no_out.feature +48 -0
- data/features/vscan/interface_param_default.feature +41 -0
- data/features/vscan/interface_param_override.feature +27 -0
- data/features/vscan/interface_port.feature +41 -0
- data/features/vscan/interface_sv.feature +35 -0
- data/features/vscan/leaf_1995.feature +27 -0
- data/features/vscan/leaf_2001.feature +25 -0
- data/features/vscan/leaf_negative_1995.feature +24 -0
- data/features/vscan/leaf_sv.feature +25 -0
- data/features/vscan/localparam_2001.feature +38 -0
- data/features/vscan/missing_parameter.feature +24 -0
- data/features/vscan/multiple_class.feature +9 -0
- data/features/vscan/multiple_flavors.feature +64 -0
- data/features/vscan/multiple_modules.feature +60 -0
- data/features/vscan/name_mismatch.feature +24 -0
- data/features/vscan/net_type.feature +67 -0
- data/features/vscan/parameter_override.feature +43 -0
- data/features/vscan/parameters_1995.feature +43 -0
- data/features/vscan/parameters_2001.feature +38 -0
- data/features/vscan/read_only.feature +19 -0
- data/features/vscan/reverse_vectors_1995.feature +33 -0
- data/features/vscan/single_line_1995.feature +24 -0
- data/features/vscan/vectors_1995.feature +33 -0
- data/features/vscan/vectors_2001.feature +29 -0
- data/features/vscan/vectors_sv.feature +31 -0
- data/lib/templates/helpers.rb +85 -0
- data/lib/templates/v2k_template.erb +6 -0
- data/lib/verilog_gen.rb +8 -3
- data/lib/verilog_gen/hdl_module.rb +274 -0
- data/lib/verilog_gen/hookup.rb +153 -0
- data/lib/verilog_gen/pin.rb +39 -0
- data/lib/verilog_gen/port.rb +109 -0
- data/lib/verilog_gen/proxy.rb +33 -0
- data/lib/verilog_gen/string.rb +38 -0
- data/lib/verilog_gen/version.rb +1 -1
- data/spec/fixture/generic_mem.v +38 -0
- data/spec/hdl_child_array_spec.rb +29 -0
- data/spec/hdl_hier_spec.rb +45 -0
- data/spec/hdl_hookup.spec +37 -0
- data/spec/hdl_module_spec.rb +117 -0
- data/spec/hdl_output_spec.rb +88 -0
- data/spec/hdl_port_spec.rb +35 -0
- data/spec/hdl_remove_child.spec +37 -0
- data/spec/pin_spec.rb +37 -0
- data/spec/port_spec.rb +90 -0
- data/spec/proxy_spec.rb +41 -0
- data/spec/spec_helper.rb +2 -0
- data/verilog_gen.gemspec +1 -1
- metadata +194 -8
- data/features/hello.feature +0 -8
- data/features/support/aruba.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1e2281d2daf631007d3ed1204c712bbdf24f6d8
|
4
|
+
data.tar.gz: 4a858282aaacc79cd2309f05b3d97083ad301438
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df11fbfda6ee4d390b7c5698c95cf619d0a778ee5dfd6d8c11a02cc128f1bb464b6a5636ec99968df0001fe2d455aed2b7b6bbf97cd6176a174f9fba83af5309
|
7
|
+
data.tar.gz: 5c5369b66f49fa986a16977770387c9cc7fd6a02a0b82d225afb9ce0cda8076e5cc70652a103bcd4bf5caa84c835e77f07ca4546c0071f52b65aa6c1e04b43b9
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,27 @@
|
|
1
1
|
# VerilogGen
|
2
2
|
|
3
|
-
|
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)
|
data/bin/hdl_equal
ADDED
@@ -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
|
-
|
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
|
+
|
data/bin/vscan
ADDED
@@ -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
|
+
|