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