HDLRuby 2.0.8
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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/HDLRuby.gemspec +36 -0
- data/LICENSE.txt +21 -0
- data/README.md +2774 -0
- data/README.pdf +0 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/hdrcc +3 -0
- data/lib/HDLRuby/alcc.rb +137 -0
- data/lib/HDLRuby/backend/hruby_allocator.rb +69 -0
- data/lib/HDLRuby/backend/hruby_c_allocator.rb +76 -0
- data/lib/HDLRuby/hdr_samples/adder.rb +7 -0
- data/lib/HDLRuby/hdr_samples/adder_assign_error.rb +11 -0
- data/lib/HDLRuby/hdr_samples/adder_bench.rb +27 -0
- data/lib/HDLRuby/hdr_samples/adder_gen.rb +7 -0
- data/lib/HDLRuby/hdr_samples/adder_nodef_error.rb +7 -0
- data/lib/HDLRuby/hdr_samples/addsub.rb +19 -0
- data/lib/HDLRuby/hdr_samples/addsubz.rb +22 -0
- data/lib/HDLRuby/hdr_samples/alu.rb +47 -0
- data/lib/HDLRuby/hdr_samples/calculator.rb +48 -0
- data/lib/HDLRuby/hdr_samples/counter_bench.rb +83 -0
- data/lib/HDLRuby/hdr_samples/dff.rb +9 -0
- data/lib/HDLRuby/hdr_samples/dff_bench.rb +66 -0
- data/lib/HDLRuby/hdr_samples/dff_counter.rb +20 -0
- data/lib/HDLRuby/hdr_samples/include.rb +14 -0
- data/lib/HDLRuby/hdr_samples/instance_open.rb +23 -0
- data/lib/HDLRuby/hdr_samples/mei8.rb +256 -0
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +309 -0
- data/lib/HDLRuby/hdr_samples/multer_gen.rb +8 -0
- data/lib/HDLRuby/hdr_samples/multer_seq.rb +29 -0
- data/lib/HDLRuby/hdr_samples/neural/a.rb +9 -0
- data/lib/HDLRuby/hdr_samples/neural/a_sub.rb +5 -0
- data/lib/HDLRuby/hdr_samples/neural/bw.rb +23 -0
- data/lib/HDLRuby/hdr_samples/neural/counter.rb +16 -0
- data/lib/HDLRuby/hdr_samples/neural/dadz.rb +9 -0
- data/lib/HDLRuby/hdr_samples/neural/dadz_sub.rb +4 -0
- data/lib/HDLRuby/hdr_samples/neural/forward.rb +153 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub.rb +62 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub_rand.rb +41 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub_rand_typedef.rb +47 -0
- data/lib/HDLRuby/hdr_samples/neural/mem.rb +30 -0
- data/lib/HDLRuby/hdr_samples/neural/random.rb +23 -0
- data/lib/HDLRuby/hdr_samples/neural/selector.rb +29 -0
- data/lib/HDLRuby/hdr_samples/neural/sigmoid.rb +20 -0
- data/lib/HDLRuby/hdr_samples/neural/z.rb +33 -0
- data/lib/HDLRuby/hdr_samples/prog.obj +256 -0
- data/lib/HDLRuby/hdr_samples/ram.rb +18 -0
- data/lib/HDLRuby/hdr_samples/register_with_code_bench.rb +98 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +10 -0
- data/lib/HDLRuby/hdr_samples/struct.rb +14 -0
- data/lib/HDLRuby/hdr_samples/sumprod.rb +29 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_bench.rb +103 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_cpu_bench.rb +261 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_cpusim_bench.rb +302 -0
- data/lib/HDLRuby/hdr_samples/system_open.rb +11 -0
- data/lib/HDLRuby/hdr_samples/tuple.rb +16 -0
- data/lib/HDLRuby/hdr_samples/with_channel.rb +118 -0
- data/lib/HDLRuby/hdr_samples/with_class.rb +199 -0
- data/lib/HDLRuby/hdr_samples/with_decoder.rb +17 -0
- data/lib/HDLRuby/hdr_samples/with_fsm.rb +34 -0
- data/lib/HDLRuby/hdr_samples/with_reconf.rb +103 -0
- data/lib/HDLRuby/hdrcc.rb +623 -0
- data/lib/HDLRuby/high_samples/_adder_fault.rb +23 -0
- data/lib/HDLRuby/high_samples/_generic_transmission2.rb +146 -0
- data/lib/HDLRuby/high_samples/adder.rb +21 -0
- data/lib/HDLRuby/high_samples/adder_common_errors.rb +25 -0
- data/lib/HDLRuby/high_samples/addsub.rb +33 -0
- data/lib/HDLRuby/high_samples/addsubz.rb +37 -0
- data/lib/HDLRuby/high_samples/after.rb +28 -0
- data/lib/HDLRuby/high_samples/all_signals.rb +29 -0
- data/lib/HDLRuby/high_samples/alu.rb +61 -0
- data/lib/HDLRuby/high_samples/anonymous.rb +41 -0
- data/lib/HDLRuby/high_samples/before.rb +28 -0
- data/lib/HDLRuby/high_samples/blockblock.rb +26 -0
- data/lib/HDLRuby/high_samples/bugs/dadz.rb +22 -0
- data/lib/HDLRuby/high_samples/bugs/misample_instan.rb +20 -0
- data/lib/HDLRuby/high_samples/bugs/misample_updown.rb +22 -0
- data/lib/HDLRuby/high_samples/bugs/sample_add.rb +16 -0
- data/lib/HDLRuby/high_samples/bugs/sample_barrel.rb +13 -0
- data/lib/HDLRuby/high_samples/bugs/sample_daice.rb +57 -0
- data/lib/HDLRuby/high_samples/bugs/sample_kumiawase.rb +52 -0
- data/lib/HDLRuby/high_samples/bugs/sample_multi.rb +18 -0
- data/lib/HDLRuby/high_samples/bugs/sample_sub.rb +14 -0
- data/lib/HDLRuby/high_samples/bugs/z2.rb +32 -0
- data/lib/HDLRuby/high_samples/case.rb +32 -0
- data/lib/HDLRuby/high_samples/case2.rb +30 -0
- data/lib/HDLRuby/high_samples/change.rb +23 -0
- data/lib/HDLRuby/high_samples/clocks.rb +35 -0
- data/lib/HDLRuby/high_samples/comparer.rb +21 -0
- data/lib/HDLRuby/high_samples/conditionals.rb +29 -0
- data/lib/HDLRuby/high_samples/dff.rb +23 -0
- data/lib/HDLRuby/high_samples/each.rb +28 -0
- data/lib/HDLRuby/high_samples/exporter.rb +42 -0
- data/lib/HDLRuby/high_samples/functions.rb +60 -0
- data/lib/HDLRuby/high_samples/if_seq.rb +26 -0
- data/lib/HDLRuby/high_samples/inherit_as_dff.rb +32 -0
- data/lib/HDLRuby/high_samples/inherit_dff.rb +36 -0
- data/lib/HDLRuby/high_samples/instance.rb +37 -0
- data/lib/HDLRuby/high_samples/memory.rb +64 -0
- data/lib/HDLRuby/high_samples/multi_file.rb +27 -0
- data/lib/HDLRuby/high_samples/overload.rb +32 -0
- data/lib/HDLRuby/high_samples/paper_after.rb +49 -0
- data/lib/HDLRuby/high_samples/ram.rb +27 -0
- data/lib/HDLRuby/high_samples/registers.rb +139 -0
- data/lib/HDLRuby/high_samples/rom.rb +23 -0
- data/lib/HDLRuby/high_samples/scopeblockname.rb +37 -0
- data/lib/HDLRuby/high_samples/scopescope.rb +26 -0
- data/lib/HDLRuby/high_samples/shift.rb +31 -0
- data/lib/HDLRuby/high_samples/shift2.rb +40 -0
- data/lib/HDLRuby/high_samples/simple_instance.rb +31 -0
- data/lib/HDLRuby/high_samples/test_all.sh +10 -0
- data/lib/HDLRuby/high_samples/typedef.rb +24 -0
- data/lib/HDLRuby/high_samples/values.rb +70 -0
- data/lib/HDLRuby/high_samples/vector.rb +22 -0
- data/lib/HDLRuby/high_samples/with_decoder.rb +30 -0
- data/lib/HDLRuby/high_samples/with_fsm.rb +46 -0
- data/lib/HDLRuby/high_samples/with_pipe.rb +43 -0
- data/lib/HDLRuby/high_samples/with_seq.rb +25 -0
- data/lib/HDLRuby/hruby_bstr.rb +1085 -0
- data/lib/HDLRuby/hruby_check.rb +317 -0
- data/lib/HDLRuby/hruby_db.rb +432 -0
- data/lib/HDLRuby/hruby_error.rb +44 -0
- data/lib/HDLRuby/hruby_high.rb +4103 -0
- data/lib/HDLRuby/hruby_low.rb +4735 -0
- data/lib/HDLRuby/hruby_low2c.rb +1986 -0
- data/lib/HDLRuby/hruby_low2high.rb +738 -0
- data/lib/HDLRuby/hruby_low2seq.rb +248 -0
- data/lib/HDLRuby/hruby_low2sym.rb +126 -0
- data/lib/HDLRuby/hruby_low2vhd.rb +1437 -0
- data/lib/HDLRuby/hruby_low_bool2select.rb +295 -0
- data/lib/HDLRuby/hruby_low_cleanup.rb +193 -0
- data/lib/HDLRuby/hruby_low_fix_types.rb +437 -0
- data/lib/HDLRuby/hruby_low_mutable.rb +1803 -0
- data/lib/HDLRuby/hruby_low_resolve.rb +165 -0
- data/lib/HDLRuby/hruby_low_skeleton.rb +129 -0
- data/lib/HDLRuby/hruby_low_with_bool.rb +141 -0
- data/lib/HDLRuby/hruby_low_with_port.rb +167 -0
- data/lib/HDLRuby/hruby_low_with_var.rb +302 -0
- data/lib/HDLRuby/hruby_low_without_bit2vector.rb +88 -0
- data/lib/HDLRuby/hruby_low_without_concat.rb +162 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +113 -0
- data/lib/HDLRuby/hruby_low_without_namespace.rb +718 -0
- data/lib/HDLRuby/hruby_low_without_outread.rb +107 -0
- data/lib/HDLRuby/hruby_low_without_select.rb +206 -0
- data/lib/HDLRuby/hruby_serializer.rb +398 -0
- data/lib/HDLRuby/hruby_tools.rb +37 -0
- data/lib/HDLRuby/hruby_types.rb +239 -0
- data/lib/HDLRuby/hruby_values.rb +64 -0
- data/lib/HDLRuby/hruby_verilog.rb +1888 -0
- data/lib/HDLRuby/hruby_verilog_name.rb +52 -0
- data/lib/HDLRuby/low_samples/adder.yaml +97 -0
- data/lib/HDLRuby/low_samples/after.yaml +228 -0
- data/lib/HDLRuby/low_samples/before.yaml +223 -0
- data/lib/HDLRuby/low_samples/blockblock.yaml +48 -0
- data/lib/HDLRuby/low_samples/bugs/sample_add.yaml +97 -0
- data/lib/HDLRuby/low_samples/bugs/sample_daice.yaml +444 -0
- data/lib/HDLRuby/low_samples/bugs/sample_kumiawase.yaml +332 -0
- data/lib/HDLRuby/low_samples/bugs/sample_sub.yaml +97 -0
- data/lib/HDLRuby/low_samples/bugs/seqpar.yaml +184 -0
- data/lib/HDLRuby/low_samples/case.yaml +327 -0
- data/lib/HDLRuby/low_samples/change.yaml +135 -0
- data/lib/HDLRuby/low_samples/clocks.yaml +674 -0
- data/lib/HDLRuby/low_samples/cloner.rb +22 -0
- data/lib/HDLRuby/low_samples/comparer.yaml +85 -0
- data/lib/HDLRuby/low_samples/conditionals.yaml +133 -0
- data/lib/HDLRuby/low_samples/dff.yaml +107 -0
- data/lib/HDLRuby/low_samples/each.yaml +1328 -0
- data/lib/HDLRuby/low_samples/exporter.yaml +226 -0
- data/lib/HDLRuby/low_samples/functions.yaml +298 -0
- data/lib/HDLRuby/low_samples/generic_transmission.yaml +597 -0
- data/lib/HDLRuby/low_samples/inherit_as_dff.yaml +125 -0
- data/lib/HDLRuby/low_samples/inherit_dff.yaml +107 -0
- data/lib/HDLRuby/low_samples/load_yaml.rb +11 -0
- data/lib/HDLRuby/low_samples/memory.yaml +678 -0
- data/lib/HDLRuby/low_samples/namespace_extractor.rb +23 -0
- data/lib/HDLRuby/low_samples/overload.yaml +226 -0
- data/lib/HDLRuby/low_samples/paper_after.yaml +431 -0
- data/lib/HDLRuby/low_samples/port_maker.rb +14 -0
- data/lib/HDLRuby/low_samples/ram.yaml +207 -0
- data/lib/HDLRuby/low_samples/registers.yaml +228 -0
- data/lib/HDLRuby/low_samples/rom.yaml +2950 -0
- data/lib/HDLRuby/low_samples/shift.yaml +230 -0
- data/lib/HDLRuby/low_samples/shift2.yaml +2095 -0
- data/lib/HDLRuby/low_samples/simple_instance.yaml +102 -0
- data/lib/HDLRuby/low_samples/test_all.sh +43 -0
- data/lib/HDLRuby/low_samples/typedef.yaml +115 -0
- data/lib/HDLRuby/low_samples/values.yaml +577 -0
- data/lib/HDLRuby/low_samples/variable_maker.rb +14 -0
- data/lib/HDLRuby/low_samples/vector.yaml +56 -0
- data/lib/HDLRuby/low_samples/with_seq.yaml +188 -0
- data/lib/HDLRuby/low_samples/yaml2hdr.rb +10 -0
- data/lib/HDLRuby/low_samples/yaml2vhd.rb +19 -0
- data/lib/HDLRuby/sim/Makefile +19 -0
- data/lib/HDLRuby/sim/hruby_sim.h +590 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +2362 -0
- data/lib/HDLRuby/sim/hruby_sim_core.c +589 -0
- data/lib/HDLRuby/sim/hruby_sim_list.c +93 -0
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +91 -0
- data/lib/HDLRuby/sim/hruby_value_pool.c +64 -0
- data/lib/HDLRuby/std/channel.rb +354 -0
- data/lib/HDLRuby/std/clocks.rb +165 -0
- data/lib/HDLRuby/std/counters.rb +82 -0
- data/lib/HDLRuby/std/decoder.rb +214 -0
- data/lib/HDLRuby/std/fsm.rb +516 -0
- data/lib/HDLRuby/std/pipeline.rb +220 -0
- data/lib/HDLRuby/std/reconf.rb +309 -0
- data/lib/HDLRuby/test_hruby_bstr.rb +2259 -0
- data/lib/HDLRuby/test_hruby_high.rb +594 -0
- data/lib/HDLRuby/test_hruby_high_low.rb +99 -0
- data/lib/HDLRuby/test_hruby_low.rb +934 -0
- data/lib/HDLRuby/v_samples/adder.v +10 -0
- data/lib/HDLRuby/v_samples/dff.v +12 -0
- data/lib/HDLRuby/v_samples/ram.v +20 -0
- data/lib/HDLRuby/v_samples/rom.v +270 -0
- data/lib/HDLRuby/version.rb +3 -0
- data/lib/HDLRuby.rb +11 -0
- data/makedoc +1 -0
- data/metadata.yaml +4 -0
- metadata +299 -0
|
@@ -0,0 +1,1437 @@
|
|
|
1
|
+
require 'HDLRuby'
|
|
2
|
+
require 'HDLRuby/hruby_low_with_bool'
|
|
3
|
+
require 'HDLRuby/hruby_low_without_namespace'
|
|
4
|
+
require 'HDLRuby/hruby_low_with_var'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module HDLRuby::Low
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
# Converts a HDLRuby::Low description to a VHDL text
|
|
12
|
+
# description
|
|
13
|
+
#
|
|
14
|
+
########################################################################
|
|
15
|
+
|
|
16
|
+
## Provides tools for converting HDLRuby::Low objects to VHDL.
|
|
17
|
+
module Low2VHDL
|
|
18
|
+
|
|
19
|
+
# Indicates if VHDL'08 can be generated.
|
|
20
|
+
# Default: true
|
|
21
|
+
#
|
|
22
|
+
# NOTE: when possible, it is better to be left true since the
|
|
23
|
+
# identifier does not require any mangling in VHDL'08
|
|
24
|
+
@@vhdl08 = true
|
|
25
|
+
|
|
26
|
+
## Tells if VHDL'08 is supported or not.
|
|
27
|
+
def self.vhdl08
|
|
28
|
+
return @@vhdl08
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
## Sets/unsets the support of VHDL'08.
|
|
32
|
+
def self.vhdl08=(mode)
|
|
33
|
+
@@vhdl08 = mode ? true : false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Indicates if target toolchain is Alliance: requires a slightly
|
|
37
|
+
# different VHDL syntax.
|
|
38
|
+
#
|
|
39
|
+
# NOTE: this syntax is not lint-compatible and should be avoided
|
|
40
|
+
# unless using specifically Alliance.
|
|
41
|
+
@@alliance = false
|
|
42
|
+
|
|
43
|
+
## Tells if Allicance toolchain is targeted.
|
|
44
|
+
def self.alliance
|
|
45
|
+
return @@alliance
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
## Sets/unsets the Allicance toolchain targeting.
|
|
49
|
+
def self.alliance=(mode)
|
|
50
|
+
@@alliance = mode ? true : false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
## Generates the pakage requirement for an entity.
|
|
54
|
+
# +spaces+ are the spaces to put before each line.
|
|
55
|
+
def self.packages(spaces)
|
|
56
|
+
return "#{spaces}library ieee;\n" +
|
|
57
|
+
"#{spaces}use ieee.std_logic_1164.all;\n" +
|
|
58
|
+
"#{spaces}use ieee.numeric_std.all;\n\n"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
## Tells if a +name+ is VHDL-compatible.
|
|
62
|
+
# To ensure compatibile, assume all the character must have the
|
|
63
|
+
# same case.
|
|
64
|
+
def self.vhdl_name?(name)
|
|
65
|
+
name = name.to_s
|
|
66
|
+
# First: character check.
|
|
67
|
+
return false unless name =~ /^[a-zA-Z]|([a-zA-Z][a-zA-Z_0-9]*[a-zA-Z0-9])$/
|
|
68
|
+
# Then character sequence check.
|
|
69
|
+
return false if name.include?("__")
|
|
70
|
+
# Then case check.
|
|
71
|
+
return (name == name.upcase || name == name.downcase)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
## Converts a +name+ to a VHDL-compatible name.
|
|
75
|
+
def self.vhdl_name(name)
|
|
76
|
+
if vhdl08 then
|
|
77
|
+
# VHDL'08, nothing to do if the name is VHDL-compatible.
|
|
78
|
+
return name.to_s if self.vhdl_name?(name)
|
|
79
|
+
# Otherwise put the name between //
|
|
80
|
+
return "\\#{name}\\".to_s
|
|
81
|
+
else
|
|
82
|
+
# Not VHDL'08, need to mangle the name.
|
|
83
|
+
# For safety also force downcase.
|
|
84
|
+
name = name.to_s
|
|
85
|
+
# Other letters: convert special characters.
|
|
86
|
+
name = name.each_char.map do |c|
|
|
87
|
+
if c=~ /[a-uw-z0-9]/ then
|
|
88
|
+
c
|
|
89
|
+
elsif c == "v" then
|
|
90
|
+
"vv"
|
|
91
|
+
else
|
|
92
|
+
"v" + c.ord.to_s
|
|
93
|
+
end
|
|
94
|
+
end.join
|
|
95
|
+
# First character: only letter is possible.
|
|
96
|
+
unless name[0] =~ /[a-z]/ then
|
|
97
|
+
name = "v" + name
|
|
98
|
+
end
|
|
99
|
+
return name
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
## Converts a +name+ to a VHDL entity name.
|
|
104
|
+
#
|
|
105
|
+
# NOTE: assume names have been converted to VHDL-compatible ones.
|
|
106
|
+
def self.entity_name(name)
|
|
107
|
+
return self.vhdl_name(name.to_s + "_e")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
## Converts a +name+ to a VHDL architecture name.
|
|
111
|
+
#
|
|
112
|
+
# NOTE: assume names have been converted to VHDL-compatible ones.
|
|
113
|
+
def self.architecture_name(name)
|
|
114
|
+
return self.vhdl_name(name.to_s + "_a")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
## Tells if a +type+ is arithmetic-compatible.
|
|
118
|
+
def self.arith?(type)
|
|
119
|
+
return type.is_a?(TypeVector) &&
|
|
120
|
+
[:signed,:unsigned,:float].include?(type.base.name)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
## Generates expression +expr+ while casting it to
|
|
124
|
+
# arithmetic-compatible type if required.
|
|
125
|
+
def self.to_arith(expr)
|
|
126
|
+
if arith?(expr.type) then
|
|
127
|
+
# The expression is arithmetic-compatible, just generate it.
|
|
128
|
+
if expr.is_a?(Value) then
|
|
129
|
+
return expr.to_arith
|
|
130
|
+
else
|
|
131
|
+
return expr.to_vhdl
|
|
132
|
+
end
|
|
133
|
+
else
|
|
134
|
+
# The expression is to convert, by default convert to unsigned
|
|
135
|
+
# (this is the standard interpretation of HDLRuby).
|
|
136
|
+
if expr.type.to_vhdl == "std_logic" then
|
|
137
|
+
# std_logic case: must convert to vector first.
|
|
138
|
+
if alliance then
|
|
139
|
+
# Alliance toolchain case.
|
|
140
|
+
return "unsigned('0' & " + expr.to_vhdl + ")"
|
|
141
|
+
else
|
|
142
|
+
# General case.
|
|
143
|
+
return "unsigned(\"\" & " + expr.to_vhdl + ")"
|
|
144
|
+
end
|
|
145
|
+
else
|
|
146
|
+
# Other case, ue the expression direction.
|
|
147
|
+
return "unsigned(" + expr.to_vhdl + ")"
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Moved to hruby_low_with_bool.rb
|
|
153
|
+
#
|
|
154
|
+
# ## Tells if an expression is a boolean.
|
|
155
|
+
# def self.boolean?(expr)
|
|
156
|
+
# if expr.is_a?(Unary) && expr.operator == :~ then
|
|
157
|
+
# # NOT, boolean is the sub expr is boolean.
|
|
158
|
+
# return Low2VHDL.boolean?(expr.child)
|
|
159
|
+
# elsif expr.is_a?(Binary) then
|
|
160
|
+
# # Binary case.
|
|
161
|
+
# case(expr.operator)
|
|
162
|
+
# when :==,:!=,:>,:<,:>=,:<= then
|
|
163
|
+
# # Comparison, it is a boolean.
|
|
164
|
+
# return true
|
|
165
|
+
# when :&,:|,:^ then
|
|
166
|
+
# # AND, OR or XOR, boolean if both subs are boolean.
|
|
167
|
+
# return Low2VHDL.boolean?(expr.left) &&
|
|
168
|
+
# Low2VHDL.boolean?(expr.right)
|
|
169
|
+
# else
|
|
170
|
+
# # Other cases: not boolean.
|
|
171
|
+
# return false
|
|
172
|
+
# end
|
|
173
|
+
# elsif expr.is_a?(Select) then
|
|
174
|
+
# # Select, binary if the choices are boolean.
|
|
175
|
+
# return !expr.each_choice.any? {|c| !Low2VHDL.boolean?(c) }
|
|
176
|
+
# else
|
|
177
|
+
# # Other cases are not considered as boolean.
|
|
178
|
+
# return false
|
|
179
|
+
# end
|
|
180
|
+
# end
|
|
181
|
+
|
|
182
|
+
## Generates a expression converted to the boolean type.
|
|
183
|
+
def self.to_boolean(expr)
|
|
184
|
+
# if boolean?(expr) then
|
|
185
|
+
if expr.boolean? then
|
|
186
|
+
# Comparison, no conversion required.
|
|
187
|
+
return expr.to_vhdl
|
|
188
|
+
else
|
|
189
|
+
# Conversion to boolean required.
|
|
190
|
+
return "(" + expr.to_vhdl + " = '1')"
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
## Generates epression +expr+ while casting it to match +type+ if
|
|
195
|
+
# required.
|
|
196
|
+
def self.to_type(type,expr)
|
|
197
|
+
# puts "expr=#{expr.to_vhdl}" unless expr.is_a?(Concat)
|
|
198
|
+
# puts "type.width=#{type.width}, expr.type.width=#{expr.type.width}"
|
|
199
|
+
if type.to_vhdl == "std_logic" then
|
|
200
|
+
# Conversion to std_logic required.
|
|
201
|
+
if expr.is_a?(Value) then
|
|
202
|
+
# Values can simply be rewritten.
|
|
203
|
+
if expr.content.to_s.to_i(2) == 0 then
|
|
204
|
+
return "'0'"
|
|
205
|
+
else
|
|
206
|
+
return "'1'"
|
|
207
|
+
end
|
|
208
|
+
elsif expr.type.to_vhdl != "std_logic"
|
|
209
|
+
# Otherwise a cast is required.
|
|
210
|
+
# if expr.type.base.name == :signed then
|
|
211
|
+
# return "unsigned(#{expr.to_vhdl})(0)"
|
|
212
|
+
# else
|
|
213
|
+
# # return "unsigned(#{expr.to_vhdl}(0))"
|
|
214
|
+
# return "unsigned(#{expr.to_vhdl})(0)"
|
|
215
|
+
# end
|
|
216
|
+
if alliance then
|
|
217
|
+
# Specific syntax for casting to std_logic with Alliance
|
|
218
|
+
if expr.type.width == 1 then
|
|
219
|
+
# No cast required with alliance if bitwidth is 1.
|
|
220
|
+
return expr.to_vhdl
|
|
221
|
+
else
|
|
222
|
+
# Multi-bit, need to select a bit and possibly
|
|
223
|
+
# cast to unsigned.
|
|
224
|
+
if expr.type.signed? then
|
|
225
|
+
return "unsigned(#{expr.to_vhdl}(0))"
|
|
226
|
+
# elsif expr.is_a?(RefRange) then
|
|
227
|
+
# # Range reference case.
|
|
228
|
+
# return "#{expr.ref.to_vhdl}(#{expr.range.first.to_vhdl})"
|
|
229
|
+
else
|
|
230
|
+
# Other cases.
|
|
231
|
+
return "#{expr.to_vhdl}(0)"
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
else
|
|
235
|
+
# Lint-compatible casting to std_logic
|
|
236
|
+
if expr.type.signed? then
|
|
237
|
+
# Signed, cast to unsigned.
|
|
238
|
+
return "unsigned(#{expr.to_vhdl})(0)"
|
|
239
|
+
# elsif expr.is_a?(RefRange) then
|
|
240
|
+
# # Range reference case.
|
|
241
|
+
# return "#{expr.ref.to_vhdl}(#{expr.range.first.to_vhdl})"
|
|
242
|
+
else
|
|
243
|
+
# Other cases: for std_logic generation.
|
|
244
|
+
return expr.to_vhdl(0,true)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
else
|
|
248
|
+
# Both are std_logic, nothing to to.
|
|
249
|
+
return expr.to_vhdl
|
|
250
|
+
end
|
|
251
|
+
elsif expr.is_a?(Value) then
|
|
252
|
+
# puts "type=#{type}, type.range=#{type.range}"
|
|
253
|
+
# Value width must be adjusted.
|
|
254
|
+
return expr.to_vhdl(0,false,type.width)
|
|
255
|
+
elsif expr.is_a?(Concat) then
|
|
256
|
+
return expr.to_vhdl(type)
|
|
257
|
+
elsif expr.type.width < type.width then
|
|
258
|
+
# Need to extend the type.
|
|
259
|
+
return '"' + "0" * (type.width - expr.type.width) + '" & ' +
|
|
260
|
+
expr.to_vhdl
|
|
261
|
+
else
|
|
262
|
+
# No conversion required.
|
|
263
|
+
return expr.to_vhdl
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
## Cast a +type+ to undo arithmetic conversion if necessary.
|
|
268
|
+
def self.unarith_cast(type)
|
|
269
|
+
# Is the type arithmetic?
|
|
270
|
+
if arith?(type) then
|
|
271
|
+
# Yes, no undo required.
|
|
272
|
+
return ""
|
|
273
|
+
else
|
|
274
|
+
# No, undo required.
|
|
275
|
+
return "std_logic_vector"
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
## Generates the name of a mux function by type string +tstr+ and
|
|
280
|
+
# number of arguments +num+.
|
|
281
|
+
def self.mux_name(tstr,num)
|
|
282
|
+
return "mux#{tstr.gsub(/[^a-zA-Z0-9_]/,"_")}#{num}"
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
## Generates the VHDL code for the mux function for type string +tstr+
|
|
286
|
+
# with +num+ choices.
|
|
287
|
+
# +spaces+ is the ident for the resulting code.
|
|
288
|
+
def self.mux_function(type,num,spaces)
|
|
289
|
+
# Create the strin of the type.
|
|
290
|
+
tstr = type.to_vhdl
|
|
291
|
+
# Create the name of the function from the type.
|
|
292
|
+
name = mux_name(tstr,num)
|
|
293
|
+
# Create the condition.
|
|
294
|
+
if num == 2 then
|
|
295
|
+
cond = "cond : boolean"
|
|
296
|
+
else
|
|
297
|
+
# First compute the width of the condition.
|
|
298
|
+
width = (num-1).width
|
|
299
|
+
# Now generate the condition.
|
|
300
|
+
cond = "val : std_logic_vector(#{width-1} downto 0)"
|
|
301
|
+
end
|
|
302
|
+
# Generate the arguments.
|
|
303
|
+
args = num.times.map {|i| "arg#{i} : #{tstr}" }.join("; ")
|
|
304
|
+
# Generate the body.
|
|
305
|
+
if num == 2 then
|
|
306
|
+
body = "#{spaces} if(cond) then\n" +
|
|
307
|
+
"#{spaces} return arg0;\n" +
|
|
308
|
+
"#{spaces} else\n" +
|
|
309
|
+
"#{spaces} return arg1;\n" +
|
|
310
|
+
"#{spaces} end if;\n"
|
|
311
|
+
else
|
|
312
|
+
# First compute the type of the choices.
|
|
313
|
+
vtype = TypeVector.new(:"",Bit,width-1..0)
|
|
314
|
+
# Now generate the body.
|
|
315
|
+
body = "#{spaces} case(val) is\n" +
|
|
316
|
+
num.times.map do |i|
|
|
317
|
+
pos = Value.new(vtype,i).to_vhdl
|
|
318
|
+
"#{spaces} when #{pos} => return arg#{i};\n"
|
|
319
|
+
end.join +
|
|
320
|
+
"#{spaces} end case;\n"
|
|
321
|
+
end
|
|
322
|
+
# Generate the choices.
|
|
323
|
+
# Generates the function
|
|
324
|
+
return "#{spaces}function #{name}" +
|
|
325
|
+
"(#{cond}; #{args})\n" +
|
|
326
|
+
"#{spaces}return #{tstr} is\n" +
|
|
327
|
+
"#{spaces}begin\n" + body +
|
|
328
|
+
"#{spaces}end #{mux_name(tstr,num)};\n\n"
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
## Extends the SystemT class with generation of HDLRuby::High text.
|
|
335
|
+
class SystemT
|
|
336
|
+
|
|
337
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
338
|
+
# +level+ is the hierachical level of the object.
|
|
339
|
+
def to_vhdl(level = 0)
|
|
340
|
+
# The resulting string.
|
|
341
|
+
res = ""
|
|
342
|
+
# Generate the entity
|
|
343
|
+
# The header
|
|
344
|
+
res << Low2VHDL.packages(" " * (level*3))
|
|
345
|
+
res << " " * (level*3)
|
|
346
|
+
res << "entity #{Low2VHDL.entity_name(self.name)} is\n"
|
|
347
|
+
# The ports
|
|
348
|
+
res << " " * ((level+1)*3)
|
|
349
|
+
res << "port (\n"
|
|
350
|
+
# Inputs
|
|
351
|
+
self.each_input do |input|
|
|
352
|
+
res << " " * ((level+2)*3)
|
|
353
|
+
res << Low2VHDL.vhdl_name(input.name) << ": in "
|
|
354
|
+
res << input.type.to_vhdl << ";\n"
|
|
355
|
+
end
|
|
356
|
+
# Outputs
|
|
357
|
+
self.each_output do |output|
|
|
358
|
+
res << " " * ((level+2)*3)
|
|
359
|
+
res << Low2VHDL.vhdl_name(output.name) << ": out "
|
|
360
|
+
res << output.type.to_vhdl << ";\n"
|
|
361
|
+
end
|
|
362
|
+
# Inouts
|
|
363
|
+
self.each_inout do |inout|
|
|
364
|
+
res << " " * ((level+2)*3)
|
|
365
|
+
res << Low2VHDL.vhdl_name(inout.name) << ": inout "
|
|
366
|
+
res << inout.type.to_vhdl << ";\n"
|
|
367
|
+
end
|
|
368
|
+
# Remove the last ";" for conforming with VHDL syntax.
|
|
369
|
+
res[-2..-1] = "\n" if res[-2] == ";"
|
|
370
|
+
res << " " * ((level+1)*3)
|
|
371
|
+
# Close the port declaration.
|
|
372
|
+
res << ");\n"
|
|
373
|
+
# Close the entity
|
|
374
|
+
res << " " * (level*3)
|
|
375
|
+
res << "end #{Low2VHDL.entity_name(self.name)};\n\n"
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
# Generate the architecture.
|
|
379
|
+
res << " " * (level*3)
|
|
380
|
+
res << "architecture #{Low2VHDL.architecture_name(self.name)} "
|
|
381
|
+
res << "of #{Low2VHDL.entity_name(self.name)} is\n"
|
|
382
|
+
# Generate the scope.
|
|
383
|
+
res << "\n"
|
|
384
|
+
res << self.scope.to_vhdl(level+1)
|
|
385
|
+
# End of the system.
|
|
386
|
+
res << " " * (level*3)
|
|
387
|
+
res << "end #{Low2VHDL.architecture_name(self.name)};\n\n"
|
|
388
|
+
# Return the result.
|
|
389
|
+
return res
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
## Extends the Scope class with generation of HDLRuby::High text.
|
|
395
|
+
class Scope
|
|
396
|
+
|
|
397
|
+
## Tells if an expression is a reference to port +systemI.signal+.
|
|
398
|
+
def port_assign?(expr, systemI, signal)
|
|
399
|
+
return expr.is_a?(RefName) && expr.name == signal.name &&
|
|
400
|
+
expr.ref.is_a?(RefName) && expr.ref.name == systemI.name
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
## Extracts the assignments to port +systemI.signal+ and returns
|
|
404
|
+
# the resulting reference to a port wire.
|
|
405
|
+
#
|
|
406
|
+
# NOTE: assumes to_upper_space! and with_port! has been called.
|
|
407
|
+
def extract_port_assign!(systemI,signal)
|
|
408
|
+
# Extract the assignment.
|
|
409
|
+
assign = nil
|
|
410
|
+
self.each_connection.to_a.each do |connection|
|
|
411
|
+
if self.port_assign?(connection.left,systemI,signal) then
|
|
412
|
+
# The left is the port.
|
|
413
|
+
# Delete the connection.
|
|
414
|
+
self.delete_connection!(connection)
|
|
415
|
+
# And return a copy of the right.
|
|
416
|
+
return connection.right.clone
|
|
417
|
+
elsif self.port_assign?(connection.right,systemI,signal) then
|
|
418
|
+
# The right is the port.
|
|
419
|
+
# Delete the connection.
|
|
420
|
+
self.delete_connection!(connection)
|
|
421
|
+
# And return a copy of the left.
|
|
422
|
+
return connection.left.clone
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
# No port found, nothing to do
|
|
426
|
+
return nil
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
430
|
+
# +level+ is the hierachical level of the object and
|
|
431
|
+
def to_vhdl(level = 0)
|
|
432
|
+
# The resulting string.
|
|
433
|
+
res = ""
|
|
434
|
+
|
|
435
|
+
# Generate the architecture's header
|
|
436
|
+
# The instances' headers
|
|
437
|
+
self.each_systemI do |systemI|
|
|
438
|
+
systemT = systemI.systemT
|
|
439
|
+
# Its entity
|
|
440
|
+
res << (" " * level*3)
|
|
441
|
+
res << "component #{Low2VHDL.entity_name(systemT.name)}\n"
|
|
442
|
+
res << (" " * (level+1)*3)
|
|
443
|
+
# Its ports
|
|
444
|
+
res << "port(\n"
|
|
445
|
+
# Inputs
|
|
446
|
+
systemT.each_input do |input|
|
|
447
|
+
res << " " * ((level+2)*3)
|
|
448
|
+
res << Low2VHDL.vhdl_name(input.name) << ": in "
|
|
449
|
+
res << input.type.to_vhdl << ";\n"
|
|
450
|
+
end
|
|
451
|
+
# Outputs
|
|
452
|
+
systemT.each_output do |output|
|
|
453
|
+
res << " " * ((level+2)*3)
|
|
454
|
+
res << Low2VHDL.vhdl_name(output.name) << ": out "
|
|
455
|
+
res << output.type.to_vhdl << ";\n"
|
|
456
|
+
end
|
|
457
|
+
# Inouts
|
|
458
|
+
systemT.each_inout do |inout|
|
|
459
|
+
res << " " * ((level+2)*3)
|
|
460
|
+
res << Low2VHDL.vhdl_name(inout.name) << ": inout "
|
|
461
|
+
res << inout.type.to_vhdl << ";\n"
|
|
462
|
+
end
|
|
463
|
+
# Remove the last ";" for conforming with VHDL syntax.
|
|
464
|
+
res[-2..-1] = "\n" if res[-2] == ";"
|
|
465
|
+
res << " " * ((level+1)*3)
|
|
466
|
+
# Close the port declaration.
|
|
467
|
+
res << ");\n"
|
|
468
|
+
# Close the component.
|
|
469
|
+
res << " " * (level*3)
|
|
470
|
+
res << "end component;\n\n"
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
# Generate the architecture's type definition.
|
|
474
|
+
# It is assumed that these types are all TypeDef.
|
|
475
|
+
self.each_type do |type|
|
|
476
|
+
res << (" " * level*3)
|
|
477
|
+
res << "type #{Low2VHDL.vhdl_name(type.name)} is "
|
|
478
|
+
res << type.def.to_vhdl(level+1)
|
|
479
|
+
res << ";\n"
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
## Generates the required mux functions.
|
|
483
|
+
mtps = [] # The mux functions to generate by type.
|
|
484
|
+
# Gather the mux functions to generate.
|
|
485
|
+
self.each_scope_deep do |scope|
|
|
486
|
+
# Checks the connections.
|
|
487
|
+
scope.each_connection do |connection|
|
|
488
|
+
connection.right.each_node_deep do |node|
|
|
489
|
+
if node.is_a?(Select) then
|
|
490
|
+
mtps << [node.type,node.each_choice.to_a.size]
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
# Checks the statements.
|
|
495
|
+
scope.each_behavior do |behavior|
|
|
496
|
+
behavior.block.each_node_deep do |node|
|
|
497
|
+
if node.is_a?(Select) then
|
|
498
|
+
mtps << [node.type,node.each_choice.to_a.size]
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
# Generate the gathered functions (only one per type).
|
|
504
|
+
mtps.uniq!
|
|
505
|
+
mtps.each do |type,num|
|
|
506
|
+
res << Low2VHDL.mux_function(type,num," " * level*3)
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
# Generate the inner signals declaration.
|
|
510
|
+
self.each_inner do |inner|
|
|
511
|
+
res << " " * (level * 3)
|
|
512
|
+
# General signal or constant signal?
|
|
513
|
+
res << (inner.is_a?(SignalC) ? "constant " : "signal ")
|
|
514
|
+
# Signal name.
|
|
515
|
+
res << Low2VHDL.vhdl_name(inner.name) << ": "
|
|
516
|
+
# Signal type.
|
|
517
|
+
res << inner.type.to_vhdl(level)
|
|
518
|
+
# Signal value.
|
|
519
|
+
if inner.value then
|
|
520
|
+
if inner.value.is_a?(Concat) then
|
|
521
|
+
# Concat are to be given the expected type of the
|
|
522
|
+
# elements for casting them equally.
|
|
523
|
+
res << " := " << inner.value.to_vhdl(inner.type.base,level)
|
|
524
|
+
else
|
|
525
|
+
res << " := " << inner.value.to_vhdl(level)
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
res << ";\n"
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
# Generate the architecture's content.
|
|
532
|
+
res << " " * ((level-1)*3) << "begin\n"
|
|
533
|
+
|
|
534
|
+
# Generate the instances connections.
|
|
535
|
+
self.each_systemI do |systemI|
|
|
536
|
+
# Its Declaration.
|
|
537
|
+
res << " " * (level*3)
|
|
538
|
+
res << Low2VHDL.vhdl_name(systemI.name) << ": "
|
|
539
|
+
systemT = systemI.systemT
|
|
540
|
+
res << Low2VHDL.entity_name(systemT.name).to_s << "\n"
|
|
541
|
+
res << " " * ((level+1)*3)
|
|
542
|
+
# Its ports
|
|
543
|
+
res << "port map(\n"
|
|
544
|
+
# Inputs
|
|
545
|
+
systemT.each_input do |input|
|
|
546
|
+
ref = self.extract_port_assign!(systemI,input)
|
|
547
|
+
if ref then
|
|
548
|
+
res << " " * ((level+2)*3)
|
|
549
|
+
res << Low2VHDL.vhdl_name(input.name) << " => "
|
|
550
|
+
res << ref.to_vhdl(level)
|
|
551
|
+
res << ",\n"
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
# Outputs
|
|
555
|
+
systemT.each_output do |output|
|
|
556
|
+
ref = self.extract_port_assign!(systemI,output)
|
|
557
|
+
if ref then
|
|
558
|
+
res << " " * ((level+2)*3)
|
|
559
|
+
res << Low2VHDL.vhdl_name(output.name) << " => "
|
|
560
|
+
res << ref.to_vhdl(level)
|
|
561
|
+
res << ",\n"
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
# Inouts
|
|
565
|
+
systemT.each_inout do |inout|
|
|
566
|
+
ref = self.extract_port_assign!(systemI,inout)
|
|
567
|
+
if ref then
|
|
568
|
+
res << " " * ((level+2)*3)
|
|
569
|
+
res << Low2VHDL.vhdl_name(inout.name) << " => "
|
|
570
|
+
res << ref.to_vhdl(level)
|
|
571
|
+
res << ",\n"
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
# Remove the last ";" for conforming with VHDL syntax.
|
|
575
|
+
res[-2..-1] = "\n" if res[-2] == ","
|
|
576
|
+
# Close the port map declaration.
|
|
577
|
+
res << " " * ((level+1)*3)
|
|
578
|
+
res << ");\n"
|
|
579
|
+
end
|
|
580
|
+
# Generate the connections.
|
|
581
|
+
res << "\n" if self.each_scope.any?
|
|
582
|
+
self.each_scope_deep do |scope|
|
|
583
|
+
scope.each_connection do |connection|
|
|
584
|
+
res << connection.to_vhdl([],level)
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
# Generate the behaviors.
|
|
589
|
+
# Current scope's
|
|
590
|
+
res << "\n" if self.each_connection.any?
|
|
591
|
+
self.each_scope_deep do |scope|
|
|
592
|
+
scope.each_behavior do |behavior|
|
|
593
|
+
res << behavior.to_vhdl(level)
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
return res
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
## Extends the Type class with generation of HDLRuby::High text.
|
|
602
|
+
class Type
|
|
603
|
+
|
|
604
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
605
|
+
# +level+ is the hierachical level of the object.
|
|
606
|
+
def to_vhdl(level = 0)
|
|
607
|
+
return self.boolean? ? "boolean" : "std_logic"
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
## Extends the TypeDef class with generation of HDLRuby::High text.
|
|
612
|
+
class TypeDef
|
|
613
|
+
|
|
614
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
615
|
+
# +level+ is the hierachical level of the object.
|
|
616
|
+
def to_vhdl(level = 0)
|
|
617
|
+
# # Simply generates the redefined type.
|
|
618
|
+
# return self.def.to_vhdl(level)
|
|
619
|
+
# Simply use the name of the type.
|
|
620
|
+
return Low2VHDL.vhdl_name(self.name)
|
|
621
|
+
end
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
## Extends the TypeVector class with generation of HDLRuby::High text.
|
|
625
|
+
class TypeVector
|
|
626
|
+
|
|
627
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
628
|
+
# +level+ is the hierachical level of the object.
|
|
629
|
+
def to_vhdl(level = 0)
|
|
630
|
+
# The resulting string.
|
|
631
|
+
res = ""
|
|
632
|
+
# Depending on the base.
|
|
633
|
+
if self.base.class < Type then
|
|
634
|
+
# The base is not a leaf, therefore the type is a VHDL array.
|
|
635
|
+
# NOTE: array are always valid if used in type definition,
|
|
636
|
+
# it is assumed that break_types! from
|
|
637
|
+
# hruby_low_without_namespace.rb is used.
|
|
638
|
+
res << "array ("
|
|
639
|
+
res << self.range.first.to_vhdl(level)
|
|
640
|
+
if self.range.first >= self.range.last then
|
|
641
|
+
res << " downto "
|
|
642
|
+
else
|
|
643
|
+
res << " to "
|
|
644
|
+
end
|
|
645
|
+
res << self.range.last.to_vhdl(level)
|
|
646
|
+
res << ") of "
|
|
647
|
+
# Now generate the base.
|
|
648
|
+
res << base.to_vhdl(level+1)
|
|
649
|
+
else
|
|
650
|
+
# The base is a leaf, therefore the type is VHDL vector.
|
|
651
|
+
# Depending on the base name.
|
|
652
|
+
case(base.name)
|
|
653
|
+
when :bit
|
|
654
|
+
# std_logic_vector.
|
|
655
|
+
res << "std_logic_vector"
|
|
656
|
+
when :signed
|
|
657
|
+
res << "signed"
|
|
658
|
+
when :unsigned
|
|
659
|
+
res << "unsigned"
|
|
660
|
+
else
|
|
661
|
+
res << Low2VHDL.vhdl_name(self.base.name)
|
|
662
|
+
end
|
|
663
|
+
# Now the range
|
|
664
|
+
res << "("
|
|
665
|
+
res << self.range.first.to_vhdl(level)
|
|
666
|
+
left = self.range.first
|
|
667
|
+
right = self.range.last
|
|
668
|
+
left = left.content if left.is_a?(Value)
|
|
669
|
+
right = right.content if right.is_a?(Value)
|
|
670
|
+
if left >= right then
|
|
671
|
+
res << " downto "
|
|
672
|
+
else
|
|
673
|
+
res << " to "
|
|
674
|
+
end
|
|
675
|
+
res << self.range.last.to_vhdl(level)
|
|
676
|
+
res << ")"
|
|
677
|
+
end
|
|
678
|
+
# Return the result.
|
|
679
|
+
return res
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
## Extends the TypeTuple class with generation of HDLRuby::High text.
|
|
684
|
+
class TypeTuple
|
|
685
|
+
|
|
686
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
687
|
+
# +level+ is the hierachical level of the object.
|
|
688
|
+
#
|
|
689
|
+
# NOTE: type tuples are converted to bit vector of their contents.
|
|
690
|
+
def to_vhdl(level = 0)
|
|
691
|
+
# raise AnyError, "Tuple types are not supported in VHDL, please convert them to Struct types using Low::tuple2struct from HDLRuby/hruby_low_witout_tuple."
|
|
692
|
+
return self.to_vector.to_vhdl(level)
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
## Extends the TypeStruct class with generation of HDLRuby::High text.
|
|
697
|
+
class TypeStruct
|
|
698
|
+
|
|
699
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
700
|
+
# +level+ is the hierachical level of the object.
|
|
701
|
+
def to_vhdl(level = 0)
|
|
702
|
+
# The resulting string.
|
|
703
|
+
res = "record \n"
|
|
704
|
+
# Generate each sub type.
|
|
705
|
+
self.each do |key,type|
|
|
706
|
+
res << " " * ((level+1)*3)
|
|
707
|
+
res << Low2VHDL.vhdl_name(key)
|
|
708
|
+
res << ": " << type.to_vhdl(level+1)
|
|
709
|
+
res << ";\n"
|
|
710
|
+
end
|
|
711
|
+
res << " " * (level*3)
|
|
712
|
+
# Close the record.
|
|
713
|
+
res << "end record"
|
|
714
|
+
# Return the result.
|
|
715
|
+
return res
|
|
716
|
+
end
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
## Extends the Behavior class with generation of HDLRuby::High text.
|
|
721
|
+
class Behavior
|
|
722
|
+
|
|
723
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
724
|
+
# +level+ is the hierachical level of the object.
|
|
725
|
+
def to_vhdl(level = 0)
|
|
726
|
+
# Gather the variables.
|
|
727
|
+
# It is assumed that the inners are all in declared in the
|
|
728
|
+
# direct sub block and that they represent variables, i.e.,
|
|
729
|
+
# Low::to_upper_space! and Low::with_var! has been called.
|
|
730
|
+
vars = self.block.each_inner.to_a
|
|
731
|
+
|
|
732
|
+
# The resulting string.
|
|
733
|
+
res = " " * (level*3)
|
|
734
|
+
# Generate the header.
|
|
735
|
+
unless self.block.name.empty? then
|
|
736
|
+
res << Low2VHDL.vhdl_name(self.block.name) << ": "
|
|
737
|
+
end
|
|
738
|
+
res << "process "
|
|
739
|
+
# Generate the senitivity list.
|
|
740
|
+
if self.each_event.any? then
|
|
741
|
+
# If there is a clock.
|
|
742
|
+
res << "("
|
|
743
|
+
res << self.each_event.map do |event|
|
|
744
|
+
event.ref.to_vhdl(level)
|
|
745
|
+
end.join(", ")
|
|
746
|
+
res << ")"
|
|
747
|
+
else
|
|
748
|
+
# If no clock, generate the sensitivity list from the right
|
|
749
|
+
# values.
|
|
750
|
+
list = self.block.each_node_deep.select do |node|
|
|
751
|
+
node.is_a?(RefName) && !node.leftvalue? &&
|
|
752
|
+
!node.parent.is_a?(RefName) &&
|
|
753
|
+
# Also skip the variables
|
|
754
|
+
!vars.find {|var| var.name == node.name }
|
|
755
|
+
end.to_a
|
|
756
|
+
# Keep only one ref per signal.
|
|
757
|
+
list.uniq! { |node| node.name }
|
|
758
|
+
# Generate the sensitivity list from it.
|
|
759
|
+
res << "("
|
|
760
|
+
res << list.map {|node| node.to_vhdl(level) }.join(", ")
|
|
761
|
+
res << ")"
|
|
762
|
+
end
|
|
763
|
+
res << "\n"
|
|
764
|
+
# Generate the variables.
|
|
765
|
+
vars.each do |var|
|
|
766
|
+
res << " " * ((level+1)*3)
|
|
767
|
+
res << "variable "
|
|
768
|
+
res << Low2VHDL.vhdl_name(var.name) << ": "
|
|
769
|
+
res << var.type.to_vhdl << ";\n"
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
# Generate the content.
|
|
773
|
+
res << " " * (level*3)
|
|
774
|
+
res << "begin\n"
|
|
775
|
+
# Generate the edges if any.
|
|
776
|
+
if self.each_event.find {|event| event.type != :change} then
|
|
777
|
+
# Generate the edge test.
|
|
778
|
+
level = level + 1
|
|
779
|
+
res << " " * (level*3)
|
|
780
|
+
res << "if ("
|
|
781
|
+
res << self.each_event.map do |event|
|
|
782
|
+
if event.type == :posedge then
|
|
783
|
+
"rising_edge(" << event.ref.to_vhdl(level) << ")"
|
|
784
|
+
else
|
|
785
|
+
"falling_edge(" << event.ref.to_vhdl(level)<< ")"
|
|
786
|
+
end
|
|
787
|
+
# The change mode is not an edge!
|
|
788
|
+
end.join(" and ")
|
|
789
|
+
res << ") then\n"
|
|
790
|
+
# Generate the body.
|
|
791
|
+
res << self.block.to_vhdl(vars,level+2)
|
|
792
|
+
# Close the edge test.
|
|
793
|
+
res << " " * (level*3)
|
|
794
|
+
res << "end if;\n"
|
|
795
|
+
level = level - 1
|
|
796
|
+
else
|
|
797
|
+
# Generate the body directly.
|
|
798
|
+
res << self.block.to_vhdl(vars,level+1)
|
|
799
|
+
end
|
|
800
|
+
# Close the process.
|
|
801
|
+
res << " " * (level*3)
|
|
802
|
+
res << "end process;\n\n"
|
|
803
|
+
# Return the result.
|
|
804
|
+
return res
|
|
805
|
+
end
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
## Extends the TimeBehavior class with generation of HDLRuby::High text.
|
|
809
|
+
class TimeBehavior
|
|
810
|
+
# TimeBehavior is identical to Behavior in VHDL
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
## Extends the Event class with generation of HDLRuby::High text.
|
|
815
|
+
class Event
|
|
816
|
+
# Events are not directly generated.
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
## Extends the SignalI class with generation of HDLRuby::High text.
|
|
821
|
+
class SignalI
|
|
822
|
+
# Signals are not directly generated.
|
|
823
|
+
|
|
824
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
825
|
+
# +level+ is the hierachical level of the object.
|
|
826
|
+
def to_vhdl(level = 0)
|
|
827
|
+
# Should never be here.
|
|
828
|
+
raise AnyError, "Internal error: to_vhdl should be implemented in class :#{self.class}"
|
|
829
|
+
end
|
|
830
|
+
end
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
## Extends the SystemI class with generation of HDLRuby::High text.
|
|
834
|
+
class SystemI
|
|
835
|
+
# Instances are not directly generated.
|
|
836
|
+
|
|
837
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
838
|
+
# +level+ is the hierachical level of the object.
|
|
839
|
+
def to_vhdl(level = 0)
|
|
840
|
+
# Should never be here.
|
|
841
|
+
raise AnyError, "Internal error: to_vhdl should be implemented in class :#{self.class}"
|
|
842
|
+
end
|
|
843
|
+
end
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
## Extends the Statement class with generation of HDLRuby::High text.
|
|
847
|
+
class Statement
|
|
848
|
+
|
|
849
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
850
|
+
# +vars+ is the list of the variables and
|
|
851
|
+
# +level+ is the hierachical level of the object.
|
|
852
|
+
def to_vhdl(vars, level = 0)
|
|
853
|
+
# Should never be here.
|
|
854
|
+
raise AnyError, "Internal error: to_vhdl should be implemented in class :#{self.class}"
|
|
855
|
+
end
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
## Extends the Transmit class with generation of HDLRuby::High text.
|
|
859
|
+
class Transmit
|
|
860
|
+
|
|
861
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
862
|
+
# +vars+ is the list of the variables and
|
|
863
|
+
# +level+ is the hierachical level of the object.
|
|
864
|
+
def to_vhdl(vars,level = 0)
|
|
865
|
+
# Generate the assign operator.
|
|
866
|
+
assign = vars.any? do |var|
|
|
867
|
+
self.left.respond_to?(:name) && var.name == self.left.name
|
|
868
|
+
end ? " := " : " <= "
|
|
869
|
+
# Generate the assignment.
|
|
870
|
+
return " " * (level*3) +
|
|
871
|
+
self.left.to_vhdl(level) + assign +
|
|
872
|
+
Low2VHDL.to_type(self.left.type,self.right) + ";\n"
|
|
873
|
+
end
|
|
874
|
+
end
|
|
875
|
+
|
|
876
|
+
## Extends the If class with generation of HDLRuby::High text.
|
|
877
|
+
class If
|
|
878
|
+
|
|
879
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
880
|
+
# +vars+ is the list of the variables and
|
|
881
|
+
# +level+ is the hierachical level of the object.
|
|
882
|
+
def to_vhdl(vars,level = 0)
|
|
883
|
+
# The result string.
|
|
884
|
+
res = " " * (level*3)
|
|
885
|
+
# Generate the test.
|
|
886
|
+
res << "if (" << Low2VHDL.to_boolean(self.condition) << ") then\n"
|
|
887
|
+
# Generate the yes part.
|
|
888
|
+
res << self.yes.to_vhdl(vars,level+1)
|
|
889
|
+
# Generate the alternate if parts.
|
|
890
|
+
self.each_noif do |cond,stmnt|
|
|
891
|
+
res << " " * (level*3)
|
|
892
|
+
# res << "elsif (" << cond.to_vhdl(level) << ") then\n"
|
|
893
|
+
res << "elsif (" << Low2VHDL.to_boolean(cond) << ") then\n"
|
|
894
|
+
res << stmnt.to_vhdl(vars,level+1)
|
|
895
|
+
end
|
|
896
|
+
# Generate the no part if any.
|
|
897
|
+
if self.no then
|
|
898
|
+
res << " " * (level*3)
|
|
899
|
+
res << "else\n" << self.no.to_vhdl(vars,level+1)
|
|
900
|
+
end
|
|
901
|
+
# Close the if.
|
|
902
|
+
res << " " * (level*3)
|
|
903
|
+
res << "end if;\n"
|
|
904
|
+
# Return the result.
|
|
905
|
+
return res
|
|
906
|
+
end
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
## Extends the When class with generation of HDLRuby::High text.
|
|
910
|
+
class When
|
|
911
|
+
|
|
912
|
+
# Generates the text of the equivalent HDLRuby::High code ensuring
|
|
913
|
+
# the match is of +type+.
|
|
914
|
+
# +vars+ is the list of the variables and
|
|
915
|
+
# +level+ is the hierachical level of the object.
|
|
916
|
+
def to_vhdl(vars,type,level = 0)
|
|
917
|
+
# The result string.
|
|
918
|
+
res = " " * (level*3)
|
|
919
|
+
# Generate the match.
|
|
920
|
+
res << "when " << Low2VHDL.to_type(type,self.match) << " =>\n"
|
|
921
|
+
# Generate the statement.
|
|
922
|
+
res << self.statement.to_vhdl(vars,level+1)
|
|
923
|
+
# Returns the result.
|
|
924
|
+
return res
|
|
925
|
+
end
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
## Extends the Case class with generation of HDLRuby::High text.
|
|
929
|
+
class Case
|
|
930
|
+
|
|
931
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
932
|
+
# +vars+ is the list of the variables and
|
|
933
|
+
# +level+ is the hierachical level of the object.
|
|
934
|
+
def to_vhdl(vars,level = 0)
|
|
935
|
+
# The result string.
|
|
936
|
+
res = " " * (level*3)
|
|
937
|
+
# Generate the test.
|
|
938
|
+
res << "case " << self.value.to_vhdl(level) << " is\n"
|
|
939
|
+
# Generate the whens.
|
|
940
|
+
self.each_when do |w|
|
|
941
|
+
res << w.to_vhdl(vars,self.value.type,level)
|
|
942
|
+
end
|
|
943
|
+
# Generate teh default if any.
|
|
944
|
+
if self.default then
|
|
945
|
+
res << " " * (level*3)
|
|
946
|
+
res << "when others =>\n"
|
|
947
|
+
res << self.default.to_vhdl(vars,level+1)
|
|
948
|
+
else
|
|
949
|
+
# NOTE: some VHDL parsers are very picky about others,
|
|
950
|
+
# even though all the cases have been treated through
|
|
951
|
+
# "when" statements.
|
|
952
|
+
res << " " * (level*3)
|
|
953
|
+
res << "when others =>\n"
|
|
954
|
+
end
|
|
955
|
+
# Close the case.
|
|
956
|
+
res << " " * (level*3)
|
|
957
|
+
res << "end case;\n"
|
|
958
|
+
# Return the resulting string.
|
|
959
|
+
return res
|
|
960
|
+
end
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
## Extends the Delay class with generation of HDLRuby::High text.
|
|
965
|
+
class Delay
|
|
966
|
+
|
|
967
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
968
|
+
# +level+ is the hierachical level of the object.
|
|
969
|
+
def to_vhdl(level = 0)
|
|
970
|
+
return self.value.to_vhdl(level) + " #{self.unit}"
|
|
971
|
+
end
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
## Extends the TimeWait class with generation of HDLRuby::High text.
|
|
976
|
+
class TimeWait
|
|
977
|
+
|
|
978
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
979
|
+
# +vars+ is the list of the variables and
|
|
980
|
+
# +level+ is the hierachical level of the object.
|
|
981
|
+
def to_vhdl(vars,level = 0)
|
|
982
|
+
# The resulting string.
|
|
983
|
+
res = " " * (level*3)
|
|
984
|
+
# Generate the wait.
|
|
985
|
+
res << "wait for " << self.delay.to_vhdl(level) << ";\n"
|
|
986
|
+
# Return the resulting string.
|
|
987
|
+
return res
|
|
988
|
+
end
|
|
989
|
+
end
|
|
990
|
+
|
|
991
|
+
## Extends the TimeRepeat class with generation of HDLRuby::High text.
|
|
992
|
+
class TimeRepeat
|
|
993
|
+
|
|
994
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
995
|
+
# +vars+ is the list of the variables and
|
|
996
|
+
# +level+ is the hierachical level of the object.
|
|
997
|
+
def to_vhdl(vars,level = 0)
|
|
998
|
+
raise AnyError, "Internal error: TimeRepeat not supported yet for conversion to VHDL."
|
|
999
|
+
end
|
|
1000
|
+
end
|
|
1001
|
+
|
|
1002
|
+
## Extends the Block class with generation of HDLRuby::High text.
|
|
1003
|
+
class Block
|
|
1004
|
+
|
|
1005
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1006
|
+
# +vars+ is the list of variables and
|
|
1007
|
+
# +level+ is the hierachical level of the object.
|
|
1008
|
+
#
|
|
1009
|
+
# NOTE: only the statements are generated, the remaining is assumed
|
|
1010
|
+
# to be handled by the upper scope.
|
|
1011
|
+
def to_vhdl(vars, level = 0)
|
|
1012
|
+
# The resulting string.
|
|
1013
|
+
res = ""
|
|
1014
|
+
# Generate the statements.
|
|
1015
|
+
self.each_statement do |stmnt|
|
|
1016
|
+
res << stmnt.to_vhdl(vars,level)
|
|
1017
|
+
end
|
|
1018
|
+
# Return the result.
|
|
1019
|
+
return res
|
|
1020
|
+
end
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
## Extends the TimeBlock class with generation of HDLRuby::High text.
|
|
1024
|
+
class TimeBlock
|
|
1025
|
+
# TimeBlock is identical to Block in VHDL
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
## Extends the Code class with generation of HDLRuby::High text.
|
|
1030
|
+
class Code
|
|
1031
|
+
|
|
1032
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1033
|
+
# +level+ is the hierachical level of the object.
|
|
1034
|
+
def to_vhdl(level = 0)
|
|
1035
|
+
raise "Code constructs cannot be converted into VHDL."
|
|
1036
|
+
end
|
|
1037
|
+
end
|
|
1038
|
+
|
|
1039
|
+
## Extends the Connection class with generation of HDLRuby::High text.
|
|
1040
|
+
class Connection
|
|
1041
|
+
# Nothing required, Transmit is generated identically.
|
|
1042
|
+
end
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
## Extends the Expression class with generation of HDLRuby::High text.
|
|
1046
|
+
class Expression
|
|
1047
|
+
|
|
1048
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1049
|
+
# +level+ is the hierachical level of the object.
|
|
1050
|
+
def to_vhdl(level = 0)
|
|
1051
|
+
# Should never be here.
|
|
1052
|
+
raise AnyError, "Internal error: to_vhdl should be implemented in class :#{self.class}"
|
|
1053
|
+
end
|
|
1054
|
+
end
|
|
1055
|
+
|
|
1056
|
+
## Extends the Value class with generation of HDLRuby::High text.
|
|
1057
|
+
class Value
|
|
1058
|
+
|
|
1059
|
+
# Generate the text of the equivalent VHDL is case of arithmetic
|
|
1060
|
+
# expression.
|
|
1061
|
+
def to_arith
|
|
1062
|
+
case self.content
|
|
1063
|
+
when HDLRuby::BitString
|
|
1064
|
+
if self.content.specified? then
|
|
1065
|
+
sign = self.type.signed? && self.content.to_s[-1] == "0" ?
|
|
1066
|
+
-1 : 1
|
|
1067
|
+
return (sign * self.content.to_s.to_i(2)).to_s
|
|
1068
|
+
else
|
|
1069
|
+
return self.content.to_s.upcase
|
|
1070
|
+
end
|
|
1071
|
+
else
|
|
1072
|
+
# NOTE: in VHDL, "z" and "x" must be upcase.
|
|
1073
|
+
return self.content.to_s.upcase
|
|
1074
|
+
end
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
# Generates the text of the equivalent VHDL with
|
|
1078
|
+
# +width+ bits.
|
|
1079
|
+
# +level+ is the hierachical level of the object.
|
|
1080
|
+
def to_vhdl(level = 0, std_logic = false, width = nil)
|
|
1081
|
+
raise "Invalid std_logic argument: #{std_logic}." unless std_logic == true || std_logic == false
|
|
1082
|
+
if self.type.boolean? then
|
|
1083
|
+
# Boolean case
|
|
1084
|
+
if self.content.is_a?(HDLRuby::BitString)
|
|
1085
|
+
return self.zero? ? "false" : "true"
|
|
1086
|
+
else
|
|
1087
|
+
return self.to_i == 0 ? "false" : "true"
|
|
1088
|
+
end
|
|
1089
|
+
end
|
|
1090
|
+
# Other cases
|
|
1091
|
+
# Maybe the value is used as a range or an index.
|
|
1092
|
+
if self.parent.is_a?(RefIndex) or self.parent.is_a?(RefRange) then
|
|
1093
|
+
# Yes, convert to a simple integer.
|
|
1094
|
+
return self.to_i.to_s.upcase
|
|
1095
|
+
end
|
|
1096
|
+
# No, generates as a bit string.
|
|
1097
|
+
width = self.type.width unless width
|
|
1098
|
+
# puts "self.type=#{self.type} width=#{width}"
|
|
1099
|
+
case self.content
|
|
1100
|
+
# when Numeric
|
|
1101
|
+
# return self.content.to_s
|
|
1102
|
+
when HDLRuby::BitString
|
|
1103
|
+
sign = self.type.signed? ? self.content.to_s[-1] : "0"
|
|
1104
|
+
return '"' + self.content.to_s.rjust(width,sign).upcase + '"'
|
|
1105
|
+
else
|
|
1106
|
+
sign = self.type.signed? ? (self.content>=0 ? "0" : "1") : "0"
|
|
1107
|
+
return '"' + self.content.to_s(2).rjust(width,sign).upcase + '"'
|
|
1108
|
+
end
|
|
1109
|
+
end
|
|
1110
|
+
end
|
|
1111
|
+
|
|
1112
|
+
## Extends the Cast class with generation of HDLRuby::High text.
|
|
1113
|
+
class Cast
|
|
1114
|
+
|
|
1115
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1116
|
+
# +level+ is the hierachical level of the object.
|
|
1117
|
+
def to_vhdl(level = 0)
|
|
1118
|
+
if type.class == TypeVector then
|
|
1119
|
+
case type.base.name
|
|
1120
|
+
when :bit
|
|
1121
|
+
return "std_logic_vector(resize(unsigned(" +
|
|
1122
|
+
self.child.to_vhdl(level) + ")," +
|
|
1123
|
+
(type.range.first-type.range.last+1).abs.to_s + "))"
|
|
1124
|
+
when :signed
|
|
1125
|
+
return "resize(signed(" +
|
|
1126
|
+
self.child.to_vhdl(level) + ")," +
|
|
1127
|
+
(type.range.first-type.range.last+1).abs.to_s + ")"
|
|
1128
|
+
when :unsigned
|
|
1129
|
+
return "resize(unsigned(" +
|
|
1130
|
+
self.child.to_vhdl(level) + ")," +
|
|
1131
|
+
(type.range.first-type.range.last+1).abs.to_s + ")"
|
|
1132
|
+
else
|
|
1133
|
+
raise "Intenal error: convertion to #{type.class} not supported yet for VHDL conversion."
|
|
1134
|
+
end
|
|
1135
|
+
elsif [:bit,:signed,:unsigned].include?(type.name) then
|
|
1136
|
+
# No conversion required.
|
|
1137
|
+
return self.child.to_vhdl(level)
|
|
1138
|
+
else
|
|
1139
|
+
raise "Intenal error: convertion to #{type.class} not supported yet for VHDL conversion."
|
|
1140
|
+
end
|
|
1141
|
+
end
|
|
1142
|
+
end
|
|
1143
|
+
|
|
1144
|
+
## Extends the Operation class with generation of HDLRuby::High text.
|
|
1145
|
+
class Operation
|
|
1146
|
+
|
|
1147
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1148
|
+
# +level+ is the hierachical level of the object.
|
|
1149
|
+
def to_vhdl(level = 0)
|
|
1150
|
+
# Should never be here.
|
|
1151
|
+
raise AnyError, "Internal error: to_vhdl should be implemented in class :#{self.class}"
|
|
1152
|
+
end
|
|
1153
|
+
end
|
|
1154
|
+
|
|
1155
|
+
## Extends the Unary class with generation of HDLRuby::High text.
|
|
1156
|
+
class Unary
|
|
1157
|
+
|
|
1158
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1159
|
+
# +level+ is the hierachical level of the object.
|
|
1160
|
+
# +std_logic+ tells if std_logic computation is to be done.
|
|
1161
|
+
def to_vhdl(level = 0, std_logic = false)
|
|
1162
|
+
# Generate the operator string.
|
|
1163
|
+
operator = self.operator == :~ ? "not " : self.operator.to_s[0]
|
|
1164
|
+
# Is the operator arithmetic?
|
|
1165
|
+
if [:+@, :-@].include?(self.operator) then
|
|
1166
|
+
# Yes, type conversion my be required by VHDL standard.
|
|
1167
|
+
res = "#{Low2VHDL.unarith_cast(self)}(#{operator}" +
|
|
1168
|
+
Low2VHDL.to_arith(self.child) + ")"
|
|
1169
|
+
res += "(0)" if std_logic
|
|
1170
|
+
return res
|
|
1171
|
+
else
|
|
1172
|
+
# No, generate simply the unary operation.
|
|
1173
|
+
# (The other unary operator is logic, no need to force
|
|
1174
|
+
# std_logic.)
|
|
1175
|
+
return "(#{operator}" + self.child.to_vhdl(level,std_logic) + ")"
|
|
1176
|
+
end
|
|
1177
|
+
end
|
|
1178
|
+
end
|
|
1179
|
+
|
|
1180
|
+
## Extends the Binary class with generation of HDLRuby::High text.
|
|
1181
|
+
class Binary
|
|
1182
|
+
|
|
1183
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1184
|
+
# +level+ is the hierachical level of the object.
|
|
1185
|
+
# +std_logic+ tells if std_logic computation is to be done.
|
|
1186
|
+
def to_vhdl(level = 0, std_logic = false)
|
|
1187
|
+
# Shifts/rotate require function call.
|
|
1188
|
+
if [:<<, :>>, :ls, :rs, :lr, :rr].include?(self.operator) then
|
|
1189
|
+
# Generate the function name.
|
|
1190
|
+
case self.operator
|
|
1191
|
+
when :<<, :ls
|
|
1192
|
+
func = "shift_left"
|
|
1193
|
+
when :>>, :rs
|
|
1194
|
+
func = "shift_right"
|
|
1195
|
+
when :lr
|
|
1196
|
+
func = "rotate_left"
|
|
1197
|
+
when :rr
|
|
1198
|
+
function = "rotate_right"
|
|
1199
|
+
else
|
|
1200
|
+
raise AnyError, "Internal unexpected error."
|
|
1201
|
+
end
|
|
1202
|
+
res = Low2VHDL.unarith_cast(self) + "(#{func}(" +
|
|
1203
|
+
Low2VHDL.to_arith(self.left) + "," +
|
|
1204
|
+
Low2VHDL.to_arith(self.right) + "))"
|
|
1205
|
+
res += "(0)" if std_logic # Force std_logic if required.
|
|
1206
|
+
return res
|
|
1207
|
+
end
|
|
1208
|
+
# Usual operators.
|
|
1209
|
+
# Generate the operator string.
|
|
1210
|
+
case self.operator
|
|
1211
|
+
when :&
|
|
1212
|
+
# puts "self.left.to_vhdl=#{self.left.to_vhdl}"
|
|
1213
|
+
# puts "self.right.to_vhdl=#{self.right.to_vhdl}"
|
|
1214
|
+
# puts "self.left.type=#{self.left.type.to_vhdl}"
|
|
1215
|
+
# puts "self.right.type=#{self.right.type.to_vhdl}"
|
|
1216
|
+
# puts "self.type=#{self.type.to_vhdl}"
|
|
1217
|
+
opr = " and "
|
|
1218
|
+
when :|
|
|
1219
|
+
opr = " or "
|
|
1220
|
+
when :^
|
|
1221
|
+
opr = " xor "
|
|
1222
|
+
when :==
|
|
1223
|
+
opr = " = "
|
|
1224
|
+
when :!=
|
|
1225
|
+
opr = " /= "
|
|
1226
|
+
else
|
|
1227
|
+
opr = self.operator.to_s
|
|
1228
|
+
end
|
|
1229
|
+
# Is the operator arithmetic?
|
|
1230
|
+
if [:+, :-, :*, :/, :%].include?(self.operator) then
|
|
1231
|
+
# Yes, type conversion my be required by VHDL standard.
|
|
1232
|
+
res = "#{Low2VHDL.unarith_cast(self)}(" +
|
|
1233
|
+
Low2VHDL.to_arith(self.left) + opr +
|
|
1234
|
+
Low2VHDL.to_arith(self.right) + ")"
|
|
1235
|
+
res += "(0)" if std_logic # Force std_logic if required.
|
|
1236
|
+
return res
|
|
1237
|
+
# Is it a comparison ?
|
|
1238
|
+
elsif [:>, :<, :>=, :<=, :==, :!=].include?(self.operator) then
|
|
1239
|
+
# Generate comparison operation
|
|
1240
|
+
return "(" + self.left.to_vhdl(level) + opr +
|
|
1241
|
+
Low2VHDL.to_type(self.left.type,self.right) + ")"
|
|
1242
|
+
else
|
|
1243
|
+
# No, simply generate the binary operation
|
|
1244
|
+
if std_logic then
|
|
1245
|
+
return "(" + self.left.to_vhdl(level,std_logic) + opr +
|
|
1246
|
+
self.right.to_vhdl(level,std_logic) + ")"
|
|
1247
|
+
else
|
|
1248
|
+
return "(" + self.left.to_vhdl(level) + opr +
|
|
1249
|
+
Low2VHDL.to_type(self.left.type,self.right) + ")"
|
|
1250
|
+
end
|
|
1251
|
+
end
|
|
1252
|
+
end
|
|
1253
|
+
end
|
|
1254
|
+
|
|
1255
|
+
## Extends the Select class with generation of HDLRuby::High text.
|
|
1256
|
+
class Select
|
|
1257
|
+
|
|
1258
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1259
|
+
# +level+ is the hierachical level of the object.
|
|
1260
|
+
#
|
|
1261
|
+
# NOTE: assumes the existance of the mux function.
|
|
1262
|
+
def to_vhdl(level = 0, std_logic = false)
|
|
1263
|
+
# The resulting string.
|
|
1264
|
+
res = ""
|
|
1265
|
+
# The number of arguments.
|
|
1266
|
+
num = @choices.size
|
|
1267
|
+
# Generate the header.
|
|
1268
|
+
res << "#{Low2VHDL.mux_name(self.type.to_vhdl(level),num)}(" +
|
|
1269
|
+
self.select.to_vhdl(level) << ", "
|
|
1270
|
+
# Generate the choices
|
|
1271
|
+
res << self.each_choice.map do |choice|
|
|
1272
|
+
choice.to_vhdl(level+1)
|
|
1273
|
+
end.join(", ")
|
|
1274
|
+
# Close the select.
|
|
1275
|
+
res << ")"
|
|
1276
|
+
# Return the resulting string.
|
|
1277
|
+
return res
|
|
1278
|
+
end
|
|
1279
|
+
end
|
|
1280
|
+
|
|
1281
|
+
## Extends the Concat class with generation of HDLRuby::High text.
|
|
1282
|
+
class Concat
|
|
1283
|
+
|
|
1284
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1285
|
+
# +type+ is the expected type of the content.
|
|
1286
|
+
# +level+ is the hierachical level of the object.
|
|
1287
|
+
def to_vhdl(type,level = 0)
|
|
1288
|
+
raise "Invalid class for a type: #{type.class}" unless type.is_a?(Type)
|
|
1289
|
+
# The resulting string.
|
|
1290
|
+
res = ""
|
|
1291
|
+
# Generate the header.
|
|
1292
|
+
# Generate the expressions.
|
|
1293
|
+
# Depends if it is an initialization or not.
|
|
1294
|
+
# if self.type.is_a?(TypeTuple) then
|
|
1295
|
+
if self.parent.is_a?(SignalC) then
|
|
1296
|
+
res << "( " << self.each_expression.map do |expression|
|
|
1297
|
+
Low2VHDL.to_type(type,expression)
|
|
1298
|
+
end.join(",\n#{" "*((level+1)*3)}") << " )"
|
|
1299
|
+
else
|
|
1300
|
+
# Compute the width of the concatenation.
|
|
1301
|
+
width = self.each_expression.reduce(0) do |sum,expr|
|
|
1302
|
+
sum += expr.type.width
|
|
1303
|
+
end
|
|
1304
|
+
# Generate the missing bits if any.
|
|
1305
|
+
width = type.width - width
|
|
1306
|
+
res << '"' + "0" * width + '" & ' if width > 0
|
|
1307
|
+
# Generate the concatenation.
|
|
1308
|
+
res << self.each_expression.map do |expression|
|
|
1309
|
+
# "(" + Low2VHDL.to_type(type,expression) + ")"
|
|
1310
|
+
"(" + expression.to_vhdl(level+1) + ")"
|
|
1311
|
+
end.join(" & ")
|
|
1312
|
+
end
|
|
1313
|
+
# Return the resulting string.
|
|
1314
|
+
return res
|
|
1315
|
+
end
|
|
1316
|
+
end
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
## Extends the Ref class with generation of HDLRuby::High text.
|
|
1320
|
+
class Ref
|
|
1321
|
+
|
|
1322
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1323
|
+
# +level+ is the hierachical level of the object.
|
|
1324
|
+
def to_vhdl(level = 0)
|
|
1325
|
+
# Should never be here.
|
|
1326
|
+
raise AnyError, "Internal error: to_vhdl should be implemented in class :#{self.class}"
|
|
1327
|
+
end
|
|
1328
|
+
end
|
|
1329
|
+
|
|
1330
|
+
## Extends the RefConcat class with generation of HDLRuby::High text.
|
|
1331
|
+
class RefConcat
|
|
1332
|
+
|
|
1333
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1334
|
+
# +level+ is the hierachical level of the object.
|
|
1335
|
+
def to_vhdl(level = 0)
|
|
1336
|
+
# The resulting string.
|
|
1337
|
+
res = ""
|
|
1338
|
+
# Generate the header.
|
|
1339
|
+
res << "( "
|
|
1340
|
+
# Generate the references.
|
|
1341
|
+
res << self.each_ref.map do |ref|
|
|
1342
|
+
ref.to_vhdl(level+1)
|
|
1343
|
+
end.join(", ")
|
|
1344
|
+
# Close the select.
|
|
1345
|
+
res << " )"
|
|
1346
|
+
# Return the resulting string.
|
|
1347
|
+
return res
|
|
1348
|
+
end
|
|
1349
|
+
end
|
|
1350
|
+
|
|
1351
|
+
## Extends the RefIndex class with generation of HDLRuby::High text.
|
|
1352
|
+
class RefIndex
|
|
1353
|
+
|
|
1354
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1355
|
+
# +level+ is the hierachical level of the object.
|
|
1356
|
+
# +std_logic+ tells if std_logic computation is to be done.
|
|
1357
|
+
def to_vhdl(level = 0, std_logic = false)
|
|
1358
|
+
if self.index.is_a?(Value) then
|
|
1359
|
+
return self.ref.to_vhdl(level,std_logic) +
|
|
1360
|
+
"(#{self.index.to_vhdl(level)})"
|
|
1361
|
+
else
|
|
1362
|
+
return self.ref.to_vhdl(level,std_logic) +
|
|
1363
|
+
"(to_integer(unsigned(#{self.index.to_vhdl(level)})))"
|
|
1364
|
+
end
|
|
1365
|
+
end
|
|
1366
|
+
end
|
|
1367
|
+
|
|
1368
|
+
## Extends the RefRange class with generation of HDLRuby::High text.
|
|
1369
|
+
class RefRange
|
|
1370
|
+
|
|
1371
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1372
|
+
# +level+ is the hierachical level of the object.
|
|
1373
|
+
# +std_logic+ tells if std_logic computation is to be done.
|
|
1374
|
+
def to_vhdl(level = 0, std_logic = false)
|
|
1375
|
+
# Generates the direction.
|
|
1376
|
+
first = self.range.first
|
|
1377
|
+
first = first.content if first.is_a?(Value)
|
|
1378
|
+
last = self.range.last
|
|
1379
|
+
last = last.content if last.is_a?(Value)
|
|
1380
|
+
direction = first >= last ? "downto " : " to "
|
|
1381
|
+
# Generate the reference.
|
|
1382
|
+
# Forced std_logic case.
|
|
1383
|
+
if std_logic then
|
|
1384
|
+
if first == last then
|
|
1385
|
+
# No range, single bit access for forcing std_logic.
|
|
1386
|
+
return self.ref.to_vhdl(level) +
|
|
1387
|
+
"(#{self.range.first.to_vhdl(level)})"
|
|
1388
|
+
else
|
|
1389
|
+
return self.ref.to_vhdl(level) +
|
|
1390
|
+
"((#{self.range.first.to_vhdl(level)}) " +
|
|
1391
|
+
direction + "(#{self.range.last.to_vhdl(level)}))(0)"
|
|
1392
|
+
end
|
|
1393
|
+
else
|
|
1394
|
+
return self.ref.to_vhdl(level) +
|
|
1395
|
+
"((#{self.range.first.to_vhdl(level)}) " +
|
|
1396
|
+
direction + "(#{self.range.last.to_vhdl(level)}))"
|
|
1397
|
+
end
|
|
1398
|
+
end
|
|
1399
|
+
end
|
|
1400
|
+
|
|
1401
|
+
## Extends the RefName class with generation of HDLRuby::High text.
|
|
1402
|
+
class RefName
|
|
1403
|
+
|
|
1404
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1405
|
+
# +level+ is the hierachical level of the object.
|
|
1406
|
+
# +std_logic+ tells if std_logic computation is to be done.
|
|
1407
|
+
def to_vhdl(level = 0, std_logic = false)
|
|
1408
|
+
# The resulting string.
|
|
1409
|
+
res = ""
|
|
1410
|
+
# Generate the sub refs if any (case of struct).
|
|
1411
|
+
unless self.ref.is_a?(RefThis) then
|
|
1412
|
+
res << self.ref.to_vhdl(level) << "."
|
|
1413
|
+
end
|
|
1414
|
+
# Generates the current reference.
|
|
1415
|
+
res << Low2VHDL.vhdl_name(self.name)
|
|
1416
|
+
res << "(0)" if std_logic # Force to std_logic if required
|
|
1417
|
+
# Returns the resulting string.
|
|
1418
|
+
return res
|
|
1419
|
+
end
|
|
1420
|
+
end
|
|
1421
|
+
|
|
1422
|
+
## Extends the RefThis class with generation of HDLRuby::High text.
|
|
1423
|
+
class RefThis
|
|
1424
|
+
# Nothing to generate.
|
|
1425
|
+
end
|
|
1426
|
+
|
|
1427
|
+
## Extends the Numeric class with generation of HDLRuby::High text.
|
|
1428
|
+
class ::Numeric
|
|
1429
|
+
|
|
1430
|
+
# Generates the text of the equivalent HDLRuby::High code.
|
|
1431
|
+
# +level+ is the hierachical level of the object.
|
|
1432
|
+
def to_vhdl(level = 0)
|
|
1433
|
+
return self.to_s
|
|
1434
|
+
end
|
|
1435
|
+
end
|
|
1436
|
+
|
|
1437
|
+
end
|