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,4103 @@
|
|
|
1
|
+
require "HDLRuby/hruby_low"
|
|
2
|
+
require "HDLRuby/hruby_tools"
|
|
3
|
+
require "HDLRuby/hruby_types"
|
|
4
|
+
require "HDLRuby/hruby_values"
|
|
5
|
+
require "HDLRuby/hruby_bstr"
|
|
6
|
+
require "HDLRuby/hruby_low_mutable"
|
|
7
|
+
|
|
8
|
+
require 'set'
|
|
9
|
+
require 'forwardable'
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# High-level libraries for describing digital hardware.
|
|
13
|
+
#######################################################
|
|
14
|
+
module HDLRuby::High
|
|
15
|
+
|
|
16
|
+
# Tells HDLRuby is currently booting.
|
|
17
|
+
def self.booting?
|
|
18
|
+
true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Base = HDLRuby::Base
|
|
22
|
+
Low = HDLRuby::Low
|
|
23
|
+
|
|
24
|
+
# Gets the infinity.
|
|
25
|
+
def infinity
|
|
26
|
+
return HDLRuby::Infinity
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Module providing extension of class.
|
|
33
|
+
module SingletonExtend
|
|
34
|
+
# Adds the singleton contents of +obj+ to current eigen class.
|
|
35
|
+
#
|
|
36
|
+
# NOTE: conflicting existing singleton content will be overridden if
|
|
37
|
+
def eigen_extend(obj)
|
|
38
|
+
# puts "eigen_extend for #{self} class=#{self.class}"
|
|
39
|
+
obj.singleton_methods.each do |name|
|
|
40
|
+
next if name == :yaml_tag # Do not know why we need to skip
|
|
41
|
+
# puts "name=#{name}"
|
|
42
|
+
self.define_singleton_method(name, &obj.singleton_method(name))
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# Describes a namespace.
|
|
50
|
+
# Used for managing the access points to internals of hardware constructs.
|
|
51
|
+
class Namespace
|
|
52
|
+
|
|
53
|
+
include SingletonExtend
|
|
54
|
+
|
|
55
|
+
# The reserved names
|
|
56
|
+
RESERVED = [ :user, :initialize, :add_method, :concat_namespace,
|
|
57
|
+
:to_namespace, :user?, :user_deep? ]
|
|
58
|
+
|
|
59
|
+
# The construct using the namespace.
|
|
60
|
+
attr_reader :user
|
|
61
|
+
|
|
62
|
+
# Creates a new namespace attached to +user+.
|
|
63
|
+
def initialize(user)
|
|
64
|
+
# Sets the user.
|
|
65
|
+
@user = user
|
|
66
|
+
# Initialize the concat namespaces.
|
|
67
|
+
@concats = []
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Clones (safely) the namespace.
|
|
71
|
+
def clone
|
|
72
|
+
# Create the new namespace.
|
|
73
|
+
res = Namespace.new(@user)
|
|
74
|
+
# Adds the concats.
|
|
75
|
+
@concats.each do |concat|
|
|
76
|
+
res.concat_namespace(concat)
|
|
77
|
+
end
|
|
78
|
+
return res
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Adds method +name+ provided the name is not empty and the method
|
|
82
|
+
# is not already defined in the current namespace.
|
|
83
|
+
def add_method(name,&ruby_block)
|
|
84
|
+
# puts "add_method with name=#{name} and parameters=#{ruby_block.parameters}"
|
|
85
|
+
unless name.empty? then
|
|
86
|
+
if RESERVED.include?(name.to_sym) then
|
|
87
|
+
raise AnyError,
|
|
88
|
+
"Resevered name #{name} cannot be overridden."
|
|
89
|
+
end
|
|
90
|
+
if self.respond_to?(name) then
|
|
91
|
+
raise AnyError,
|
|
92
|
+
"Symbol #{name} is already defined."
|
|
93
|
+
end
|
|
94
|
+
define_singleton_method(name,&ruby_block)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Concats another +namespace+ to current one.
|
|
99
|
+
def concat_namespace(namespace)
|
|
100
|
+
# Ensure namespace is really a namespace and concat it.
|
|
101
|
+
namespace = namespace.to_namespace
|
|
102
|
+
self.eigen_extend(namespace)
|
|
103
|
+
# Adds the concat the the list.
|
|
104
|
+
@concats << namespace
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Ensure it is a namespace
|
|
108
|
+
def to_namespace
|
|
109
|
+
return self
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Tell if an +object+ is the user of the namespace.
|
|
113
|
+
def user?(object)
|
|
114
|
+
return @user.equal?(object)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Tell if an +object+ is the user of the namespace or of one of its
|
|
118
|
+
# concats.
|
|
119
|
+
def user_deep?(object)
|
|
120
|
+
# puts "@user=#{@user}, @concats=#{@concats.size}, object=#{object}"
|
|
121
|
+
# Convert the object to a user if appliable (for SystemT)
|
|
122
|
+
object = object.to_user if object.respond_to?(:to_user)
|
|
123
|
+
# Maybe object is the user of this namespace.
|
|
124
|
+
return true if user?(object)
|
|
125
|
+
# No, try in the concat namespaces.
|
|
126
|
+
@concats.any? { |concat| concat.user_deep?(object) }
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
# Module providing handling of unknown methods for hardware constructs.
|
|
133
|
+
module Hmissing
|
|
134
|
+
High = HDLRuby::High
|
|
135
|
+
|
|
136
|
+
# Missing methods may be immediate values, if not, they are looked up
|
|
137
|
+
# in the upper level of the namespace if any.
|
|
138
|
+
def method_missing(m, *args, &ruby_block)
|
|
139
|
+
# puts "method_missing in class=#{self.class} with m=#{m}"
|
|
140
|
+
# Is the missing method an immediate value?
|
|
141
|
+
value = m.to_value
|
|
142
|
+
return value if value and args.empty?
|
|
143
|
+
# No, is there an upper namespace, i.e. is the current object
|
|
144
|
+
# present in the space?
|
|
145
|
+
if High.space_index(self) then
|
|
146
|
+
# Yes, self is in it, can try the methods in the space.
|
|
147
|
+
High.space_call(m,*args,&ruby_block)
|
|
148
|
+
elsif self.respond_to?(:namespace) and
|
|
149
|
+
High.space_index(self.namespace) then
|
|
150
|
+
# Yes, the private namespace is in it, can try the methods in
|
|
151
|
+
# the space.
|
|
152
|
+
begin
|
|
153
|
+
High.space_call(m,*args,&ruby_block)
|
|
154
|
+
end
|
|
155
|
+
elsif self.respond_to?(:public_namespace) and
|
|
156
|
+
High.space_index(self.public_namespace) then
|
|
157
|
+
# Yes, the private namespace is in it, can try the methods in
|
|
158
|
+
# the space.
|
|
159
|
+
High.space_call(m,*args,&ruby_block)
|
|
160
|
+
else
|
|
161
|
+
# No, this is a true error.
|
|
162
|
+
raise NotDefinedError, "undefined HDLRuby construct, local variable or method `#{m}'."
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
module HScope_missing
|
|
168
|
+
|
|
169
|
+
include Hmissing
|
|
170
|
+
|
|
171
|
+
alias_method :h_missing, :method_missing
|
|
172
|
+
|
|
173
|
+
# Missing methods are looked for in the private namespace.
|
|
174
|
+
#
|
|
175
|
+
# NOTE: it is ok to use the private namespace because the scope
|
|
176
|
+
# can only be accessed if it is available from its systemT.
|
|
177
|
+
def method_missing(m, *args, &ruby_block)
|
|
178
|
+
# puts "looking for #{m} in #{self}"
|
|
179
|
+
# Is the scope currently opened?
|
|
180
|
+
# if High.space_top.user_deep?(self) then
|
|
181
|
+
if High.space_index(self.namespace) then
|
|
182
|
+
# Yes, use the stack of namespaces.
|
|
183
|
+
h_missing(m,*args,&ruby_block)
|
|
184
|
+
else
|
|
185
|
+
# No, look into the current namespace and return a reference
|
|
186
|
+
# to the result if it is a referable hardware object.
|
|
187
|
+
res = self.namespace.send(m,*args,&ruby_block)
|
|
188
|
+
if res.respond_to?(:to_ref) then
|
|
189
|
+
# This is a referable object, build the reference from
|
|
190
|
+
# the namespace.
|
|
191
|
+
return RefObject.new(self.to_ref,res)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
##
|
|
199
|
+
# Module providing methods for declaring select expressions.
|
|
200
|
+
module Hmux
|
|
201
|
+
# Creates an operator selecting from +select+ one of the +choices+.
|
|
202
|
+
#
|
|
203
|
+
# NOTE: * +choices+ can either be a list of arguments or an array.
|
|
204
|
+
# If +choices+ has only two entries (and it is not a hash),
|
|
205
|
+
# +value+ will be converted to a boolean.
|
|
206
|
+
# * The type of the select is computed as the largest no
|
|
207
|
+
# integer-constant choice. If only constant integer choices,
|
|
208
|
+
# use the largest type of them.
|
|
209
|
+
def mux(select,*choices)
|
|
210
|
+
# Process the choices.
|
|
211
|
+
choices = choices.flatten(1) if choices.size == 1
|
|
212
|
+
choices.map! { |choice| choice.to_expr }
|
|
213
|
+
# Compute the type of the select as the largest no
|
|
214
|
+
# integer-constant type.
|
|
215
|
+
# If only such constants, use the largest type of them.
|
|
216
|
+
type = choices.reduce(Bit) do |type,choice|
|
|
217
|
+
unless choice.is_a?(Value) && choice.type == Integer then
|
|
218
|
+
type.width >= choice.type.width ? type : choice.type
|
|
219
|
+
else
|
|
220
|
+
type
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
unless type then
|
|
224
|
+
type = choices.reduce(Bit) do |type,choice|
|
|
225
|
+
type.width >= choice.type.width ? type : choice.type
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
# Generate the select expression.
|
|
229
|
+
return Select.new(type,"?",select.to_expr,*choices)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
##
|
|
235
|
+
# Module providing declaration of inner signal (assumes inner signals
|
|
236
|
+
# are present.
|
|
237
|
+
module Hinner
|
|
238
|
+
|
|
239
|
+
# Only adds the methods if not present.
|
|
240
|
+
def self.included(klass)
|
|
241
|
+
klass.class_eval do
|
|
242
|
+
unless instance_methods.include?(:make_inners) then
|
|
243
|
+
# Creates and adds a set of inners typed +type+ from a
|
|
244
|
+
# list of +names+.
|
|
245
|
+
#
|
|
246
|
+
# NOTE: * a name can also be a signal, is which case it is
|
|
247
|
+
# duplicated.
|
|
248
|
+
# * a name can also be a hash containing names
|
|
249
|
+
# associated with an initial value.
|
|
250
|
+
def make_inners(type, *names)
|
|
251
|
+
res = nil
|
|
252
|
+
names.each do |name|
|
|
253
|
+
if name.respond_to?(:to_sym) then
|
|
254
|
+
# Adds the inner signal
|
|
255
|
+
res = self.add_inner(
|
|
256
|
+
SignalI.new(name,type,:inner))
|
|
257
|
+
elsif name.is_a?(Hash) then
|
|
258
|
+
# Names associated with values.
|
|
259
|
+
names.each do |name,value|
|
|
260
|
+
res = self.add_inner(
|
|
261
|
+
SignalI.new(name,type,:inner,value))
|
|
262
|
+
end
|
|
263
|
+
else
|
|
264
|
+
raise AnyError,
|
|
265
|
+
"Invalid class for a name: #{name.class}"
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
return res
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
unless instance_methods.include?(:make_constants) then
|
|
273
|
+
# Creates and adds a set of contants typed +type+ from a
|
|
274
|
+
# hsh given names and corresponding values.
|
|
275
|
+
def make_constants(type, hsh)
|
|
276
|
+
res = nil
|
|
277
|
+
hsh.each do |name,value|
|
|
278
|
+
# Adds the Constant signal
|
|
279
|
+
res = self.add_inner(SignalC.new(name,type,value))
|
|
280
|
+
end
|
|
281
|
+
return res
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
unless instance_methods.include?(:inner) then
|
|
286
|
+
# Declares high-level bit inner signals named +names+.
|
|
287
|
+
def inner(*names)
|
|
288
|
+
self.make_inners(bit,*names)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
unless instance_methods.include?(:constant) then
|
|
293
|
+
# Declares high-level untyped constant signals by name and
|
|
294
|
+
# value given by +hsh+ of the current type.
|
|
295
|
+
def constant(hsh)
|
|
296
|
+
self.make_constants(bit,hsh)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# Classes describing hardware types.
|
|
305
|
+
|
|
306
|
+
##
|
|
307
|
+
# Describes a high-level system type.
|
|
308
|
+
class SystemT < Low::SystemT
|
|
309
|
+
High = HDLRuby::High
|
|
310
|
+
|
|
311
|
+
# include Hinner
|
|
312
|
+
|
|
313
|
+
include SingletonExtend
|
|
314
|
+
|
|
315
|
+
# The public namespace
|
|
316
|
+
#
|
|
317
|
+
# NOTE: the private namespace is the namespace of the scope object.
|
|
318
|
+
attr_reader :public_namespace
|
|
319
|
+
|
|
320
|
+
##
|
|
321
|
+
# Creates a new high-level system type named +name+ and inheriting
|
|
322
|
+
# from +mixins+.
|
|
323
|
+
#
|
|
324
|
+
# # If name is hash, it is considered the system is unnamed and the
|
|
325
|
+
# # table is used to rename its signals or instances.
|
|
326
|
+
#
|
|
327
|
+
# The proc +ruby_block+ is executed when instantiating the system.
|
|
328
|
+
def initialize(name, *mixins, &ruby_block)
|
|
329
|
+
# Initialize the system type structure.
|
|
330
|
+
super(name,Scope.new(name,self))
|
|
331
|
+
|
|
332
|
+
# Initialize the set of extensions to transmit to the instances'
|
|
333
|
+
# eigen class
|
|
334
|
+
@singleton_instanceO = Namespace.new(self.scope)
|
|
335
|
+
|
|
336
|
+
# Create the public namespace.
|
|
337
|
+
@public_namespace = Namespace.new(self.scope)
|
|
338
|
+
|
|
339
|
+
# Check and set the mixins.
|
|
340
|
+
mixins.each do |mixin|
|
|
341
|
+
unless mixin.is_a?(SystemT) then
|
|
342
|
+
raise AnyError,
|
|
343
|
+
"Invalid class for inheriting: #{mixin.class}."
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
@to_includes = mixins
|
|
347
|
+
# Prepare the instantiation methods
|
|
348
|
+
make_instantiater(name,SystemI,&ruby_block)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# Converts to a namespace user.
|
|
352
|
+
def to_user
|
|
353
|
+
# Returns the scope.
|
|
354
|
+
return @scope
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Creates and adds a set of inputs typed +type+ from a list of +names+.
|
|
358
|
+
#
|
|
359
|
+
# NOTE: a name can also be a signal, is which case it is duplicated.
|
|
360
|
+
def make_inputs(type, *names)
|
|
361
|
+
# Check if called within the top scope of the block.
|
|
362
|
+
if High.top_user != @scope then
|
|
363
|
+
# No, cannot make an input from here.
|
|
364
|
+
raise AnyError,
|
|
365
|
+
"Input signals can only be declared in the top scope of a system."
|
|
366
|
+
end
|
|
367
|
+
res = nil
|
|
368
|
+
names.each do |name|
|
|
369
|
+
if name.respond_to?(:to_sym) then
|
|
370
|
+
res = self.add_input(SignalI.new(name,type,:input))
|
|
371
|
+
elsif name.is_a?(Hash) then
|
|
372
|
+
# Names associated with values.
|
|
373
|
+
names.each do |name,value|
|
|
374
|
+
res = self.add_inner(
|
|
375
|
+
SignalI.new(name,type,:inner,value))
|
|
376
|
+
end
|
|
377
|
+
else
|
|
378
|
+
raise AnyError, "Invalid class for a name: #{name.class}"
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
return res
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Creates and adds a set of outputs typed +type+ from a list of +names+.
|
|
385
|
+
#
|
|
386
|
+
# NOTE: a name can also be a signal, is which case it is duplicated.
|
|
387
|
+
def make_outputs(type, *names)
|
|
388
|
+
# puts "type=#{type.inspect}"
|
|
389
|
+
res = nil
|
|
390
|
+
names.each do |name|
|
|
391
|
+
# puts "name=#{name}"
|
|
392
|
+
if name.respond_to?(:to_sym) then
|
|
393
|
+
res = self.add_output(SignalI.new(name,type,:output))
|
|
394
|
+
elsif name.is_a?(Hash) then
|
|
395
|
+
# Names associated with values.
|
|
396
|
+
names.each do |name,value|
|
|
397
|
+
res = self.add_inner(
|
|
398
|
+
SignalI.new(name,type,:inner,value))
|
|
399
|
+
end
|
|
400
|
+
else
|
|
401
|
+
raise AnyError, "Invalid class for a name: #{name.class}"
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
return res
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
# Creates and adds a set of inouts typed +type+ from a list of +names+.
|
|
408
|
+
#
|
|
409
|
+
# NOTE: a name can also be a signal, is which case it is duplicated.
|
|
410
|
+
def make_inouts(type, *names)
|
|
411
|
+
res = nil
|
|
412
|
+
names.each do |name|
|
|
413
|
+
if name.respond_to?(:to_sym) then
|
|
414
|
+
res = self.add_inout(SignalI.new(name,type,:inout))
|
|
415
|
+
elsif name.is_a?(Hash) then
|
|
416
|
+
# Names associated with values.
|
|
417
|
+
names.each do |name,value|
|
|
418
|
+
res = self.add_inner(
|
|
419
|
+
SignalI.new(name,type,:inner,value))
|
|
420
|
+
end
|
|
421
|
+
else
|
|
422
|
+
raise AnyError, "Invalid class for a name: #{name.class}"
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
return res
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# Iterates over the all interface signals, i.e, also the ones of
|
|
429
|
+
# the included systems.
|
|
430
|
+
#
|
|
431
|
+
# Returns an enumerator if no ruby block is given.
|
|
432
|
+
def each_signal_with_included(&ruby_block)
|
|
433
|
+
# No ruby block? Return an enumerator.
|
|
434
|
+
return to_enum(:each_signal_with_included) unless ruby_block
|
|
435
|
+
# Iterate on the signals of the current system.
|
|
436
|
+
self.each_signal(&ruby_block)
|
|
437
|
+
# Recurse on the included systems.
|
|
438
|
+
self.scope.each_included do |included|
|
|
439
|
+
included.each_signal_with_included(&ruby_block)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
# Get one of all the interface signal by index, i.e., also the ones
|
|
444
|
+
# of the included systems.
|
|
445
|
+
def get_interface_with_included(i)
|
|
446
|
+
return each_signal_with_included.to_a[i]
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
# Iterates over the exported constructs
|
|
450
|
+
#
|
|
451
|
+
# NOTE: look into the scope.
|
|
452
|
+
def each_export(&ruby_block)
|
|
453
|
+
@scope.each_export(&ruby_block)
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Gets class containing the extension for the instances.
|
|
457
|
+
def singleton_instance
|
|
458
|
+
@singleton_instanceO.singleton_class
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
# Gets the private namespace of the system.
|
|
462
|
+
def namespace
|
|
463
|
+
return self.scope.namespace
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# Execute +ruby_block+ in the context of the system.
|
|
467
|
+
def run(&ruby_block)
|
|
468
|
+
self.scope.open(&ruby_block)
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
# Opens for extension.
|
|
472
|
+
#
|
|
473
|
+
# NOTE: actually executes +ruby_block+ in the context of the scope
|
|
474
|
+
# of the system.
|
|
475
|
+
def open(&ruby_block)
|
|
476
|
+
# Are we instantiating current system?
|
|
477
|
+
if (High.space_include?(self.scope.namespace)) then
|
|
478
|
+
# Yes, execute the ruby block in the top context of the
|
|
479
|
+
# system.
|
|
480
|
+
# self.scope.open(&ruby_block)
|
|
481
|
+
self.run(&ruby_block)
|
|
482
|
+
else
|
|
483
|
+
# No, add the ruby block to the list of block to execute
|
|
484
|
+
# when instantiating.
|
|
485
|
+
@instance_procs << ruby_block
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
# The instantiation target class.
|
|
490
|
+
attr_reader :instance_class
|
|
491
|
+
|
|
492
|
+
# Iterates over the instance procedures.
|
|
493
|
+
#
|
|
494
|
+
# Returns an enumerator if no ruby block is given.
|
|
495
|
+
def each_instance_proc(&ruby_block)
|
|
496
|
+
# No ruby block? Return an enumerator.
|
|
497
|
+
return to_enum(:each_instance_proc) unless ruby_block
|
|
498
|
+
# A block? Apply it on each input signal instance.
|
|
499
|
+
@instance_procs.each(&ruby_block)
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
# Expands the system with possible arugments +args+ to a new system
|
|
503
|
+
# named +name+.
|
|
504
|
+
def expand(name, *args)
|
|
505
|
+
# puts "expand #{self.name} to #{name}"
|
|
506
|
+
# Create the new system.
|
|
507
|
+
expanded = self.class.new(name.to_s) {}
|
|
508
|
+
# Include the mixin systems given when declaring the system.
|
|
509
|
+
@to_includes.each { |system| expanded.scope.include(system) }
|
|
510
|
+
|
|
511
|
+
# Fills the scope of the expanded class.
|
|
512
|
+
# puts "Build top with #{self.name} for #{name}"
|
|
513
|
+
expanded.scope.build_top(self.scope,*args)
|
|
514
|
+
# puts "Top built with #{self.name} for #{name}"
|
|
515
|
+
return expanded
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
# Make a system eigen of a given +instance+.
|
|
519
|
+
def eigenize(instance)
|
|
520
|
+
unless instance.systemT == self then
|
|
521
|
+
raise "Cannot eigenize system #{self.name} to instance #{instance.name}"
|
|
522
|
+
end
|
|
523
|
+
# The instance becames the owner.
|
|
524
|
+
@owner = instance
|
|
525
|
+
# Fill the public namespace
|
|
526
|
+
space = self.public_namespace
|
|
527
|
+
# Interface signals
|
|
528
|
+
# puts "i_name=#{i_name} @to_includes=#{@to_includes.size}"
|
|
529
|
+
self.each_signal do |signal|
|
|
530
|
+
# puts "signal=#{signal.name}"
|
|
531
|
+
space.send(:define_singleton_method,signal.name) do
|
|
532
|
+
RefObject.new(instance.to_ref,signal)
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
# Exported objects
|
|
536
|
+
self.each_export do |export|
|
|
537
|
+
# puts "export=#{export.name}"
|
|
538
|
+
space.send(:define_singleton_method,export.name) do
|
|
539
|
+
RefObject.new(instance.to_ref,export)
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
return self
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
# Instantiate the system type to an instance named +i_name+ with
|
|
547
|
+
# possible arguments +args+.
|
|
548
|
+
def instantiate(i_name,*args)
|
|
549
|
+
# Create the eigen type.
|
|
550
|
+
eigen = self.expand(High.names_create(i_name.to_s + ":T"), *args)
|
|
551
|
+
|
|
552
|
+
# Create the instance and sets its eigen system to +eigen+.
|
|
553
|
+
instance = @instance_class.new(i_name,eigen)
|
|
554
|
+
eigen.eigenize(instance)
|
|
555
|
+
# puts "instance interface=#{instance.each_signal.to_a.size}"
|
|
556
|
+
# puts "eigen interface=#{eigen.each_signal.to_a.size}"
|
|
557
|
+
|
|
558
|
+
# Extend the instance.
|
|
559
|
+
instance.eigen_extend(@singleton_instanceO)
|
|
560
|
+
# puts "instance scope= #{instance.systemT.scope}"
|
|
561
|
+
# Add the instance.
|
|
562
|
+
High.top_user.send(:add_systemI,instance)
|
|
563
|
+
# Return the resulting instance
|
|
564
|
+
return instance
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
# Instantiation can also be done throw the call operator.
|
|
568
|
+
alias_method :call, :instantiate
|
|
569
|
+
|
|
570
|
+
# Generates the instantiation capabilities including an instantiation
|
|
571
|
+
# method +name+ for hdl-like instantiation, target instantiation as
|
|
572
|
+
# +klass+, added to the calling object, and
|
|
573
|
+
# whose eigen type is initialized by +ruby_block+.
|
|
574
|
+
#
|
|
575
|
+
# NOTE: actually creates two instantiater, a general one, being
|
|
576
|
+
# registered in the namespace stack, and one for creating an
|
|
577
|
+
# array of instances being registered in the Array class.
|
|
578
|
+
def make_instantiater(name,klass,&ruby_block)
|
|
579
|
+
# puts "make_instantiater with name=#{name}"
|
|
580
|
+
# Set the instanciater.
|
|
581
|
+
@instance_procs = [ ruby_block ]
|
|
582
|
+
# Set the target instantiation class.
|
|
583
|
+
@instance_class = klass
|
|
584
|
+
|
|
585
|
+
# Unnamed types do not have associated access method.
|
|
586
|
+
return if name.empty?
|
|
587
|
+
|
|
588
|
+
obj = self # For using the right self within the proc
|
|
589
|
+
|
|
590
|
+
# Create and register the general instantiater.
|
|
591
|
+
High.space_reg(name) do |*args|
|
|
592
|
+
# puts "Instantiating #{name} with args=#{args.size}"
|
|
593
|
+
# If no arguments, return the system as is
|
|
594
|
+
return obj if args.empty?
|
|
595
|
+
# Are there any generic arguments?
|
|
596
|
+
if ruby_block.arity > 0 then
|
|
597
|
+
# Yes, must specialize the system with the arguments.
|
|
598
|
+
# If arguments, create a new system specialized with them
|
|
599
|
+
return SystemT.new(:"") { include(obj,*args) }
|
|
600
|
+
end
|
|
601
|
+
# It is the case where it is an instantiation
|
|
602
|
+
# Get the names from the arguments.
|
|
603
|
+
i_names = args.shift
|
|
604
|
+
# puts "i_names=#{i_names}(#{i_names.class})"
|
|
605
|
+
i_names = [*i_names]
|
|
606
|
+
instance = nil # The current instance
|
|
607
|
+
i_names.each do |i_name|
|
|
608
|
+
# Instantiate.
|
|
609
|
+
instance = obj.instantiate(i_name,*args)
|
|
610
|
+
end
|
|
611
|
+
# # Return the last instance.
|
|
612
|
+
instance
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
# Create and register the array of instances instantiater.
|
|
616
|
+
::Array.class_eval do
|
|
617
|
+
define_method(name) { |*args| make(name,*args) }
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
# Missing methods may be immediate values, if not, they are looked up
|
|
622
|
+
include Hmissing
|
|
623
|
+
|
|
624
|
+
# Methods used for describing a system in HDLRuby::High
|
|
625
|
+
|
|
626
|
+
# Declares high-level bit input signals named +names+.
|
|
627
|
+
#
|
|
628
|
+
# Retuns the last declared input.
|
|
629
|
+
def input(*names)
|
|
630
|
+
self.make_inputs(bit,*names)
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
# Declares high-level bit output signals named +names+.
|
|
634
|
+
#
|
|
635
|
+
# Retuns the last declared input.
|
|
636
|
+
def output(*names)
|
|
637
|
+
self.make_outputs(bit,*names)
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
# Declares high-level bit inout signals named +names+.
|
|
641
|
+
#
|
|
642
|
+
# Retuns the last declared input.
|
|
643
|
+
def inout(*names)
|
|
644
|
+
self.make_inouts(bit,*names)
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
# Extend the class according to another +system+.
|
|
648
|
+
def extend(system)
|
|
649
|
+
# Adds the singleton methods
|
|
650
|
+
self.eigen_extend(system)
|
|
651
|
+
# Adds the singleton methods for the instances.
|
|
652
|
+
@singleton_instanceO.eigen_extend(system.singleton_instance)
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
# Casts as an included +system+.
|
|
656
|
+
#
|
|
657
|
+
# NOTE: use the includes of the scope.
|
|
658
|
+
def as(system)
|
|
659
|
+
# return self.scope.as(system.scope)
|
|
660
|
+
return self.scope.as(system)
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
include Hmux
|
|
664
|
+
|
|
665
|
+
# Fills the interface of a low level system.
|
|
666
|
+
def fill_interface(systemTlow)
|
|
667
|
+
# Adds its input signals.
|
|
668
|
+
self.each_input { |input| systemTlow.add_input(input.to_low) }
|
|
669
|
+
# Adds its output signals.
|
|
670
|
+
self.each_output { |output| systemTlow.add_output(output.to_low) }
|
|
671
|
+
# Adds its inout signals.
|
|
672
|
+
self.each_inout { |inout| systemTlow.add_inout(inout.to_low) }
|
|
673
|
+
# Adds the interface of its included systems.
|
|
674
|
+
self.scope.each_included do |included|
|
|
675
|
+
included.fill_interface(systemTlow)
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
# Fills a low level system with self's contents.
|
|
680
|
+
#
|
|
681
|
+
# NOTE: name conflicts are treated in the current NameStack state.
|
|
682
|
+
def fill_low(systemTlow)
|
|
683
|
+
# Fills the interface
|
|
684
|
+
self.fill_interface(systemTlow)
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
# Converts the system to HDLRuby::Low and set its +name+.
|
|
688
|
+
def to_low(name = self.name)
|
|
689
|
+
name = name.to_s
|
|
690
|
+
if name.empty? then
|
|
691
|
+
raise AnyError,
|
|
692
|
+
"Cannot convert a system without a name to HDLRuby::Low."
|
|
693
|
+
end
|
|
694
|
+
# Create the resulting low system type.
|
|
695
|
+
systemTlow = HDLRuby::Low::SystemT.new(High.names_create(name),
|
|
696
|
+
self.scope.to_low)
|
|
697
|
+
# Fills the interface of the new system
|
|
698
|
+
# from the included systems.
|
|
699
|
+
self.fill_low(systemTlow)
|
|
700
|
+
# Return theresulting system.
|
|
701
|
+
return systemTlow
|
|
702
|
+
end
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
##
|
|
708
|
+
# Describes a scope for a system type
|
|
709
|
+
class Scope < Low::Scope
|
|
710
|
+
High = HDLRuby::High
|
|
711
|
+
|
|
712
|
+
# include HMix
|
|
713
|
+
include Hinner
|
|
714
|
+
|
|
715
|
+
include SingletonExtend
|
|
716
|
+
|
|
717
|
+
# The name of the scope if any.
|
|
718
|
+
attr_reader :name
|
|
719
|
+
|
|
720
|
+
# The namespace
|
|
721
|
+
attr_reader :namespace
|
|
722
|
+
|
|
723
|
+
# The return value when building the scope.
|
|
724
|
+
attr_reader :return_value
|
|
725
|
+
|
|
726
|
+
##
|
|
727
|
+
# Creates a new scope with possible +name+.
|
|
728
|
+
# If the scope is a top scope of a system, this systemT is
|
|
729
|
+
# given by +systemT+.
|
|
730
|
+
#
|
|
731
|
+
# The proc +ruby_block+ is executed for building the scope.
|
|
732
|
+
# If no block is provided, the scope is the top of a system and
|
|
733
|
+
# is filled by the instantiation procedure of the system.
|
|
734
|
+
def initialize(name = :"", systemT = nil, &ruby_block)
|
|
735
|
+
# Initialize the scope structure
|
|
736
|
+
super(name)
|
|
737
|
+
|
|
738
|
+
# Initialize the set of grouped system instances.
|
|
739
|
+
@groupIs = {}
|
|
740
|
+
|
|
741
|
+
# Creates the namespace.
|
|
742
|
+
@namespace = Namespace.new(self)
|
|
743
|
+
|
|
744
|
+
# Register the scope if it is not the top scope of a system
|
|
745
|
+
# (in which case the system has already be registered with
|
|
746
|
+
# the same name).
|
|
747
|
+
unless name.empty? or systemT then
|
|
748
|
+
# Named scope, set the hdl-like access to the scope.
|
|
749
|
+
obj = self # For using the right self within the proc
|
|
750
|
+
High.space_reg(name) { obj }
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
# Initialize the set of exported inner signals and instances
|
|
754
|
+
@exports = {}
|
|
755
|
+
# Initialize the set of included systems.
|
|
756
|
+
@includes = {}
|
|
757
|
+
|
|
758
|
+
# Builds the scope if a ruby block is provided
|
|
759
|
+
# (which means the scope is not the top of a system).
|
|
760
|
+
self.build(&ruby_block) if block_given?
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
# Converts to a namespace user.
|
|
764
|
+
def to_user
|
|
765
|
+
# Already a user.
|
|
766
|
+
return self
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
# Adds a group of system +instances+ named +name+.
|
|
770
|
+
def add_groupI(name, *instances)
|
|
771
|
+
# Ensure name is a symbol and is not already used for another
|
|
772
|
+
# group.
|
|
773
|
+
name = name.to_sym
|
|
774
|
+
if @groupIs.key?(name)
|
|
775
|
+
raise AnyError,
|
|
776
|
+
"Group of system instances named #{name} already exist."
|
|
777
|
+
end
|
|
778
|
+
# Add the group.
|
|
779
|
+
@groupIs[name.to_sym] = instances
|
|
780
|
+
# Sets the parent of the instances.
|
|
781
|
+
instances.each { |instance| instance.parent = self }
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
# Access a group of system instances by +name+.
|
|
785
|
+
#
|
|
786
|
+
# NOTE: the result is a copy of the group for avoiding side effects.
|
|
787
|
+
def get_groupI(name)
|
|
788
|
+
return @groupIs[name.to_sym].clone
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
# Iterates over the group of system instances.
|
|
792
|
+
#
|
|
793
|
+
# Returns an enumerator if no ruby block is given.
|
|
794
|
+
def each_groupI(&ruby_block)
|
|
795
|
+
# No ruby block? Return an enumerator.
|
|
796
|
+
return to_enum(:each_groupI) unless ruby_block
|
|
797
|
+
# A block? Apply it on each input signal instance.
|
|
798
|
+
@groupIs.each(&ruby_block)
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
# Adds a +name+ to export.
|
|
802
|
+
#
|
|
803
|
+
# NOTE: if the name do not corresponds to any inner signal nor
|
|
804
|
+
# instance, raise an exception.
|
|
805
|
+
def add_export(name)
|
|
806
|
+
# Check the name.
|
|
807
|
+
name = name.to_sym
|
|
808
|
+
# Look for construct to make public.
|
|
809
|
+
# Maybe it is an inner signals.
|
|
810
|
+
inner = self.get_inner(name)
|
|
811
|
+
if inner then
|
|
812
|
+
# Yes set it as export.
|
|
813
|
+
@exports[name] = inner
|
|
814
|
+
return
|
|
815
|
+
end
|
|
816
|
+
# No, maybe it is an instance.
|
|
817
|
+
instance = self.get_systemI(name)
|
|
818
|
+
if instance then
|
|
819
|
+
# Yes, set it as export.
|
|
820
|
+
@exports[name] = instance
|
|
821
|
+
return
|
|
822
|
+
end
|
|
823
|
+
# No, error.
|
|
824
|
+
raise AnyError, "Invalid name for export: #{name}"
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
# Iterates over the exported constructs.
|
|
828
|
+
#
|
|
829
|
+
# Returns an enumerator if no ruby block is given.
|
|
830
|
+
def each_export(&ruby_block)
|
|
831
|
+
# No ruby block? Return an enumerator.
|
|
832
|
+
return to_enum(:each_export) unless ruby_block
|
|
833
|
+
# A block? Apply it on each input signal instance.
|
|
834
|
+
@exports.each_value(&ruby_block)
|
|
835
|
+
# And apply on the sub scopes if any.
|
|
836
|
+
@scopes.each {|scope| scope.each_export(&ruby_block) }
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
# Iterates over the included systems.
|
|
840
|
+
def each_included(&ruby_block)
|
|
841
|
+
# No ruby block? Return an enumerator.
|
|
842
|
+
return to_enum(:each_included) unless ruby_block
|
|
843
|
+
# A block? Apply it on each included system.
|
|
844
|
+
@includes.each_value(&ruby_block)
|
|
845
|
+
# And apply on the sub scopes if any.
|
|
846
|
+
@scopes.each {|scope| scope.each_included(&ruby_block) }
|
|
847
|
+
end
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
# Opens for extension.
|
|
851
|
+
#
|
|
852
|
+
# NOTE: actually executes +ruby_block+ in the context.
|
|
853
|
+
def open(&ruby_block)
|
|
854
|
+
High.space_push(@namespace)
|
|
855
|
+
res = High.top_user.instance_eval(&ruby_block)
|
|
856
|
+
High.space_pop
|
|
857
|
+
# Return the result of the execution so that it can be used
|
|
858
|
+
# as an expression
|
|
859
|
+
res
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
# Build the scope by executing +ruby_block+.
|
|
864
|
+
#
|
|
865
|
+
# NOTE: used when the scope is not the top of a system.
|
|
866
|
+
def build(&ruby_block)
|
|
867
|
+
# Set the namespace for buidling the scope.
|
|
868
|
+
High.space_push(@namespace)
|
|
869
|
+
# Build the scope.
|
|
870
|
+
@return_value = High.top_user.instance_eval(&ruby_block)
|
|
871
|
+
High.space_pop
|
|
872
|
+
@return_value
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
# Builds the scope using +base+ as model scope with possible arguments
|
|
877
|
+
# +args+.
|
|
878
|
+
#
|
|
879
|
+
# NOTE: Used by the instantiation procedure of a system.
|
|
880
|
+
def build_top(base,*args)
|
|
881
|
+
# Fills its namespace with the content of the base scope
|
|
882
|
+
# (this latter may already contains access points if it has been
|
|
883
|
+
# opended for extension previously).
|
|
884
|
+
@namespace.concat_namespace(base.namespace)
|
|
885
|
+
High.space_push(@namespace)
|
|
886
|
+
# Execute the instantiation block
|
|
887
|
+
# instance_proc = base.parent.instance_proc if base.parent.respond_to?(:instance_proc)
|
|
888
|
+
# @return_value = High.top_user.instance_exec(*args,&instance_proc) if instance_proc
|
|
889
|
+
base.parent.each_instance_proc do |instance_proc|
|
|
890
|
+
@return_value = High.top_user.instance_exec(*args,&instance_proc)
|
|
891
|
+
end
|
|
892
|
+
High.space_pop
|
|
893
|
+
end
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
# Methods delegated to the upper system.
|
|
897
|
+
|
|
898
|
+
# Adds input +signal+ in the current system.
|
|
899
|
+
def add_input(signal)
|
|
900
|
+
self.parent.add_input(signal)
|
|
901
|
+
end
|
|
902
|
+
|
|
903
|
+
# Adds output +signal+ in the current system.
|
|
904
|
+
def add_output(signal)
|
|
905
|
+
self.parent.add_output(signal)
|
|
906
|
+
end
|
|
907
|
+
|
|
908
|
+
# Adds inout +signal+ in the current system.
|
|
909
|
+
def add_inout(signal)
|
|
910
|
+
self.parent.add_inout(signal)
|
|
911
|
+
end
|
|
912
|
+
|
|
913
|
+
# Creates and adds a set of inputs typed +type+ from a list of +names+
|
|
914
|
+
# in the current system.
|
|
915
|
+
#
|
|
916
|
+
# NOTE: a name can also be a signal, is which case it is duplicated.
|
|
917
|
+
def make_inputs(type, *names)
|
|
918
|
+
self.parent.make_inputs(type,*names)
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
# Creates and adds a set of outputs typed +type+ from a list of +names+
|
|
922
|
+
# in the current system.
|
|
923
|
+
#
|
|
924
|
+
# NOTE: a name can also be a signal, is which case it is duplicated.
|
|
925
|
+
def make_outputs(type, *names)
|
|
926
|
+
self.parent.make_outputs(type,*names)
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
# Creates and adds a set of inouts typed +type+ from a list of +names+
|
|
930
|
+
# in the current system.
|
|
931
|
+
#
|
|
932
|
+
# NOTE: a name can also be a signal, is which case it is duplicated.
|
|
933
|
+
def make_inouts(type, *names)
|
|
934
|
+
self.parent.make_inouts(type,*names)
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
# Converts to a new reference.
|
|
938
|
+
def to_ref
|
|
939
|
+
return RefObject.new(this,self)
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
include HScope_missing
|
|
944
|
+
|
|
945
|
+
# Methods used for describing a system in HDLRuby::High
|
|
946
|
+
|
|
947
|
+
# Declares high-level bit input signals named +names+
|
|
948
|
+
# in the current system.
|
|
949
|
+
def input(*names)
|
|
950
|
+
self.parent.input(*names)
|
|
951
|
+
end
|
|
952
|
+
|
|
953
|
+
# Declares high-level bit output signals named +names+
|
|
954
|
+
# in the current system.
|
|
955
|
+
def output(*names)
|
|
956
|
+
self.parent.output(*names)
|
|
957
|
+
end
|
|
958
|
+
|
|
959
|
+
# Declares high-level bit inout signals named +names+
|
|
960
|
+
# in the current system.
|
|
961
|
+
def inout(*names)
|
|
962
|
+
self.parent.inout(*names)
|
|
963
|
+
end
|
|
964
|
+
|
|
965
|
+
# Declares a non-HDLRuby set of code chunks described by +content+ and
|
|
966
|
+
# completed from +ruby_block+ execution result.
|
|
967
|
+
# NOTE: content includes the events to activate the code on and
|
|
968
|
+
# a description of the code as a hash assotiating names
|
|
969
|
+
# to code text.
|
|
970
|
+
def code(*content, &ruby_block)
|
|
971
|
+
# Process the content.
|
|
972
|
+
# Separate events from code chunks descriptions.
|
|
973
|
+
events, chunks = content.partition {|elem| elem.is_a?(Event) }
|
|
974
|
+
# Generates a large hash from the code.
|
|
975
|
+
chunks = chunks.reduce(:merge)
|
|
976
|
+
# Adds the result of the ruby block if any.
|
|
977
|
+
if ruby_block then
|
|
978
|
+
chunks.merge(HDLRuby::High.top_user.instance_eval(&ruby_block))
|
|
979
|
+
end
|
|
980
|
+
# Create the chunk objects.
|
|
981
|
+
chunks = chunks.each.map do |name,content|
|
|
982
|
+
content = [*content]
|
|
983
|
+
# Process the lumps
|
|
984
|
+
content.map! do |lump|
|
|
985
|
+
lump.respond_to?(:to_expr) ? lump.to_expr : lump
|
|
986
|
+
end
|
|
987
|
+
Chunk.new(name,*content)
|
|
988
|
+
end
|
|
989
|
+
# Create the code object.
|
|
990
|
+
res = Code.new
|
|
991
|
+
# Adds the events.
|
|
992
|
+
events.each(&res.method(:add_event))
|
|
993
|
+
# Adds the chunks.
|
|
994
|
+
chunks.each(&res.method(:add_chunk))
|
|
995
|
+
# Adds the resulting code to the current scope.
|
|
996
|
+
HDLRuby::High.top_user.add_code(res)
|
|
997
|
+
# Return the resulting code
|
|
998
|
+
return res
|
|
999
|
+
end
|
|
1000
|
+
|
|
1001
|
+
# Declares a sub scope with possible +name+ and built from +ruby_block+.
|
|
1002
|
+
def sub(name = :"", &ruby_block)
|
|
1003
|
+
# Creates the new scope.
|
|
1004
|
+
scope = Scope.new(name,&ruby_block)
|
|
1005
|
+
# puts "new scope=#{scope}"
|
|
1006
|
+
# Add it
|
|
1007
|
+
self.add_scope(scope)
|
|
1008
|
+
# puts "self=#{self}"
|
|
1009
|
+
# puts "self scopes=#{self.each_scope.to_a.join(",")}"
|
|
1010
|
+
# Use its return value
|
|
1011
|
+
return scope.return_value
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
# Declares a high-level sequential behavior activated on a list of
|
|
1015
|
+
# +events+, and built by executing +ruby_block+.
|
|
1016
|
+
def seq(*events, &ruby_block)
|
|
1017
|
+
# Preprocess the events.
|
|
1018
|
+
events.map! do |event|
|
|
1019
|
+
event.respond_to?(:to_event) ? event.to_event : event
|
|
1020
|
+
end
|
|
1021
|
+
# Create and add the resulting behavior.
|
|
1022
|
+
self.add_behavior(Behavior.new(:seq,*events,&ruby_block))
|
|
1023
|
+
end
|
|
1024
|
+
|
|
1025
|
+
# Declares a high-level parallel behavior activated on a list of
|
|
1026
|
+
# +events+, and built by executing +ruby_block+.
|
|
1027
|
+
def par(*events, &ruby_block)
|
|
1028
|
+
# Preprocess the events.
|
|
1029
|
+
events.map! do |event|
|
|
1030
|
+
event.respond_to?(:to_event) ? event.to_event : event
|
|
1031
|
+
end
|
|
1032
|
+
# Create and add the resulting behavior.
|
|
1033
|
+
self.add_behavior(Behavior.new(:par,*events,&ruby_block))
|
|
1034
|
+
end
|
|
1035
|
+
|
|
1036
|
+
# Declares a high-level timed behavior built by executing +ruby_block+.
|
|
1037
|
+
# By default, timed behavior are sequential.
|
|
1038
|
+
def timed(&ruby_block)
|
|
1039
|
+
# Create and add the resulting behavior.
|
|
1040
|
+
self.add_behavior(TimeBehavior.new(:seq,&ruby_block))
|
|
1041
|
+
end
|
|
1042
|
+
|
|
1043
|
+
# Statements automatically enclosed in a behavior.
|
|
1044
|
+
|
|
1045
|
+
# Creates a new if statement with a +condition+ that when met lead
|
|
1046
|
+
# to the execution of the block in +mode+ generated by the +ruby_block+.
|
|
1047
|
+
#
|
|
1048
|
+
# NOTE:
|
|
1049
|
+
# * the else part is defined through the helse method.
|
|
1050
|
+
# * a behavior is created to enclose the hif.
|
|
1051
|
+
def hif(condition, mode = nil, &ruby_block)
|
|
1052
|
+
self.par do
|
|
1053
|
+
hif(condition,mode,&ruby_block)
|
|
1054
|
+
end
|
|
1055
|
+
end
|
|
1056
|
+
|
|
1057
|
+
# Sets the block executed when the condition is not met to the block
|
|
1058
|
+
# in +mode+ generated by the execution of +ruby_block+.
|
|
1059
|
+
#
|
|
1060
|
+
# Can only be used once.
|
|
1061
|
+
#
|
|
1062
|
+
# NOTE: added to the hif of the last behavior.
|
|
1063
|
+
def helse(mode = nil, &ruby_block)
|
|
1064
|
+
# There is a ruby_block: the helse is assumed to be with
|
|
1065
|
+
# the last statement of the last behavior.
|
|
1066
|
+
statement = self.last_behavior.last_statement
|
|
1067
|
+
# Completes the hif or the hcase statement.
|
|
1068
|
+
unless statement.is_a?(If) or statement.is_a?(Case) then
|
|
1069
|
+
raise AnyError, "Error: helse statement without hif nor hcase (#{statement.class})."
|
|
1070
|
+
end
|
|
1071
|
+
statement.helse(mode, &ruby_block)
|
|
1072
|
+
end
|
|
1073
|
+
|
|
1074
|
+
# Sets the condition check when the condition is not met to the block,
|
|
1075
|
+
# with a +condition+ that when met lead
|
|
1076
|
+
# to the execution of the block in +mode+ generated by the +ruby_block+.
|
|
1077
|
+
def helsif(condition, mode = nil, &ruby_block)
|
|
1078
|
+
# There is a ruby_block: the helse is assumed to be with
|
|
1079
|
+
# the last statement of the last behavior.
|
|
1080
|
+
statement = self.last_behavior.last_statement
|
|
1081
|
+
# Completes the hif statement.
|
|
1082
|
+
unless statement.is_a?(If) then
|
|
1083
|
+
raise AnyError, "Error: helsif statement without hif (#{statement.class})."
|
|
1084
|
+
end
|
|
1085
|
+
statement.helsif(condition, mode, &ruby_block)
|
|
1086
|
+
end
|
|
1087
|
+
|
|
1088
|
+
# Creates a new case statement with a +value+ used for deciding which
|
|
1089
|
+
# block to execute.
|
|
1090
|
+
#
|
|
1091
|
+
# NOTE:
|
|
1092
|
+
# * the when part is defined through the hwhen method.
|
|
1093
|
+
# * a new behavior is created to enclose the hcase.
|
|
1094
|
+
def hcase(value)
|
|
1095
|
+
self.par do
|
|
1096
|
+
hcase(value)
|
|
1097
|
+
end
|
|
1098
|
+
end
|
|
1099
|
+
|
|
1100
|
+
# Sets the block of a case structure executed when the +match+ is met
|
|
1101
|
+
# to the block in +mode+ generated by the execution of +ruby_block+.
|
|
1102
|
+
#
|
|
1103
|
+
# Can only be used once.
|
|
1104
|
+
def hwhen(match, mode = nil, &ruby_block)
|
|
1105
|
+
# There is a ruby_block: the helse is assumed to be with
|
|
1106
|
+
# the last statement of the last behavior.
|
|
1107
|
+
statement = @behaviors.last.last_statement
|
|
1108
|
+
# Completes the hcase statement.
|
|
1109
|
+
unless statement.is_a?(Case) then
|
|
1110
|
+
raise AnyError, "Error: hwhen statement without hcase (#{statement.class})."
|
|
1111
|
+
end
|
|
1112
|
+
statement.hwhen(match, mode, &ruby_block)
|
|
1113
|
+
end
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
# Sets the constructs corresponding to +names+ as exports.
|
|
1117
|
+
def export(*names)
|
|
1118
|
+
names.each {|name| self.add_export(name) }
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1121
|
+
# Include a +system+ type with possible +args+ instanciation
|
|
1122
|
+
# arguments.
|
|
1123
|
+
def include(system,*args)
|
|
1124
|
+
if @includes.key?(system.name) then
|
|
1125
|
+
raise AnyError, "Cannot include twice the same system."
|
|
1126
|
+
end
|
|
1127
|
+
# puts "Include system=#{system.name}"
|
|
1128
|
+
# Save the name of the included system, it will serve as key
|
|
1129
|
+
# for looking for the included expanded version.
|
|
1130
|
+
include_name = system.name
|
|
1131
|
+
# Expand the system to include
|
|
1132
|
+
system = system.expand(:"",*args)
|
|
1133
|
+
# Add the included system interface to the current one.
|
|
1134
|
+
if self.parent.is_a?(SystemT) then
|
|
1135
|
+
space = self.namespace
|
|
1136
|
+
# Interface signals
|
|
1137
|
+
# puts "i_name=#{i_name} @to_includes=#{@to_includes.size}"
|
|
1138
|
+
system.each_signal_with_included do |signal|
|
|
1139
|
+
# puts "signal=#{signal.name}"
|
|
1140
|
+
space.send(:define_singleton_method,signal.name) do
|
|
1141
|
+
signal
|
|
1142
|
+
end
|
|
1143
|
+
end
|
|
1144
|
+
# Exported objects
|
|
1145
|
+
system.each_export do |export|
|
|
1146
|
+
# puts "export=#{export.name}"
|
|
1147
|
+
space.send(:define_singleton_method,export.name) do
|
|
1148
|
+
export
|
|
1149
|
+
end
|
|
1150
|
+
end
|
|
1151
|
+
end
|
|
1152
|
+
# Adds it the list of includeds
|
|
1153
|
+
@includes[include_name] = system
|
|
1154
|
+
end
|
|
1155
|
+
|
|
1156
|
+
# Casts as an included +system+.
|
|
1157
|
+
def as(system)
|
|
1158
|
+
# puts "as with name: #{system.name}"
|
|
1159
|
+
system = system.name if system.respond_to?(:name)
|
|
1160
|
+
# puts "includes are: #{@includes.keys}"
|
|
1161
|
+
return @includes[system].namespace
|
|
1162
|
+
end
|
|
1163
|
+
|
|
1164
|
+
include Hmux
|
|
1165
|
+
|
|
1166
|
+
# Fills a low level scope with self's contents.
|
|
1167
|
+
#
|
|
1168
|
+
# NOTE: name conflicts are treated in the current NameStack state.
|
|
1169
|
+
def fill_low(scopeLow)
|
|
1170
|
+
# Adds the content of its included systems.
|
|
1171
|
+
@includes.each_value {|system| system.scope.fill_low(scopeLow) }
|
|
1172
|
+
# Adds the declared local system types.
|
|
1173
|
+
# NOTE: in the current version of HDLRuby::High, there should not
|
|
1174
|
+
# be any of them (only eigen systems are real system types).
|
|
1175
|
+
self.each_systemT { |systemT| scopeLow.add_systemT(systemT.to_low) }
|
|
1176
|
+
# Adds the local types.
|
|
1177
|
+
self.each_type { |type| scopeLow.add_type(type.to_low) }
|
|
1178
|
+
# Adds the inner scopes.
|
|
1179
|
+
self.each_scope { |scope| scopeLow.add_scope(scope.to_low) }
|
|
1180
|
+
# Adds the inner signals.
|
|
1181
|
+
self.each_inner { |inner| scopeLow.add_inner(inner.to_low) }
|
|
1182
|
+
# Adds the instances.
|
|
1183
|
+
# Single ones.
|
|
1184
|
+
self.each_systemI do |systemI|
|
|
1185
|
+
# puts "Filling with systemI=#{systemI.name}"
|
|
1186
|
+
systemI_low = scopeLow.add_systemI(systemI.to_low)
|
|
1187
|
+
# Also add the eigen system to the list of local systems.
|
|
1188
|
+
scopeLow.add_systemT(systemI_low.systemT)
|
|
1189
|
+
end
|
|
1190
|
+
# Grouped ones.
|
|
1191
|
+
self.each_groupI do |name,systemIs|
|
|
1192
|
+
systemIs.each.with_index { |systemI,i|
|
|
1193
|
+
# Sets the name of the system instance
|
|
1194
|
+
# (required for conversion of further accesses).
|
|
1195
|
+
# puts "systemI.respond_to?=#{systemI.respond_to?(:name=)}"
|
|
1196
|
+
systemI.name = name.to_s + "[#{i}]"
|
|
1197
|
+
# And convert it to low
|
|
1198
|
+
systemI_low = scopeLow.add_systemI(systemI.to_low())
|
|
1199
|
+
# Also add the eigen system to the list of local systems.
|
|
1200
|
+
scopeLow.add_systemT(systemI_low.systemT)
|
|
1201
|
+
}
|
|
1202
|
+
end
|
|
1203
|
+
# Adds the code chunks.
|
|
1204
|
+
self.each_code { |code| scopeLow.add_code(code.to_low) }
|
|
1205
|
+
# Adds the connections.
|
|
1206
|
+
self.each_connection { |connection|
|
|
1207
|
+
# puts "connection=#{connection}"
|
|
1208
|
+
scopeLow.add_connection(connection.to_low)
|
|
1209
|
+
}
|
|
1210
|
+
# Adds the behaviors.
|
|
1211
|
+
self.each_behavior { |behavior|
|
|
1212
|
+
scopeLow.add_behavior(behavior.to_low)
|
|
1213
|
+
}
|
|
1214
|
+
end
|
|
1215
|
+
|
|
1216
|
+
# Converts the scope to HDLRuby::Low.
|
|
1217
|
+
def to_low()
|
|
1218
|
+
# Create the resulting low scope.
|
|
1219
|
+
scopeLow = HDLRuby::Low::Scope.new()
|
|
1220
|
+
# Push the private namespace for the low generation.
|
|
1221
|
+
High.space_push(@namespace)
|
|
1222
|
+
# Pushes on the name stack for converting the internals of
|
|
1223
|
+
# the system.
|
|
1224
|
+
High.names_push
|
|
1225
|
+
# Adds the content of the actual system.
|
|
1226
|
+
self.fill_low(scopeLow)
|
|
1227
|
+
# Restores the name stack.
|
|
1228
|
+
High.names_pop
|
|
1229
|
+
# Restores the namespace stack.
|
|
1230
|
+
High.space_pop
|
|
1231
|
+
# Return theresulting system.
|
|
1232
|
+
return scopeLow
|
|
1233
|
+
end
|
|
1234
|
+
end
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
##
|
|
1238
|
+
# Module bringing high-level properties to Type classes.
|
|
1239
|
+
#
|
|
1240
|
+
# NOTE: by default a type is not specified.
|
|
1241
|
+
module Htype
|
|
1242
|
+
High = HDLRuby::High
|
|
1243
|
+
|
|
1244
|
+
# Type processing
|
|
1245
|
+
include HDLRuby::Tprocess
|
|
1246
|
+
|
|
1247
|
+
# Ensures initialize registers the type name
|
|
1248
|
+
def self.included(base) # built-in Ruby hook for modules
|
|
1249
|
+
base.class_eval do
|
|
1250
|
+
original_method = instance_method(:initialize)
|
|
1251
|
+
define_method(:initialize) do |*args, &block|
|
|
1252
|
+
original_method.bind(self).call(*args, &block)
|
|
1253
|
+
# Registers the name (if not empty).
|
|
1254
|
+
self.register(name) unless name.empty?
|
|
1255
|
+
end
|
|
1256
|
+
end
|
|
1257
|
+
end
|
|
1258
|
+
|
|
1259
|
+
# Tells htype has been included.
|
|
1260
|
+
def htype?
|
|
1261
|
+
return true
|
|
1262
|
+
end
|
|
1263
|
+
|
|
1264
|
+
# Sets the +name+.
|
|
1265
|
+
#
|
|
1266
|
+
# NOTE: can only be done if the name is not already set.
|
|
1267
|
+
def name=(name)
|
|
1268
|
+
unless @name.empty? then
|
|
1269
|
+
raise AnyError, "Name of type already set to: #{@name}."
|
|
1270
|
+
end
|
|
1271
|
+
# Checks and sets the name.
|
|
1272
|
+
name = name.to_sym
|
|
1273
|
+
if name.empty? then
|
|
1274
|
+
raise AnyError, "Cannot set an empty name."
|
|
1275
|
+
end
|
|
1276
|
+
@name = name
|
|
1277
|
+
# Registers the name.
|
|
1278
|
+
self.register(name)
|
|
1279
|
+
end
|
|
1280
|
+
|
|
1281
|
+
# Register the +name+ of the type.
|
|
1282
|
+
def register(name)
|
|
1283
|
+
if self.name.empty? then
|
|
1284
|
+
raise AnyError, "Cannot register with empty name."
|
|
1285
|
+
else
|
|
1286
|
+
# Sets the hdl-like access to the type.
|
|
1287
|
+
obj = self # For using the right self within the proc
|
|
1288
|
+
High.space_reg(name) { obj }
|
|
1289
|
+
end
|
|
1290
|
+
end
|
|
1291
|
+
|
|
1292
|
+
|
|
1293
|
+
# Gets the type as left value.
|
|
1294
|
+
#
|
|
1295
|
+
# NOTE: used for asymetric types like TypeSystemI.
|
|
1296
|
+
def left
|
|
1297
|
+
# By default self.
|
|
1298
|
+
self
|
|
1299
|
+
end
|
|
1300
|
+
|
|
1301
|
+
# Gets the type as right value.
|
|
1302
|
+
#
|
|
1303
|
+
# NOTE: used for asymetric types like TypeSystemI.
|
|
1304
|
+
def right
|
|
1305
|
+
# By default self.
|
|
1306
|
+
self
|
|
1307
|
+
end
|
|
1308
|
+
|
|
1309
|
+
# Type creation in HDLRuby::High.
|
|
1310
|
+
|
|
1311
|
+
# Declares a new type definition with +name+ equivalent to current one.
|
|
1312
|
+
def typedef(name)
|
|
1313
|
+
# Create the new type.
|
|
1314
|
+
typ = TypeDef.new(name,self)
|
|
1315
|
+
# Register it.
|
|
1316
|
+
High.space_reg(name) { typ }
|
|
1317
|
+
# Return it.
|
|
1318
|
+
return typ
|
|
1319
|
+
end
|
|
1320
|
+
|
|
1321
|
+
# Creates a new vector type of range +rng+ and with current type as
|
|
1322
|
+
# base.
|
|
1323
|
+
def [](rng)
|
|
1324
|
+
return TypeVector.new(:"",self,rng)
|
|
1325
|
+
end
|
|
1326
|
+
|
|
1327
|
+
# SignalI creation through the type.
|
|
1328
|
+
|
|
1329
|
+
# Declares high-level input signals named +names+ of the current type.
|
|
1330
|
+
def input(*names)
|
|
1331
|
+
High.top_user.make_inputs(self,*names)
|
|
1332
|
+
end
|
|
1333
|
+
|
|
1334
|
+
# Declares high-level untyped output signals named +names+ of the
|
|
1335
|
+
# current type.
|
|
1336
|
+
def output(*names)
|
|
1337
|
+
# High.top_user.make_outputs(self.instantiate,*names)
|
|
1338
|
+
High.top_user.make_outputs(self,*names)
|
|
1339
|
+
end
|
|
1340
|
+
|
|
1341
|
+
# Declares high-level untyped inout signals named +names+ of the
|
|
1342
|
+
# current type.
|
|
1343
|
+
def inout(*names)
|
|
1344
|
+
# High.top_user.make_inouts(self.instantiate,*names)
|
|
1345
|
+
High.top_user.make_inouts(self,*names)
|
|
1346
|
+
end
|
|
1347
|
+
|
|
1348
|
+
# Declares high-level untyped inner signals named +names+ of the
|
|
1349
|
+
# current type.
|
|
1350
|
+
def inner(*names)
|
|
1351
|
+
High.top_user.make_inners(self,*names)
|
|
1352
|
+
end
|
|
1353
|
+
|
|
1354
|
+
# Declares high-level untyped constant signals by name and
|
|
1355
|
+
# value given by +hsh+ of the current type.
|
|
1356
|
+
def constant(hsh)
|
|
1357
|
+
High.top_user.make_constants(self,hsh)
|
|
1358
|
+
end
|
|
1359
|
+
|
|
1360
|
+
# Computations of expressions
|
|
1361
|
+
|
|
1362
|
+
# Gets the computation method for +operator+.
|
|
1363
|
+
def comp_operator(op)
|
|
1364
|
+
return (op.to_s + ":C").to_sym
|
|
1365
|
+
end
|
|
1366
|
+
|
|
1367
|
+
# Performs unary operation +operator+ on expression +expr+.
|
|
1368
|
+
def unary(operator,expr)
|
|
1369
|
+
# Look for a specific computation method.
|
|
1370
|
+
comp = comp_operator(operator)
|
|
1371
|
+
if self.respond_to?(comp) then
|
|
1372
|
+
# Found, use it.
|
|
1373
|
+
self.send(comp,expr)
|
|
1374
|
+
else
|
|
1375
|
+
# Not found, back to default generation of unary expression.
|
|
1376
|
+
return Unary.new(self.send(operator),operator,expr)
|
|
1377
|
+
end
|
|
1378
|
+
end
|
|
1379
|
+
|
|
1380
|
+
# Performs binary operation +operator+ on expressions +expr0+
|
|
1381
|
+
# and +expr1+.
|
|
1382
|
+
def binary(operator, expr0, expr1)
|
|
1383
|
+
# Look for a specific computation method.
|
|
1384
|
+
comp = comp_operator(operator)
|
|
1385
|
+
if self.respond_to?(comp) then
|
|
1386
|
+
# Found, use it.
|
|
1387
|
+
self.send(comp,expr0,expr1)
|
|
1388
|
+
else
|
|
1389
|
+
# Not found, back to default generation of binary expression.
|
|
1390
|
+
return Binary.new(self.send(operator,expr1.type),operator,
|
|
1391
|
+
expr0,expr1)
|
|
1392
|
+
end
|
|
1393
|
+
end
|
|
1394
|
+
|
|
1395
|
+
# Redefinition of +operator+.
|
|
1396
|
+
def define_operator(operator,&ruby_block)
|
|
1397
|
+
# Register the operator as overloaded.
|
|
1398
|
+
@overloads ||= {}
|
|
1399
|
+
@overloads[operator] = ruby_block
|
|
1400
|
+
# Set the new method for the operator.
|
|
1401
|
+
self.define_singleton_method(comp_operator(operator)) do |*args|
|
|
1402
|
+
# puts "Top user=#{HDLRuby::High.top_user}"
|
|
1403
|
+
HDLRuby::High.top_user.instance_exec do
|
|
1404
|
+
sub do
|
|
1405
|
+
HDLRuby::High.top_user.instance_exec(*args,&ruby_block)
|
|
1406
|
+
end
|
|
1407
|
+
end
|
|
1408
|
+
end
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1411
|
+
# Interates over the overloaded operators.
|
|
1412
|
+
def each_overload(&ruby_block)
|
|
1413
|
+
# No ruby block? Return an enumerator.
|
|
1414
|
+
return to_enum(:each_overload) unless ruby_block
|
|
1415
|
+
# A block? Apply it on each overload if any.
|
|
1416
|
+
@overloads.each(&ruby_block) if @overloads
|
|
1417
|
+
end
|
|
1418
|
+
end
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
##
|
|
1422
|
+
# Describes a high-level data type.
|
|
1423
|
+
#
|
|
1424
|
+
# NOTE: by default a type is not specified.
|
|
1425
|
+
class Type < Low::Type
|
|
1426
|
+
High = HDLRuby::High
|
|
1427
|
+
|
|
1428
|
+
include Htype
|
|
1429
|
+
|
|
1430
|
+
# Type creation.
|
|
1431
|
+
|
|
1432
|
+
# Creates a new type named +name+.
|
|
1433
|
+
def initialize(name)
|
|
1434
|
+
# Initialize the type structure.
|
|
1435
|
+
super(name)
|
|
1436
|
+
end
|
|
1437
|
+
|
|
1438
|
+
# Converts the type to HDLRuby::Low and set its +name+.
|
|
1439
|
+
#
|
|
1440
|
+
# NOTE: should be overridden by other type classes.
|
|
1441
|
+
def to_low(name = self.name)
|
|
1442
|
+
return HDLRuby::Low::Type.new(name)
|
|
1443
|
+
end
|
|
1444
|
+
end
|
|
1445
|
+
|
|
1446
|
+
|
|
1447
|
+
# Creates the basic types.
|
|
1448
|
+
|
|
1449
|
+
# Module providing the properties of a basic type.
|
|
1450
|
+
# NOTE: requires method 'to_low' to be defined.
|
|
1451
|
+
module HbasicType
|
|
1452
|
+
# Get all the metods from Low::Bit appart from 'base'
|
|
1453
|
+
extend Forwardable
|
|
1454
|
+
def_delegators :to_low, :signed?, :unsigned?, :fixed?, :float?,
|
|
1455
|
+
:width, :range
|
|
1456
|
+
|
|
1457
|
+
# Get the base type, actually self for leaf types.
|
|
1458
|
+
def base
|
|
1459
|
+
self
|
|
1460
|
+
end
|
|
1461
|
+
|
|
1462
|
+
end
|
|
1463
|
+
|
|
1464
|
+
# Defines a basic type +name+.
|
|
1465
|
+
def self.define_type(name)
|
|
1466
|
+
name = name.to_sym
|
|
1467
|
+
type = Type.new(name)
|
|
1468
|
+
self.send(:define_method,name) { type }
|
|
1469
|
+
return type
|
|
1470
|
+
end
|
|
1471
|
+
|
|
1472
|
+
# The void type
|
|
1473
|
+
Void = define_type(:void)
|
|
1474
|
+
class << Void
|
|
1475
|
+
# Converts the type to HDLRuby::Low.
|
|
1476
|
+
def to_low
|
|
1477
|
+
return Low::Void
|
|
1478
|
+
end
|
|
1479
|
+
|
|
1480
|
+
include HbasicType
|
|
1481
|
+
end
|
|
1482
|
+
|
|
1483
|
+
# The bit type.
|
|
1484
|
+
Bit = define_type(:bit)
|
|
1485
|
+
class << Bit
|
|
1486
|
+
# Converts the type to HDLRuby::Low.
|
|
1487
|
+
def to_low
|
|
1488
|
+
return Low::Bit
|
|
1489
|
+
end
|
|
1490
|
+
|
|
1491
|
+
include HbasicType
|
|
1492
|
+
end
|
|
1493
|
+
|
|
1494
|
+
# The signed bit type.
|
|
1495
|
+
Signed = define_type(:signed)
|
|
1496
|
+
class << Signed
|
|
1497
|
+
# Converts the type to HDLRuby::Low.
|
|
1498
|
+
def to_low
|
|
1499
|
+
return Low::Signed
|
|
1500
|
+
end
|
|
1501
|
+
|
|
1502
|
+
include HbasicType
|
|
1503
|
+
end
|
|
1504
|
+
|
|
1505
|
+
# The unsigned bit type.
|
|
1506
|
+
Unsigned = define_type(:unsigned)
|
|
1507
|
+
class << Unsigned
|
|
1508
|
+
# Converts the type to HDLRuby::Low.
|
|
1509
|
+
def to_low
|
|
1510
|
+
return Low::Unsigned
|
|
1511
|
+
end
|
|
1512
|
+
|
|
1513
|
+
include HbasicType
|
|
1514
|
+
end
|
|
1515
|
+
|
|
1516
|
+
# The float bit type
|
|
1517
|
+
Float = define_type(:float)
|
|
1518
|
+
class << Float
|
|
1519
|
+
# Converts the type to HDLRuby::Low.
|
|
1520
|
+
def to_low
|
|
1521
|
+
return Low::Float
|
|
1522
|
+
end
|
|
1523
|
+
|
|
1524
|
+
include HbasicType
|
|
1525
|
+
end
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
|
|
1530
|
+
##
|
|
1531
|
+
# Describes a high-level type definition.
|
|
1532
|
+
#
|
|
1533
|
+
# NOTE: type definition are actually type with a name refering to another
|
|
1534
|
+
# type (and equivalent to it).
|
|
1535
|
+
class TypeDef < Low::TypeDef
|
|
1536
|
+
High = HDLRuby::High
|
|
1537
|
+
|
|
1538
|
+
include Htype
|
|
1539
|
+
|
|
1540
|
+
# Type creation.
|
|
1541
|
+
|
|
1542
|
+
# Creates a new type definition named +name+ refering +type+.
|
|
1543
|
+
def initialize(name,type)
|
|
1544
|
+
# Initialize the type structure.
|
|
1545
|
+
super(name,type)
|
|
1546
|
+
end
|
|
1547
|
+
|
|
1548
|
+
# Converts the type to HDLRuby::Low and set its +name+.
|
|
1549
|
+
#
|
|
1550
|
+
# NOTE: should be overridden by other type classes.
|
|
1551
|
+
def to_low(name = self.name)
|
|
1552
|
+
return HDLRuby::Low::TypeDef.new(name,self.def.to_low)
|
|
1553
|
+
end
|
|
1554
|
+
end
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
##
|
|
1558
|
+
# Describes a high-level generic type definition.
|
|
1559
|
+
#
|
|
1560
|
+
# NOTE: this type does not correspond to any low-level type
|
|
1561
|
+
class TypeGen< Type
|
|
1562
|
+
High = HDLRuby::High
|
|
1563
|
+
|
|
1564
|
+
# Type creation.
|
|
1565
|
+
|
|
1566
|
+
# Creates a new generic type definition producing a new type by
|
|
1567
|
+
# executing +ruby_block+.
|
|
1568
|
+
def initialize(name,&ruby_block)
|
|
1569
|
+
# Initialize the type structure.
|
|
1570
|
+
super(name)
|
|
1571
|
+
|
|
1572
|
+
# Sets the block to execute when instantiating the type.
|
|
1573
|
+
@instance_proc = ruby_block
|
|
1574
|
+
end
|
|
1575
|
+
|
|
1576
|
+
# Generates the type with +args+ generic parameters.
|
|
1577
|
+
def generate(*args)
|
|
1578
|
+
# Generate the resulting type.
|
|
1579
|
+
gtype = High.top_user.instance_exec(*args,&@instance_proc)
|
|
1580
|
+
# Ensures a type has been produced.
|
|
1581
|
+
gtype = gtype.to_type if gtype.respond_to?(:to_type)
|
|
1582
|
+
unless gtype.is_a?(HDLRuby::Low::Type) then
|
|
1583
|
+
raise AnyError, "Generic type #{self.name} did not produce a valid type: #{gtype.class}"
|
|
1584
|
+
end
|
|
1585
|
+
# Create a new type definition from it.
|
|
1586
|
+
gtype = TypeDef.new(self.name.to_s + "_#{args.join(":")}",
|
|
1587
|
+
gtype)
|
|
1588
|
+
# Adds the possible overloaded operators.
|
|
1589
|
+
self.each_overload do |op,ruby_block|
|
|
1590
|
+
gtype.define_operator(op,&(ruby_block.curry[*args]))
|
|
1591
|
+
end
|
|
1592
|
+
# Returns the resulting type
|
|
1593
|
+
return gtype
|
|
1594
|
+
end
|
|
1595
|
+
|
|
1596
|
+
# Converts the type to HDLRuby::Low and set its +name+.
|
|
1597
|
+
#
|
|
1598
|
+
# NOTE: should be overridden by other type classes.
|
|
1599
|
+
def to_low(name = self.name)
|
|
1600
|
+
return HDLRuby::Low::TypeDef.new(name,self.def.to_low)
|
|
1601
|
+
end
|
|
1602
|
+
end
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
# Methods for vector types.
|
|
1607
|
+
module HvectorType
|
|
1608
|
+
# Converts the type to HDLRuby::Low and set its +name+.
|
|
1609
|
+
def to_low(name = self.name)
|
|
1610
|
+
# Generate and return the new type.
|
|
1611
|
+
return HDLRuby::Low::TypeVector.new(name,self.base.to_low,
|
|
1612
|
+
self.range.to_low)
|
|
1613
|
+
end
|
|
1614
|
+
end
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
##
|
|
1618
|
+
# Describes a vector type.
|
|
1619
|
+
# class TypeVector < TypeExtend
|
|
1620
|
+
class TypeVector < Low::TypeVector
|
|
1621
|
+
High = HDLRuby::High
|
|
1622
|
+
include Htype
|
|
1623
|
+
include HvectorType
|
|
1624
|
+
end
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
##
|
|
1629
|
+
# Describes a signed integer data type.
|
|
1630
|
+
class TypeSigned < TypeVector
|
|
1631
|
+
|
|
1632
|
+
# Creates a new vector type named +name+ from +base+ type and with
|
|
1633
|
+
# +range+.
|
|
1634
|
+
#
|
|
1635
|
+
# NOTE:
|
|
1636
|
+
# * The default range is 32-bit.
|
|
1637
|
+
def initialize(name,range = 31..0)
|
|
1638
|
+
# Initialize the type.
|
|
1639
|
+
super(name,Signed,range)
|
|
1640
|
+
end
|
|
1641
|
+
end
|
|
1642
|
+
|
|
1643
|
+
##
|
|
1644
|
+
# Describes a unsigned integer data type.
|
|
1645
|
+
class TypeUnsigned < TypeVector
|
|
1646
|
+
|
|
1647
|
+
# Creates a new vector type named +name+ from +base+ type and with
|
|
1648
|
+
# +range+.
|
|
1649
|
+
#
|
|
1650
|
+
# NOTE:
|
|
1651
|
+
# * The default range is 32-bit.
|
|
1652
|
+
def initialize(name,range = 31..0)
|
|
1653
|
+
# Initialize the type.
|
|
1654
|
+
super(name,Unsigned,range)
|
|
1655
|
+
end
|
|
1656
|
+
end
|
|
1657
|
+
|
|
1658
|
+
##
|
|
1659
|
+
# Describes a float data type.
|
|
1660
|
+
class TypeFloat < TypeVector
|
|
1661
|
+
|
|
1662
|
+
# Creates a new vector type named +name+ from +base+ type and with
|
|
1663
|
+
# +range+.
|
|
1664
|
+
#
|
|
1665
|
+
# NOTE:
|
|
1666
|
+
# * The bits of negative range stands for the exponent
|
|
1667
|
+
# * The default range is for 64-bit IEEE 754 double precision standart
|
|
1668
|
+
def initialize(name,range = 52..-11)
|
|
1669
|
+
# Initialize the type.
|
|
1670
|
+
super(name,Float,range)
|
|
1671
|
+
end
|
|
1672
|
+
end
|
|
1673
|
+
|
|
1674
|
+
|
|
1675
|
+
##
|
|
1676
|
+
# Describes a tuple type.
|
|
1677
|
+
# class TypeTuple < Tuple
|
|
1678
|
+
class TypeTuple < Low::TypeTuple
|
|
1679
|
+
High = HDLRuby::High
|
|
1680
|
+
|
|
1681
|
+
include Htype
|
|
1682
|
+
|
|
1683
|
+
# Converts the type to HDLRuby::Low and set its +name+.
|
|
1684
|
+
def to_low(name = self.name)
|
|
1685
|
+
return HDLRuby::Low::TypeTuple.new(name,self.direction,
|
|
1686
|
+
*@types.map { |type| type.to_low } )
|
|
1687
|
+
end
|
|
1688
|
+
end
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
##
|
|
1692
|
+
# Describes a structure type.
|
|
1693
|
+
class TypeStruct < Low::TypeStruct
|
|
1694
|
+
High = HDLRuby::High
|
|
1695
|
+
|
|
1696
|
+
include Htype
|
|
1697
|
+
|
|
1698
|
+
# Converts the type to HDLRuby::Low and set its +name+.
|
|
1699
|
+
def to_low(name = self.name)
|
|
1700
|
+
return HDLRuby::Low::TypeStruct.new(name,self.direction,
|
|
1701
|
+
@types.map { |name,type| [name,type.to_low] } )
|
|
1702
|
+
end
|
|
1703
|
+
end
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
## Methods for declaring system types and functions.
|
|
1708
|
+
|
|
1709
|
+
# The type constructors.
|
|
1710
|
+
|
|
1711
|
+
# Creates an unnamed structure type from a +content+.
|
|
1712
|
+
def struct(content)
|
|
1713
|
+
return TypeStruct.new(:"",:little,content)
|
|
1714
|
+
end
|
|
1715
|
+
|
|
1716
|
+
# Methods for declaring types
|
|
1717
|
+
|
|
1718
|
+
# Declares a high-level generic type named +name+, and using +ruby_block+
|
|
1719
|
+
# for construction.
|
|
1720
|
+
def typedef(name, &ruby_block)
|
|
1721
|
+
type = TypeGen.new(name,&ruby_block)
|
|
1722
|
+
if HDLRuby::High.in_system? then
|
|
1723
|
+
# Must be inside a scope.
|
|
1724
|
+
unless HDLRuby::High.top_user.is_a?(Scope) then
|
|
1725
|
+
raise AnyError, "A local type cannot be declared within a #{HDLRuby::High.top_user.class}."
|
|
1726
|
+
end
|
|
1727
|
+
define_singleton_method(name.to_sym) do |*args|
|
|
1728
|
+
if (args.size < ruby_block.arity) then
|
|
1729
|
+
# Not enough arguments get generic type as is.
|
|
1730
|
+
type
|
|
1731
|
+
else
|
|
1732
|
+
# There are arguments, specialize the type.
|
|
1733
|
+
gtype = type.generate(*args)
|
|
1734
|
+
# And add it as a local type of the system.
|
|
1735
|
+
HDLRuby::High.top_user.add_type(gtype)
|
|
1736
|
+
end
|
|
1737
|
+
end
|
|
1738
|
+
else
|
|
1739
|
+
define_method(name.to_sym) do |*args|
|
|
1740
|
+
if (args.size < ruby_block.arity) then
|
|
1741
|
+
# Not enough arguments, get generic type as is.
|
|
1742
|
+
type
|
|
1743
|
+
else
|
|
1744
|
+
# There are arguments, specialize the type.
|
|
1745
|
+
type.generate(*args)
|
|
1746
|
+
end
|
|
1747
|
+
end
|
|
1748
|
+
end
|
|
1749
|
+
end
|
|
1750
|
+
|
|
1751
|
+
# Methods for declaring systems
|
|
1752
|
+
|
|
1753
|
+
# Declares a high-level system type named +name+, with +includes+ mixins
|
|
1754
|
+
# system types and using +ruby_block+ for instantiating.
|
|
1755
|
+
def system(name = :"", *includes, &ruby_block)
|
|
1756
|
+
# print "system ruby_block=#{ruby_block}\n"
|
|
1757
|
+
# Creates the resulting system.
|
|
1758
|
+
return SystemT.new(name,*includes,&ruby_block)
|
|
1759
|
+
end
|
|
1760
|
+
|
|
1761
|
+
# Declares a high-level system instance named +name+, with +includes+
|
|
1762
|
+
# mixins system types and using +ruby_block+ for instantiating.
|
|
1763
|
+
#
|
|
1764
|
+
# NOTE: this is for generating directly an instance without declaring
|
|
1765
|
+
# it system type.
|
|
1766
|
+
def instance(name, *includes, &ruby_block)
|
|
1767
|
+
# Creates the system type.
|
|
1768
|
+
systemT = system(:"",*includes,&ruby_block)
|
|
1769
|
+
# Instantiate it with +name+.
|
|
1770
|
+
return systemT.instantiate(name)
|
|
1771
|
+
end
|
|
1772
|
+
|
|
1773
|
+
# Methods for declaring functions
|
|
1774
|
+
|
|
1775
|
+
# Declares a function named +name+ using +ruby_block+ as body.
|
|
1776
|
+
#
|
|
1777
|
+
# NOTE: a function is a short-cut for a method that creates a scope.
|
|
1778
|
+
def function(name, &ruby_block)
|
|
1779
|
+
if HDLRuby::High.in_system? then
|
|
1780
|
+
define_singleton_method(name.to_sym) do |*args|
|
|
1781
|
+
sub do
|
|
1782
|
+
HDLRuby::High.top_user.instance_exec(*args,&ruby_block)
|
|
1783
|
+
# ruby_block.call(*args)
|
|
1784
|
+
end
|
|
1785
|
+
end
|
|
1786
|
+
else
|
|
1787
|
+
define_method(name.to_sym) do |*args|
|
|
1788
|
+
sub do
|
|
1789
|
+
HDLRuby::High.top_user.instance_exec(*args,&ruby_block)
|
|
1790
|
+
end
|
|
1791
|
+
end
|
|
1792
|
+
end
|
|
1793
|
+
end
|
|
1794
|
+
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
|
|
1798
|
+
# Classes describing harware instances.
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
##
|
|
1802
|
+
# Describes a high-level system instance.
|
|
1803
|
+
class SystemI < Low::SystemI
|
|
1804
|
+
High = HDLRuby::High
|
|
1805
|
+
|
|
1806
|
+
include SingletonExtend
|
|
1807
|
+
|
|
1808
|
+
# Creates a new system instance of system type +systemT+ named +name+.
|
|
1809
|
+
def initialize(name, systemT)
|
|
1810
|
+
# Initialize the system instance structure.
|
|
1811
|
+
super(name,systemT)
|
|
1812
|
+
|
|
1813
|
+
# Sets the hdl-like access to the system instance.
|
|
1814
|
+
obj = self # For using the right self within the proc
|
|
1815
|
+
High.space_reg(name) { obj }
|
|
1816
|
+
end
|
|
1817
|
+
|
|
1818
|
+
# The type of a systemI: for now Void (may change in the future).
|
|
1819
|
+
def type
|
|
1820
|
+
return void
|
|
1821
|
+
end
|
|
1822
|
+
|
|
1823
|
+
# Converts to a new reference.
|
|
1824
|
+
def to_ref
|
|
1825
|
+
if self.name.empty? then
|
|
1826
|
+
# No name, happens if inside the systemI so use this.
|
|
1827
|
+
return this
|
|
1828
|
+
else
|
|
1829
|
+
# A name.
|
|
1830
|
+
return RefObject.new(this,self)
|
|
1831
|
+
end
|
|
1832
|
+
end
|
|
1833
|
+
|
|
1834
|
+
# Connects signals of the system instance according to +connects+.
|
|
1835
|
+
#
|
|
1836
|
+
# NOTE: +connects+ can be a hash table where each entry gives the
|
|
1837
|
+
# correspondance between a system's signal name and an external
|
|
1838
|
+
# signal to connect to, or a list of signals that will be connected
|
|
1839
|
+
# in the order of declaration.
|
|
1840
|
+
def call(*connects)
|
|
1841
|
+
# Checks if it is a connection through is a hash.
|
|
1842
|
+
if connects.size == 1 and connects[0].respond_to?(:to_h) then
|
|
1843
|
+
# Yes, perform a connection by name
|
|
1844
|
+
connects = connects[0].to_h
|
|
1845
|
+
# Performs the connections.
|
|
1846
|
+
connects.each do |key,value|
|
|
1847
|
+
# Gets the signal corresponding to connect.
|
|
1848
|
+
signal = self.get_signal(key)
|
|
1849
|
+
# Check if it is an output.
|
|
1850
|
+
isout = self.get_output(key)
|
|
1851
|
+
# Convert it to a reference.
|
|
1852
|
+
ref = RefObject.new(self.to_ref,signal)
|
|
1853
|
+
# Make the connection.
|
|
1854
|
+
if isout then
|
|
1855
|
+
value <= ref
|
|
1856
|
+
else
|
|
1857
|
+
ref <= value
|
|
1858
|
+
end
|
|
1859
|
+
end
|
|
1860
|
+
else
|
|
1861
|
+
# No, perform a connection is order of declaration
|
|
1862
|
+
connects.each.with_index do |csig,i|
|
|
1863
|
+
# puts "csig=#{csig} i=#{i}"
|
|
1864
|
+
# puts "systemT inputs=#{systemT.each_input.to_a.size}"
|
|
1865
|
+
# Gets i-est signal to connect
|
|
1866
|
+
ssig = self.systemT.get_interface_with_included(i)
|
|
1867
|
+
# Check if it is an output.
|
|
1868
|
+
isout = self.get_output(ssig.name)
|
|
1869
|
+
# Convert it to a reference.
|
|
1870
|
+
ssig = RefObject.new(self.to_ref,ssig)
|
|
1871
|
+
# Make the connection.
|
|
1872
|
+
if isout then
|
|
1873
|
+
csig <= ssig
|
|
1874
|
+
else
|
|
1875
|
+
ssig <= csig
|
|
1876
|
+
end
|
|
1877
|
+
end
|
|
1878
|
+
end
|
|
1879
|
+
end
|
|
1880
|
+
|
|
1881
|
+
# Gets an exported element (signal or system instance) by +name+.
|
|
1882
|
+
def get_export(name)
|
|
1883
|
+
return @systemT.get_export(name)
|
|
1884
|
+
end
|
|
1885
|
+
|
|
1886
|
+
|
|
1887
|
+
# Opens for extension.
|
|
1888
|
+
#
|
|
1889
|
+
# NOTE: actually executes +ruby_block+ in the context of the
|
|
1890
|
+
# systemT.
|
|
1891
|
+
def open(&ruby_block)
|
|
1892
|
+
# Extend the eigen system.
|
|
1893
|
+
@systemT.run(&ruby_block)
|
|
1894
|
+
# Update the methods.
|
|
1895
|
+
@systemT.eigenize(self)
|
|
1896
|
+
self.eigen_extend(@systemT.public_namespace)
|
|
1897
|
+
end
|
|
1898
|
+
|
|
1899
|
+
# include Hmissing
|
|
1900
|
+
|
|
1901
|
+
# Missing methods are looked for in the public namespace of the
|
|
1902
|
+
# system type.
|
|
1903
|
+
def method_missing(m, *args, &ruby_block)
|
|
1904
|
+
# print "method_missing in class=#{self.class} with m=#{m}\n"
|
|
1905
|
+
self.public_namespace.send(m,*args,&ruby_block)
|
|
1906
|
+
end
|
|
1907
|
+
|
|
1908
|
+
|
|
1909
|
+
# Methods to transmit to the systemT
|
|
1910
|
+
|
|
1911
|
+
# Gets the public namespace.
|
|
1912
|
+
def public_namespace
|
|
1913
|
+
self.systemT.public_namespace
|
|
1914
|
+
end
|
|
1915
|
+
|
|
1916
|
+
# Gets the private namespace.
|
|
1917
|
+
def namespace
|
|
1918
|
+
# self.systemT.scope.namespace
|
|
1919
|
+
self.systemT.namespace
|
|
1920
|
+
end
|
|
1921
|
+
|
|
1922
|
+
|
|
1923
|
+
# Converts the instance to HDLRuby::Low and set its +name+.
|
|
1924
|
+
def to_low(name = self.name)
|
|
1925
|
+
# puts "to_low with #{self} (#{self.name}) #{self.systemT}"
|
|
1926
|
+
# Converts the system of the instance to HDLRuby::Low
|
|
1927
|
+
systemTlow = self.systemT.to_low
|
|
1928
|
+
# Creates the resulting HDLRuby::Low instance
|
|
1929
|
+
systemIlow = HDLRuby::Low::SystemI.new(High.names_create(name),
|
|
1930
|
+
systemTlow)
|
|
1931
|
+
# Adds the other systemTs.
|
|
1932
|
+
self.each_systemT do |systemT|
|
|
1933
|
+
systemIlow.add_systemT(systemT.to_low) unless systemT == self.systemT
|
|
1934
|
+
end
|
|
1935
|
+
return systemIlow
|
|
1936
|
+
end
|
|
1937
|
+
end
|
|
1938
|
+
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
##
|
|
1942
|
+
# Describes a non-HDLRuby code chunk.
|
|
1943
|
+
class Chunk < HDLRuby::Low::Chunk
|
|
1944
|
+
# Converts the if to HDLRuby::Low.
|
|
1945
|
+
def to_low
|
|
1946
|
+
return HDLRuby::Low::Chunk.new(self.name,
|
|
1947
|
+
*self.each_lump.map do |lump|
|
|
1948
|
+
lump = lump.respond_to?(:to_low) ? lump.to_low : lump.to_s
|
|
1949
|
+
lump
|
|
1950
|
+
end)
|
|
1951
|
+
end
|
|
1952
|
+
end
|
|
1953
|
+
|
|
1954
|
+
##
|
|
1955
|
+
# Decribes a set of non-HDLRuby code chunks.
|
|
1956
|
+
class Code < HDLRuby::Low::Code
|
|
1957
|
+
# Converts the if to HDLRuby::Low.
|
|
1958
|
+
def to_low
|
|
1959
|
+
# Create the resulting code.
|
|
1960
|
+
res = HDLRuby::Low::Code.new
|
|
1961
|
+
# Add the low-level events.
|
|
1962
|
+
self.each_event { |event| res.add_event(event.to_low) }
|
|
1963
|
+
# Add the low-level code chunks.
|
|
1964
|
+
self.each_chunk { |chunk| res.add_chunk(chunk.to_low) }
|
|
1965
|
+
# Return the resulting code.
|
|
1966
|
+
return res
|
|
1967
|
+
end
|
|
1968
|
+
end
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
# Class describing namespace in system.
|
|
1972
|
+
|
|
1973
|
+
|
|
1974
|
+
|
|
1975
|
+
# Classes describing hardware statements, connections and expressions
|
|
1976
|
+
|
|
1977
|
+
|
|
1978
|
+
##
|
|
1979
|
+
# Module giving high-level statement properties
|
|
1980
|
+
module HStatement
|
|
1981
|
+
# Creates a new if statement with a +condition+ enclosing the statement.
|
|
1982
|
+
#
|
|
1983
|
+
# NOTE: the else part is defined through the helse method.
|
|
1984
|
+
def hif(condition)
|
|
1985
|
+
# Creates the if statement.
|
|
1986
|
+
return If.new(condition) { self }
|
|
1987
|
+
end
|
|
1988
|
+
end
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
##
|
|
1992
|
+
# Describes a high-level if statement.
|
|
1993
|
+
class If < Low::If
|
|
1994
|
+
High = HDLRuby::High
|
|
1995
|
+
|
|
1996
|
+
include HStatement
|
|
1997
|
+
|
|
1998
|
+
# Creates a new if statement with a +condition+ that when met lead
|
|
1999
|
+
# to the execution of the block in +mode+ generated by the execution of
|
|
2000
|
+
# +ruby_block+.
|
|
2001
|
+
def initialize(condition, mode = nil, &ruby_block)
|
|
2002
|
+
# Create the yes block.
|
|
2003
|
+
yes_block = High.make_block(mode,&ruby_block)
|
|
2004
|
+
# Creates the if statement.
|
|
2005
|
+
super(condition.to_expr,yes_block)
|
|
2006
|
+
end
|
|
2007
|
+
|
|
2008
|
+
# Sets the block executed in +mode+ when the condition is not met to
|
|
2009
|
+
# the block generated by the execution of +ruby_block+.
|
|
2010
|
+
#
|
|
2011
|
+
# Can only be used once.
|
|
2012
|
+
def helse(mode = nil, &ruby_block)
|
|
2013
|
+
# If there is a no block, it is an error.
|
|
2014
|
+
raise AnyError, "Cannot have two helse for a single if statement." if self.no
|
|
2015
|
+
# Create the no block if required
|
|
2016
|
+
no_block = High.make_block(mode,&ruby_block)
|
|
2017
|
+
# Sets the no block.
|
|
2018
|
+
self.no = no_block
|
|
2019
|
+
end
|
|
2020
|
+
|
|
2021
|
+
# Sets the block executed in +mode+ when the condition is not met
|
|
2022
|
+
# but +next_cond+ is met to the block generated by the execution of
|
|
2023
|
+
# +ruby_block+.
|
|
2024
|
+
#
|
|
2025
|
+
# Can only be used if the no-block is not set yet.
|
|
2026
|
+
def helsif(next_cond, mode = nil, &ruby_block)
|
|
2027
|
+
# If there is a no block, it is an error.
|
|
2028
|
+
raise AnyError, "Cannot have an helsif after an helse." if self.no
|
|
2029
|
+
# Create the noif block if required
|
|
2030
|
+
noif_block = High.make_block(mode,&ruby_block)
|
|
2031
|
+
# Adds the noif block.
|
|
2032
|
+
self.add_noif(next_cond.to_expr,noif_block)
|
|
2033
|
+
end
|
|
2034
|
+
|
|
2035
|
+
# Converts the if to HDLRuby::Low.
|
|
2036
|
+
def to_low
|
|
2037
|
+
# no may be nil, so treat it appart
|
|
2038
|
+
noL = self.no ? self.no.to_low : nil
|
|
2039
|
+
# Now generate the low-level if.
|
|
2040
|
+
low = HDLRuby::Low::If.new(self.condition.to_low,
|
|
2041
|
+
self.yes.to_low,noL)
|
|
2042
|
+
self.each_noif {|cond,block| low.add_noif(cond.to_low,block.to_low)}
|
|
2043
|
+
return low
|
|
2044
|
+
end
|
|
2045
|
+
end
|
|
2046
|
+
|
|
2047
|
+
|
|
2048
|
+
##
|
|
2049
|
+
# Describes a high-level when for a case statement.
|
|
2050
|
+
class When < Low::When
|
|
2051
|
+
High = HDLRuby::High
|
|
2052
|
+
|
|
2053
|
+
# Creates a new when for a casde statement that executes +statement+
|
|
2054
|
+
# on +match+.
|
|
2055
|
+
def initialize(match,statement)
|
|
2056
|
+
super(match,statement)
|
|
2057
|
+
end
|
|
2058
|
+
|
|
2059
|
+
# Converts the if to HDLRuby::Low.
|
|
2060
|
+
def to_low
|
|
2061
|
+
return HDLRuby::Low::When.new(self.match.to_low,
|
|
2062
|
+
self.statement.to_low)
|
|
2063
|
+
end
|
|
2064
|
+
end
|
|
2065
|
+
|
|
2066
|
+
|
|
2067
|
+
##
|
|
2068
|
+
# Describes a high-level case statement.
|
|
2069
|
+
class Case < Low::Case
|
|
2070
|
+
High = HDLRuby::High
|
|
2071
|
+
|
|
2072
|
+
include HStatement
|
|
2073
|
+
|
|
2074
|
+
# Creates a new case statement with a +value+ that decides which
|
|
2075
|
+
# block to execute.
|
|
2076
|
+
def initialize(value)
|
|
2077
|
+
# Create the yes block.
|
|
2078
|
+
super(value.to_expr)
|
|
2079
|
+
end
|
|
2080
|
+
|
|
2081
|
+
# Sets the block executed in +mode+ when the value matches +match+.
|
|
2082
|
+
# The block is generated by the execution of +ruby_block+.
|
|
2083
|
+
#
|
|
2084
|
+
# Can only be used once for the given +match+.
|
|
2085
|
+
def hwhen(match, mode = nil, &ruby_block)
|
|
2086
|
+
# Create the nu block if required
|
|
2087
|
+
when_block = High.make_block(mode,&ruby_block)
|
|
2088
|
+
# Adds the case.
|
|
2089
|
+
self.add_when(When.new(match.to_expr,when_block))
|
|
2090
|
+
end
|
|
2091
|
+
|
|
2092
|
+
# Sets the block executed in +mode+ when there were no match to
|
|
2093
|
+
# the block generated by the execution of +ruby_block+.
|
|
2094
|
+
#
|
|
2095
|
+
# Can only be used once.
|
|
2096
|
+
def helse(mode = nil, &ruby_block)
|
|
2097
|
+
# Create the nu block if required
|
|
2098
|
+
default_block = High.make_block(mode,&ruby_block)
|
|
2099
|
+
# Sets the default block.
|
|
2100
|
+
self.default = default_block
|
|
2101
|
+
end
|
|
2102
|
+
|
|
2103
|
+
# Converts the case to HDLRuby::Low.
|
|
2104
|
+
def to_low
|
|
2105
|
+
# Create the low level case.
|
|
2106
|
+
caseL = HDLRuby::Low::Case.new(@value.to_low)
|
|
2107
|
+
# Add each when case.
|
|
2108
|
+
self.each_when do |w|
|
|
2109
|
+
caseL.add_when(w.to_low)
|
|
2110
|
+
end
|
|
2111
|
+
# Add the default if any.
|
|
2112
|
+
if self.default then
|
|
2113
|
+
caseL.default = self.default.to_low
|
|
2114
|
+
end
|
|
2115
|
+
return caseL
|
|
2116
|
+
end
|
|
2117
|
+
end
|
|
2118
|
+
|
|
2119
|
+
|
|
2120
|
+
##
|
|
2121
|
+
# Describes a delay: not synthesizable.
|
|
2122
|
+
class Delay < Low::Delay
|
|
2123
|
+
High = HDLRuby::High
|
|
2124
|
+
|
|
2125
|
+
include HStatement
|
|
2126
|
+
|
|
2127
|
+
def !
|
|
2128
|
+
High.top_user.wait(self)
|
|
2129
|
+
end
|
|
2130
|
+
|
|
2131
|
+
# Converts the delay to HDLRuby::Low.
|
|
2132
|
+
def to_low
|
|
2133
|
+
return HDLRuby::Low::Delay.new(self.value, self.unit)
|
|
2134
|
+
end
|
|
2135
|
+
end
|
|
2136
|
+
|
|
2137
|
+
##
|
|
2138
|
+
# Describes a high-level wait delay statement.
|
|
2139
|
+
class TimeWait < Low::TimeWait
|
|
2140
|
+
include HStatement
|
|
2141
|
+
|
|
2142
|
+
# Converts the wait statement to HDLRuby::Low.
|
|
2143
|
+
def to_low
|
|
2144
|
+
return HDLRuby::Low::TimeWait.new(self.delay.to_low)
|
|
2145
|
+
end
|
|
2146
|
+
end
|
|
2147
|
+
|
|
2148
|
+
|
|
2149
|
+
##
|
|
2150
|
+
# Describes a timed loop statement: not synthesizable!
|
|
2151
|
+
class TimeRepeat < Low::TimeRepeat
|
|
2152
|
+
include HStatement
|
|
2153
|
+
|
|
2154
|
+
# Converts the repeat statement to HDLRuby::Low.
|
|
2155
|
+
def to_low
|
|
2156
|
+
return HDLRuby::Low::TimeRepeat.new(self.statement.to_low,
|
|
2157
|
+
self.delay.to_low)
|
|
2158
|
+
end
|
|
2159
|
+
end
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
##
|
|
2163
|
+
# Module giving high-level expression properties
|
|
2164
|
+
module HExpression
|
|
2165
|
+
# The system type the expression has been resolved in, if any.
|
|
2166
|
+
attr_reader :systemT
|
|
2167
|
+
# The type of the expression if resolved.
|
|
2168
|
+
attr_reader :type
|
|
2169
|
+
|
|
2170
|
+
# Tell if the expression can be converted to a value.
|
|
2171
|
+
def to_value?
|
|
2172
|
+
return false
|
|
2173
|
+
end
|
|
2174
|
+
|
|
2175
|
+
# Converts to a new value.
|
|
2176
|
+
#
|
|
2177
|
+
# NOTE: to be redefined.
|
|
2178
|
+
def to_value
|
|
2179
|
+
raise AnyError,
|
|
2180
|
+
"Expression cannot be converted to a value: #{self.class}"
|
|
2181
|
+
end
|
|
2182
|
+
|
|
2183
|
+
# Tell if the expression is constant.
|
|
2184
|
+
def constant?
|
|
2185
|
+
# By default not constant.
|
|
2186
|
+
return false unless self.each_node.any?
|
|
2187
|
+
# If any sub node, check if all of them are constants.
|
|
2188
|
+
self.each_node { |node| return false unless node.constant? }
|
|
2189
|
+
return true
|
|
2190
|
+
end
|
|
2191
|
+
|
|
2192
|
+
|
|
2193
|
+
# Converts to a new expression.
|
|
2194
|
+
#
|
|
2195
|
+
# NOTE: to be redefined in case of non-expression class.
|
|
2196
|
+
def to_expr
|
|
2197
|
+
raise AnyError, "Internal error: to_expr not defined yet for class: #{self.class}"
|
|
2198
|
+
end
|
|
2199
|
+
|
|
2200
|
+
# # Converts to a new ref.
|
|
2201
|
+
# def to_ref
|
|
2202
|
+
# return RefObject.new(this,self)
|
|
2203
|
+
# end
|
|
2204
|
+
|
|
2205
|
+
# Casts as +type+.
|
|
2206
|
+
def as(type)
|
|
2207
|
+
return Cast.new(type.to_type,self.to_expr)
|
|
2208
|
+
end
|
|
2209
|
+
|
|
2210
|
+
# Gets the origin method for operation +op+.
|
|
2211
|
+
def self.orig_operator(op)
|
|
2212
|
+
return (op.to_s + "_orig").to_sym
|
|
2213
|
+
end
|
|
2214
|
+
def orig_operator(op)
|
|
2215
|
+
HExpression.orig_operator(op)
|
|
2216
|
+
end
|
|
2217
|
+
|
|
2218
|
+
# Adds the unary operations generation.
|
|
2219
|
+
[:"-@",:"@+",:"~", :abs,
|
|
2220
|
+
:boolean, :bit, :signed, :unsigned].each do |operator|
|
|
2221
|
+
meth = proc do
|
|
2222
|
+
expr = self.to_expr
|
|
2223
|
+
return expr.type.unary(operator,expr)
|
|
2224
|
+
end
|
|
2225
|
+
# Defines the operator method.
|
|
2226
|
+
define_method(operator,&meth)
|
|
2227
|
+
# And save it so that it can still be accessed if overidden.
|
|
2228
|
+
define_method(orig_operator(operator),&meth)
|
|
2229
|
+
end
|
|
2230
|
+
|
|
2231
|
+
# Coerce by forcing convertion of obj to expression.
|
|
2232
|
+
def coerce(obj)
|
|
2233
|
+
if obj.is_a?(HDLRuby::Low::Expression) then
|
|
2234
|
+
# Already an expression, nothing to do.
|
|
2235
|
+
return [obj,self]
|
|
2236
|
+
elsif obj.respond_to?(:to_expr) then
|
|
2237
|
+
# Can be converted to an expression, do it.
|
|
2238
|
+
return [obj.to_expr, self]
|
|
2239
|
+
else
|
|
2240
|
+
return [obj,self]
|
|
2241
|
+
end
|
|
2242
|
+
end
|
|
2243
|
+
|
|
2244
|
+
# Adds the binary operations generation.
|
|
2245
|
+
[:"+",:"-",:"*",:"/",:"%",:"**",
|
|
2246
|
+
:"&",:"|",:"^",
|
|
2247
|
+
:"<<",:">>",:ls,:rs,:lr,:rr,
|
|
2248
|
+
:"==",:"!=",:"<",:">",:"<=",:">="].each do |operator|
|
|
2249
|
+
meth = proc do |right|
|
|
2250
|
+
expr = self.to_expr
|
|
2251
|
+
return expr.type.binary(operator,expr,right.to_expr)
|
|
2252
|
+
end
|
|
2253
|
+
# Defines the operator method.
|
|
2254
|
+
define_method(operator,&meth)
|
|
2255
|
+
# And save it so that it can still be accessed if overidden.
|
|
2256
|
+
define_method(orig_operator(operator),&meth)
|
|
2257
|
+
end
|
|
2258
|
+
|
|
2259
|
+
# Creates an access to elements of range +rng+ of the signal.
|
|
2260
|
+
#
|
|
2261
|
+
# NOTE: +rng+ can be a single expression in which case it is an index.
|
|
2262
|
+
def [](rng)
|
|
2263
|
+
if rng.respond_to?(:to_expr) then
|
|
2264
|
+
# Number range: convert it to an expression.
|
|
2265
|
+
rng = rng.to_expr
|
|
2266
|
+
end
|
|
2267
|
+
if rng.is_a?(HDLRuby::Low::Expression) then
|
|
2268
|
+
# Index case
|
|
2269
|
+
return RefIndex.new(self.type.base,self.to_expr,rng)
|
|
2270
|
+
else
|
|
2271
|
+
# Range case, ensure it is made among expression.
|
|
2272
|
+
first = rng.first.to_expr
|
|
2273
|
+
last = rng.last.to_expr
|
|
2274
|
+
# Abd create the reference.
|
|
2275
|
+
return RefRange.new(self.type.slice(first..last),
|
|
2276
|
+
self.to_expr,first..last)
|
|
2277
|
+
end
|
|
2278
|
+
end
|
|
2279
|
+
|
|
2280
|
+
|
|
2281
|
+
# Converts to a select operator using current expression as
|
|
2282
|
+
# condition for one of the +choices+.
|
|
2283
|
+
#
|
|
2284
|
+
# NOTE: +choices+ can either be a list of arguments or an array.
|
|
2285
|
+
# If +choices+ has only two entries
|
|
2286
|
+
# (and it is not a hash), +value+ will be converted to a boolean.
|
|
2287
|
+
def mux(*choices)
|
|
2288
|
+
# Process the choices.
|
|
2289
|
+
choices = choices.flatten(1) if choices.size == 1
|
|
2290
|
+
choices.map! { |choice| choice.to_expr }
|
|
2291
|
+
# Generate the select expression.
|
|
2292
|
+
return Select.new(choices[0].type,"?",self.to_expr,*choices)
|
|
2293
|
+
end
|
|
2294
|
+
|
|
2295
|
+
|
|
2296
|
+
# Methods for conversion for HDLRuby::Low: type processing, flattening
|
|
2297
|
+
# and so on
|
|
2298
|
+
|
|
2299
|
+
# The type of the expression if any.
|
|
2300
|
+
attr_reader :type
|
|
2301
|
+
|
|
2302
|
+
# Sets the data +type+.
|
|
2303
|
+
def type=(type)
|
|
2304
|
+
# Check and set the type.
|
|
2305
|
+
unless type.respond_to?(:htype?) then
|
|
2306
|
+
raise AnyError, "Invalid class for a type: #{type.class}."
|
|
2307
|
+
end
|
|
2308
|
+
@type = type
|
|
2309
|
+
end
|
|
2310
|
+
# Converts to a select operator using current expression as
|
|
2311
|
+
# condition for one of the +choices+.
|
|
2312
|
+
#
|
|
2313
|
+
# NOTE: +choices+ can either be a list of arguments or an array.
|
|
2314
|
+
# If +choices+ has only two entries
|
|
2315
|
+
# (and it is not a hash), +value+ will be converted to a boolean.
|
|
2316
|
+
def mux(*choices)
|
|
2317
|
+
# Process the choices.
|
|
2318
|
+
choices = choices.flatten(1) if choices.size == 1
|
|
2319
|
+
choices.map! { |choice| choice.to_expr }
|
|
2320
|
+
# Generate the select expression.
|
|
2321
|
+
return Select.new(choices[0].type,"?",self.to_expr,*choices)
|
|
2322
|
+
end
|
|
2323
|
+
|
|
2324
|
+
end
|
|
2325
|
+
|
|
2326
|
+
|
|
2327
|
+
##
|
|
2328
|
+
# Module giving high-level properties for handling the arrow (<=) operator.
|
|
2329
|
+
module HArrow
|
|
2330
|
+
High = HDLRuby::High
|
|
2331
|
+
|
|
2332
|
+
# Creates a transmit, or connection with an +expr+.
|
|
2333
|
+
#
|
|
2334
|
+
# NOTE: it is converted afterward to an expression if required.
|
|
2335
|
+
def <=(expr)
|
|
2336
|
+
if High.top_user.is_a?(HDLRuby::Low::Block) then
|
|
2337
|
+
# We are in a block, so generate and add a Transmit.
|
|
2338
|
+
High.top_user.
|
|
2339
|
+
add_statement(Transmit.new(self.to_ref,expr.to_expr))
|
|
2340
|
+
else
|
|
2341
|
+
# We are in a system type, so generate and add a Connection.
|
|
2342
|
+
High.top_user.
|
|
2343
|
+
add_connection(Connection.new(self.to_ref,expr.to_expr))
|
|
2344
|
+
end
|
|
2345
|
+
end
|
|
2346
|
+
end
|
|
2347
|
+
|
|
2348
|
+
|
|
2349
|
+
##
|
|
2350
|
+
# Describes a high-level cast expression
|
|
2351
|
+
class Cast < Low::Cast
|
|
2352
|
+
include HExpression
|
|
2353
|
+
|
|
2354
|
+
# Converts to a new expression.
|
|
2355
|
+
def to_expr
|
|
2356
|
+
return Cast.new(self.type,self.child.to_expr)
|
|
2357
|
+
end
|
|
2358
|
+
|
|
2359
|
+
# Converts the unary expression to HDLRuby::Low.
|
|
2360
|
+
def to_low
|
|
2361
|
+
return HDLRuby::Low::Cast.new(self.type.to_low,self.child.to_low)
|
|
2362
|
+
end
|
|
2363
|
+
end
|
|
2364
|
+
|
|
2365
|
+
|
|
2366
|
+
##
|
|
2367
|
+
# Describes a high-level unary expression
|
|
2368
|
+
class Unary < Low::Unary
|
|
2369
|
+
include HExpression
|
|
2370
|
+
|
|
2371
|
+
# Converts to a new expression.
|
|
2372
|
+
def to_expr
|
|
2373
|
+
return Unary.new(self.type,self.operator,self.child.to_expr)
|
|
2374
|
+
end
|
|
2375
|
+
|
|
2376
|
+
# Converts the unary expression to HDLRuby::Low.
|
|
2377
|
+
def to_low
|
|
2378
|
+
return HDLRuby::Low::Unary.new(self.type.to_low, self.operator,
|
|
2379
|
+
self.child.to_low)
|
|
2380
|
+
end
|
|
2381
|
+
end
|
|
2382
|
+
|
|
2383
|
+
|
|
2384
|
+
##
|
|
2385
|
+
# Describes a high-level binary expression
|
|
2386
|
+
class Binary < Low::Binary
|
|
2387
|
+
include HExpression
|
|
2388
|
+
|
|
2389
|
+
# Converts to a new expression.
|
|
2390
|
+
def to_expr
|
|
2391
|
+
return Binary.new(self.type, self.operator,
|
|
2392
|
+
self.left.to_expr, self.right.to_expr)
|
|
2393
|
+
end
|
|
2394
|
+
|
|
2395
|
+
# Converts the binary expression to HDLRuby::Low.
|
|
2396
|
+
def to_low
|
|
2397
|
+
# return HDLRuby::Low::Binary.new(self.operator,
|
|
2398
|
+
return HDLRuby::Low::Binary.new(self.type.to_low, self.operator,
|
|
2399
|
+
self.left.to_low, self.right.to_low)
|
|
2400
|
+
end
|
|
2401
|
+
end
|
|
2402
|
+
|
|
2403
|
+
|
|
2404
|
+
##
|
|
2405
|
+
# Describes a section operation (generalization of the ternary operator).
|
|
2406
|
+
#
|
|
2407
|
+
# NOTE: choice is using the value of +select+ as an index.
|
|
2408
|
+
class Select < Low::Select
|
|
2409
|
+
include HExpression
|
|
2410
|
+
|
|
2411
|
+
# Converts to a new expression.
|
|
2412
|
+
def to_expr
|
|
2413
|
+
return Select.new(self.type,"?",self.select.to_expr,
|
|
2414
|
+
*self.each_choice.map do |choice|
|
|
2415
|
+
choice.to_expr
|
|
2416
|
+
end)
|
|
2417
|
+
end
|
|
2418
|
+
|
|
2419
|
+
# Converts the selection expression to HDLRuby::Low.
|
|
2420
|
+
def to_low
|
|
2421
|
+
return HDLRuby::Low::Select.new(self.type.to_low,"?",
|
|
2422
|
+
self.select.to_low,
|
|
2423
|
+
*self.each_choice.map do |choice|
|
|
2424
|
+
choice.to_low
|
|
2425
|
+
end)
|
|
2426
|
+
end
|
|
2427
|
+
end
|
|
2428
|
+
|
|
2429
|
+
|
|
2430
|
+
##
|
|
2431
|
+
# Describes z high-level concat expression.
|
|
2432
|
+
class Concat < Low::Concat
|
|
2433
|
+
include HExpression
|
|
2434
|
+
|
|
2435
|
+
# Converts to a new expression.
|
|
2436
|
+
def to_expr
|
|
2437
|
+
return Concat.new(self.type,
|
|
2438
|
+
self.each_expression.map do |expr|
|
|
2439
|
+
expr.to_expr
|
|
2440
|
+
end
|
|
2441
|
+
)
|
|
2442
|
+
end
|
|
2443
|
+
|
|
2444
|
+
# Converts the concatenation expression to HDLRuby::Low.
|
|
2445
|
+
def to_low
|
|
2446
|
+
return HDLRuby::Low::Concat.new(self.type.to_low,
|
|
2447
|
+
self.each_expression.map do |expr|
|
|
2448
|
+
expr.to_low
|
|
2449
|
+
end
|
|
2450
|
+
)
|
|
2451
|
+
end
|
|
2452
|
+
end
|
|
2453
|
+
|
|
2454
|
+
|
|
2455
|
+
##
|
|
2456
|
+
# Describes a high-level value.
|
|
2457
|
+
class Value < Low::Value
|
|
2458
|
+
include HExpression
|
|
2459
|
+
include HDLRuby::Vprocess
|
|
2460
|
+
|
|
2461
|
+
# Tell if the expression can be converted to a value.
|
|
2462
|
+
def to_value?
|
|
2463
|
+
return true
|
|
2464
|
+
end
|
|
2465
|
+
|
|
2466
|
+
# Converts to a new value.
|
|
2467
|
+
def to_value
|
|
2468
|
+
# # Already a value.
|
|
2469
|
+
# self
|
|
2470
|
+
return Value.new(self.type,self.content)
|
|
2471
|
+
end
|
|
2472
|
+
|
|
2473
|
+
# Tell if the expression is constant.
|
|
2474
|
+
def constant?
|
|
2475
|
+
# A value is a constant.
|
|
2476
|
+
return true
|
|
2477
|
+
end
|
|
2478
|
+
|
|
2479
|
+
# Converts to a new expression.
|
|
2480
|
+
def to_expr
|
|
2481
|
+
return self.to_value
|
|
2482
|
+
end
|
|
2483
|
+
|
|
2484
|
+
# Converts the value to HDLRuby::Low.
|
|
2485
|
+
def to_low
|
|
2486
|
+
# Clone the content if possible
|
|
2487
|
+
content = self.content.frozen? ? self.content : self.content.clone
|
|
2488
|
+
# Create and return the resulting low-level value
|
|
2489
|
+
return HDLRuby::Low::Value.new(self.type.to_low,self.content)
|
|
2490
|
+
end
|
|
2491
|
+
|
|
2492
|
+
end
|
|
2493
|
+
|
|
2494
|
+
|
|
2495
|
+
|
|
2496
|
+
##
|
|
2497
|
+
# Module giving high-level reference properties.
|
|
2498
|
+
module HRef
|
|
2499
|
+
# Properties of expressions are also required
|
|
2500
|
+
def self.included(klass)
|
|
2501
|
+
klass.class_eval do
|
|
2502
|
+
include HExpression
|
|
2503
|
+
include HArrow
|
|
2504
|
+
|
|
2505
|
+
# Converts to a new expression.
|
|
2506
|
+
def to_expr
|
|
2507
|
+
self.to_ref
|
|
2508
|
+
end
|
|
2509
|
+
end
|
|
2510
|
+
end
|
|
2511
|
+
|
|
2512
|
+
# Converts to a new reference.
|
|
2513
|
+
#
|
|
2514
|
+
# NOTE: to be redefined in case of non-reference class.
|
|
2515
|
+
def to_ref
|
|
2516
|
+
raise AnyError, "Internal error: to_ref not defined yet for class: #{self.class}"
|
|
2517
|
+
end
|
|
2518
|
+
|
|
2519
|
+
# Converts to a new event.
|
|
2520
|
+
def to_event
|
|
2521
|
+
return Event.new(:change,self.to_ref)
|
|
2522
|
+
end
|
|
2523
|
+
|
|
2524
|
+
# Iterate over the elements.
|
|
2525
|
+
#
|
|
2526
|
+
# Returns an enumerator if no ruby block is given.
|
|
2527
|
+
def each(&ruby_block)
|
|
2528
|
+
# No ruby block? Return an enumerator.
|
|
2529
|
+
return to_enum(:each) unless ruby_block
|
|
2530
|
+
# A block? Apply it on each element.
|
|
2531
|
+
self.type.range.heach do |i|
|
|
2532
|
+
yield(self[i])
|
|
2533
|
+
end
|
|
2534
|
+
end
|
|
2535
|
+
|
|
2536
|
+
# Reference can be used like enumerator
|
|
2537
|
+
include Enumerable
|
|
2538
|
+
end
|
|
2539
|
+
|
|
2540
|
+
|
|
2541
|
+
|
|
2542
|
+
##
|
|
2543
|
+
# Describes a high-level object reference: no low-level equivalent!
|
|
2544
|
+
class RefObject < Low::Ref
|
|
2545
|
+
include HRef
|
|
2546
|
+
|
|
2547
|
+
# The base of the reference
|
|
2548
|
+
attr_reader :base
|
|
2549
|
+
|
|
2550
|
+
# The refered object.
|
|
2551
|
+
attr_reader :object
|
|
2552
|
+
|
|
2553
|
+
# Creates a new reference from a +base+ reference and named +object+.
|
|
2554
|
+
def initialize(base,object)
|
|
2555
|
+
if object.respond_to?(:type) then
|
|
2556
|
+
# Typed object, so typed reference.
|
|
2557
|
+
super(object.type)
|
|
2558
|
+
else
|
|
2559
|
+
# Untyped object, so untyped reference.
|
|
2560
|
+
super(void)
|
|
2561
|
+
end
|
|
2562
|
+
# Check and set the base (it must be convertible to a reference).
|
|
2563
|
+
unless base.respond_to?(:to_ref)
|
|
2564
|
+
raise AnyError, "Invalid base for a RefObject: #{base}"
|
|
2565
|
+
end
|
|
2566
|
+
@base = base
|
|
2567
|
+
# Set the object
|
|
2568
|
+
@object = object
|
|
2569
|
+
end
|
|
2570
|
+
|
|
2571
|
+
# Tell if the expression is constant.
|
|
2572
|
+
def constant?
|
|
2573
|
+
return self.base.constant?
|
|
2574
|
+
end
|
|
2575
|
+
|
|
2576
|
+
# Converts to a new reference.
|
|
2577
|
+
def to_ref
|
|
2578
|
+
return RefObject.new(@base,@object)
|
|
2579
|
+
end
|
|
2580
|
+
|
|
2581
|
+
# Converts the name reference to a HDLRuby::Low::RefName.
|
|
2582
|
+
def to_low
|
|
2583
|
+
# return HDLRuby::Low::RefName.new(@base.to_ref.to_low,@object.name)
|
|
2584
|
+
return HDLRuby::Low::RefName.new(self.type.to_low,
|
|
2585
|
+
@base.to_ref.to_low,@object.name)
|
|
2586
|
+
end
|
|
2587
|
+
|
|
2588
|
+
# Missing methods are looked for into the refered object.
|
|
2589
|
+
def method_missing(m, *args, &ruby_block)
|
|
2590
|
+
@object.send(m,*args,&ruby_block)
|
|
2591
|
+
end
|
|
2592
|
+
|
|
2593
|
+
end
|
|
2594
|
+
|
|
2595
|
+
|
|
2596
|
+
##
|
|
2597
|
+
# Describes a high-level concat reference.
|
|
2598
|
+
class RefConcat < Low::RefConcat
|
|
2599
|
+
include HRef
|
|
2600
|
+
|
|
2601
|
+
# Converts to a new reference.
|
|
2602
|
+
def to_ref
|
|
2603
|
+
return RefConcat.new(self.type,
|
|
2604
|
+
self.each_ref.map do |ref|
|
|
2605
|
+
ref.to_ref
|
|
2606
|
+
end
|
|
2607
|
+
)
|
|
2608
|
+
end
|
|
2609
|
+
|
|
2610
|
+
# Converts the concat reference to HDLRuby::Low.
|
|
2611
|
+
def to_low
|
|
2612
|
+
return HDLRuby::Low::RefConcat.new(self.type.to_low,
|
|
2613
|
+
self.each_ref.map do |ref|
|
|
2614
|
+
ref.to_low
|
|
2615
|
+
end
|
|
2616
|
+
)
|
|
2617
|
+
end
|
|
2618
|
+
end
|
|
2619
|
+
|
|
2620
|
+
##
|
|
2621
|
+
# Describes a high-level index reference.
|
|
2622
|
+
class RefIndex < Low::RefIndex
|
|
2623
|
+
include HRef
|
|
2624
|
+
|
|
2625
|
+
# Converts to a new reference.
|
|
2626
|
+
def to_ref
|
|
2627
|
+
return RefIndex.new(self.type,
|
|
2628
|
+
self.ref.to_ref,self.index.to_expr)
|
|
2629
|
+
end
|
|
2630
|
+
|
|
2631
|
+
# Converts the index reference to HDLRuby::Low.
|
|
2632
|
+
def to_low
|
|
2633
|
+
return HDLRuby::Low::RefIndex.new(self.type.to_low,
|
|
2634
|
+
self.ref.to_low,self.index.to_low)
|
|
2635
|
+
end
|
|
2636
|
+
end
|
|
2637
|
+
|
|
2638
|
+
##
|
|
2639
|
+
# Describes a high-level range reference.
|
|
2640
|
+
class RefRange < Low::RefRange
|
|
2641
|
+
include HRef
|
|
2642
|
+
|
|
2643
|
+
# Converts to a new reference.
|
|
2644
|
+
def to_ref
|
|
2645
|
+
return RefRange.new(self.type,self.ref.to_expr,
|
|
2646
|
+
self.range.first.to_expr..self.range.last.to_expr)
|
|
2647
|
+
end
|
|
2648
|
+
|
|
2649
|
+
# Converts the range reference to HDLRuby::Low.
|
|
2650
|
+
def to_low
|
|
2651
|
+
return HDLRuby::Low::RefRange.new(self.type.to_low,
|
|
2652
|
+
self.ref.to_low,self.range.to_low)
|
|
2653
|
+
end
|
|
2654
|
+
end
|
|
2655
|
+
|
|
2656
|
+
##
|
|
2657
|
+
# Describes a high-level name reference.
|
|
2658
|
+
class RefName < Low::RefName
|
|
2659
|
+
include HRef
|
|
2660
|
+
|
|
2661
|
+
# Converts to a new reference.
|
|
2662
|
+
def to_ref
|
|
2663
|
+
return RefName.new(self.ref.to_ref,self.name)
|
|
2664
|
+
end
|
|
2665
|
+
|
|
2666
|
+
# Converts the name reference to HDLRuby::Low.
|
|
2667
|
+
def to_low
|
|
2668
|
+
# puts "To low for ref with name=#{self.name} and subref=#{self.ref}"
|
|
2669
|
+
return HDLRuby::Low::RefName.new(self.type.to_low,
|
|
2670
|
+
self.ref.to_low,self.name)
|
|
2671
|
+
end
|
|
2672
|
+
end
|
|
2673
|
+
|
|
2674
|
+
##
|
|
2675
|
+
# Describes a this reference.
|
|
2676
|
+
class RefThis < Low::RefThis
|
|
2677
|
+
High = HDLRuby::High
|
|
2678
|
+
include HRef
|
|
2679
|
+
|
|
2680
|
+
# Converts to a new reference.
|
|
2681
|
+
def to_ref
|
|
2682
|
+
return RefThis.new
|
|
2683
|
+
end
|
|
2684
|
+
|
|
2685
|
+
# Gets the enclosing system type.
|
|
2686
|
+
def system
|
|
2687
|
+
return High.cur_system
|
|
2688
|
+
end
|
|
2689
|
+
|
|
2690
|
+
# Gets the enclosing behavior if any.
|
|
2691
|
+
def behavior
|
|
2692
|
+
return High.cur_behavior
|
|
2693
|
+
end
|
|
2694
|
+
|
|
2695
|
+
# Gets the enclosing block if any.
|
|
2696
|
+
def block
|
|
2697
|
+
return High.cur_block
|
|
2698
|
+
end
|
|
2699
|
+
|
|
2700
|
+
# Converts the this reference to HDLRuby::Low.
|
|
2701
|
+
def to_low
|
|
2702
|
+
return HDLRuby::Low::RefThis.new
|
|
2703
|
+
end
|
|
2704
|
+
end
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
# Gives access to the *this* reference.
|
|
2708
|
+
def this
|
|
2709
|
+
RefThis.new
|
|
2710
|
+
end
|
|
2711
|
+
|
|
2712
|
+
|
|
2713
|
+
##
|
|
2714
|
+
# Describes a high-level event.
|
|
2715
|
+
class Event < Low::Event
|
|
2716
|
+
# Converts to a new event.
|
|
2717
|
+
def to_event
|
|
2718
|
+
return Event.new(self.type,self.ref.to_ref)
|
|
2719
|
+
end
|
|
2720
|
+
|
|
2721
|
+
# Inverts the event: create a negedge if posedge, a posedge if negedge.
|
|
2722
|
+
#
|
|
2723
|
+
# NOTE: raise an execption if the event is neigther pos nor neg edge.
|
|
2724
|
+
def invert
|
|
2725
|
+
if self.type == :posedge then
|
|
2726
|
+
return Event.new(:negedge,self.ref.to_ref)
|
|
2727
|
+
elsif self.type == :negedge then
|
|
2728
|
+
return Event.new(:posedge,self.ref.to_ref)
|
|
2729
|
+
else
|
|
2730
|
+
raise AnyError, "Event cannot be inverted: #{self.type}"
|
|
2731
|
+
end
|
|
2732
|
+
end
|
|
2733
|
+
|
|
2734
|
+
# Converts the event to HDLRuby::Low.
|
|
2735
|
+
def to_low
|
|
2736
|
+
return HDLRuby::Low::Event.new(self.type,self.ref.to_low)
|
|
2737
|
+
end
|
|
2738
|
+
end
|
|
2739
|
+
|
|
2740
|
+
|
|
2741
|
+
##
|
|
2742
|
+
# Decribes a transmission statement.
|
|
2743
|
+
class Transmit < Low::Transmit
|
|
2744
|
+
High = HDLRuby::High
|
|
2745
|
+
|
|
2746
|
+
include HStatement
|
|
2747
|
+
|
|
2748
|
+
# Creates a new transmission from a +right+ expression to a +left+
|
|
2749
|
+
# reference, ensuring left is not a constant.
|
|
2750
|
+
def initialize(left,right)
|
|
2751
|
+
if left.constant? then
|
|
2752
|
+
raise AnyError, "Cannot assign to constant: #{left}"
|
|
2753
|
+
end
|
|
2754
|
+
super(left,right)
|
|
2755
|
+
end
|
|
2756
|
+
|
|
2757
|
+
# Converts the transmission to a comparison expression.
|
|
2758
|
+
#
|
|
2759
|
+
# NOTE: required because the <= operator is ambigous and by
|
|
2760
|
+
# default produces a Transmit or a Connection.
|
|
2761
|
+
def to_expr
|
|
2762
|
+
# Remove the transission from the block.
|
|
2763
|
+
High.top_user.delete_statement!(self)
|
|
2764
|
+
# Generate an expression.
|
|
2765
|
+
return Binary.new(
|
|
2766
|
+
self.left.to_expr.type.send(:<=,self.right.to_expr.type),
|
|
2767
|
+
:<=,self.left.to_expr,self.right.to_expr)
|
|
2768
|
+
end
|
|
2769
|
+
|
|
2770
|
+
# Converts the transmit to HDLRuby::Low.
|
|
2771
|
+
def to_low
|
|
2772
|
+
return HDLRuby::Low::Transmit.new(self.left.to_low,
|
|
2773
|
+
self.right.to_low)
|
|
2774
|
+
end
|
|
2775
|
+
end
|
|
2776
|
+
|
|
2777
|
+
##
|
|
2778
|
+
# Describes a connection.
|
|
2779
|
+
class Connection < Low::Connection
|
|
2780
|
+
High = HDLRuby::High
|
|
2781
|
+
|
|
2782
|
+
# Converts the connection to a comparison expression.
|
|
2783
|
+
#
|
|
2784
|
+
# NOTE: required because the <= operator is ambigous and by
|
|
2785
|
+
# default produces a Transmit or a Connection.
|
|
2786
|
+
def to_expr
|
|
2787
|
+
# Remove the connection from the system type.
|
|
2788
|
+
High.top_user.delete_connection(self)
|
|
2789
|
+
# Generate an expression.
|
|
2790
|
+
return Binary.new(:<=,self.left,self.right)
|
|
2791
|
+
end
|
|
2792
|
+
|
|
2793
|
+
# Creates a new behavior sensitive to +event+ including the connection
|
|
2794
|
+
# converted to a transmission, and replace the former by the new
|
|
2795
|
+
# behavior.
|
|
2796
|
+
def at(event)
|
|
2797
|
+
# Creates the behavior.
|
|
2798
|
+
left, right = self.left, self.right
|
|
2799
|
+
# Detached left and right from their connection since they will
|
|
2800
|
+
# be put in a new behavior instead.
|
|
2801
|
+
left.parent = right.parent = nil
|
|
2802
|
+
# Create the new behavior replacing the connection.
|
|
2803
|
+
behavior = Behavior.new(:par,event) do
|
|
2804
|
+
left <= right
|
|
2805
|
+
end
|
|
2806
|
+
# Adds the behavior.
|
|
2807
|
+
High.top_user.add_behavior(behavior)
|
|
2808
|
+
# Remove the connection
|
|
2809
|
+
High.top_user.delete_connection!(self)
|
|
2810
|
+
end
|
|
2811
|
+
|
|
2812
|
+
# Creates a new behavior with an if statement from +condition+
|
|
2813
|
+
# enclosing the connection converted to a transmission, and replace the
|
|
2814
|
+
# former by the new behavior.
|
|
2815
|
+
#
|
|
2816
|
+
# NOTE: the else part is defined through the helse method.
|
|
2817
|
+
def hif(condition)
|
|
2818
|
+
# Creates the behavior.
|
|
2819
|
+
left, right = self.left, self.right
|
|
2820
|
+
# Detached left and right from their connection since they will
|
|
2821
|
+
# be put in a new behavior instead.
|
|
2822
|
+
left.parent = right.parent = nil
|
|
2823
|
+
# Create the new behavior replacing the connection.
|
|
2824
|
+
behavior = Behavior.new(:par) do
|
|
2825
|
+
hif(condition) do
|
|
2826
|
+
left <= right
|
|
2827
|
+
end
|
|
2828
|
+
end
|
|
2829
|
+
# Adds the behavior.
|
|
2830
|
+
High.top_user.add_behavior(behavior)
|
|
2831
|
+
# Remove the connection
|
|
2832
|
+
High.top_user.delete_connection!(self)
|
|
2833
|
+
end
|
|
2834
|
+
|
|
2835
|
+
# Converts the connection to HDLRuby::Low.
|
|
2836
|
+
def to_low
|
|
2837
|
+
return HDLRuby::Low::Connection.new(self.left.to_low,
|
|
2838
|
+
self.right.to_low)
|
|
2839
|
+
end
|
|
2840
|
+
end
|
|
2841
|
+
|
|
2842
|
+
|
|
2843
|
+
##
|
|
2844
|
+
# Describes a high-level signal.
|
|
2845
|
+
class SignalI < Low::SignalI
|
|
2846
|
+
High = HDLRuby::High
|
|
2847
|
+
|
|
2848
|
+
include HRef
|
|
2849
|
+
|
|
2850
|
+
# The valid bounding directions.
|
|
2851
|
+
DIRS = [ :no, :input, :output, :inout, :inner ]
|
|
2852
|
+
|
|
2853
|
+
# The bounding direction.
|
|
2854
|
+
attr_reader :dir
|
|
2855
|
+
|
|
2856
|
+
# Tells if the signal can be read.
|
|
2857
|
+
attr_reader :can_read
|
|
2858
|
+
|
|
2859
|
+
# Tells if the signal can be written.
|
|
2860
|
+
attr_reader :can_write
|
|
2861
|
+
|
|
2862
|
+
# Creates a new signal named +name+ typed as +type+ with
|
|
2863
|
+
# +dir+ as bounding direction and possible +value+.
|
|
2864
|
+
#
|
|
2865
|
+
# NOTE: +dir+ can be :input, :output, :inout or :inner
|
|
2866
|
+
def initialize(name,type,dir,value = nil)
|
|
2867
|
+
# Check the value.
|
|
2868
|
+
value = value.to_expr if value
|
|
2869
|
+
# Initialize the type structure.
|
|
2870
|
+
super(name,type,value)
|
|
2871
|
+
|
|
2872
|
+
unless name.empty? then
|
|
2873
|
+
# Named signal, set the hdl-like access to the signal.
|
|
2874
|
+
obj = self # For using the right self within the proc
|
|
2875
|
+
High.space_reg(name) { obj }
|
|
2876
|
+
end
|
|
2877
|
+
|
|
2878
|
+
# Hierarchical type allows access to sub references, so generate
|
|
2879
|
+
# the corresponding methods.
|
|
2880
|
+
if type.struct? then
|
|
2881
|
+
type.each_name do |name|
|
|
2882
|
+
self.define_singleton_method(name) do
|
|
2883
|
+
RefObject.new(self.to_ref,
|
|
2884
|
+
SignalI.new(name,type.get_type(name),dir))
|
|
2885
|
+
end
|
|
2886
|
+
end
|
|
2887
|
+
end
|
|
2888
|
+
|
|
2889
|
+
# Check and set the bound.
|
|
2890
|
+
self.dir = dir
|
|
2891
|
+
|
|
2892
|
+
# Set the read and write authorisations.
|
|
2893
|
+
@can_read = 1.to_expr
|
|
2894
|
+
@can_write = 1.to_expr
|
|
2895
|
+
end
|
|
2896
|
+
|
|
2897
|
+
# Sets the +condition+ when the signal can be read.
|
|
2898
|
+
def can_read=(condition)
|
|
2899
|
+
@can_read = condition.to_expr
|
|
2900
|
+
end
|
|
2901
|
+
|
|
2902
|
+
# Sets the +condition+ when the signal can be write.
|
|
2903
|
+
def can_write=(condition)
|
|
2904
|
+
@can_write = condition.to_expr
|
|
2905
|
+
end
|
|
2906
|
+
|
|
2907
|
+
# Sets the direction to +dir+.
|
|
2908
|
+
def dir=(dir)
|
|
2909
|
+
unless DIRS.include?(dir) then
|
|
2910
|
+
raise AnyError, "Invalid bounding for signal #{self.name} direction: #{dir}."
|
|
2911
|
+
end
|
|
2912
|
+
@dir = dir
|
|
2913
|
+
end
|
|
2914
|
+
|
|
2915
|
+
# Creates a positive edge event from the signal.
|
|
2916
|
+
def posedge
|
|
2917
|
+
return Event.new(:posedge,self.to_ref)
|
|
2918
|
+
end
|
|
2919
|
+
|
|
2920
|
+
# Creates a negative edge event from the signal.
|
|
2921
|
+
def negedge
|
|
2922
|
+
return Event.new(:negedge,self.to_ref)
|
|
2923
|
+
end
|
|
2924
|
+
|
|
2925
|
+
# Creates an edge event from the signal.
|
|
2926
|
+
def edge
|
|
2927
|
+
return Event.new(:edge,self.to_ref)
|
|
2928
|
+
end
|
|
2929
|
+
|
|
2930
|
+
# Converts to a new reference.
|
|
2931
|
+
def to_ref
|
|
2932
|
+
return RefObject.new(this,self)
|
|
2933
|
+
end
|
|
2934
|
+
|
|
2935
|
+
# Converts to a new expression.
|
|
2936
|
+
def to_expr
|
|
2937
|
+
return self.to_ref
|
|
2938
|
+
end
|
|
2939
|
+
|
|
2940
|
+
# Coerce by converting signal to an expression.
|
|
2941
|
+
def coerce(obj)
|
|
2942
|
+
return [obj,self.to_expr]
|
|
2943
|
+
end
|
|
2944
|
+
|
|
2945
|
+
# Converts the system to HDLRuby::Low and set its +name+.
|
|
2946
|
+
def to_low(name = self.name)
|
|
2947
|
+
return HDLRuby::Low::SignalI.new(name,self.type.to_low)
|
|
2948
|
+
end
|
|
2949
|
+
end
|
|
2950
|
+
|
|
2951
|
+
|
|
2952
|
+
##
|
|
2953
|
+
# Describes a high-level constant signal.
|
|
2954
|
+
class SignalC < Low::SignalC
|
|
2955
|
+
High = HDLRuby::High
|
|
2956
|
+
|
|
2957
|
+
include HRef
|
|
2958
|
+
|
|
2959
|
+
# Creates a new constant signal named +name+ typed as +type+
|
|
2960
|
+
# and +value+.
|
|
2961
|
+
def initialize(name,type,value)
|
|
2962
|
+
# Check the value is a constant.
|
|
2963
|
+
value = value.to_expr
|
|
2964
|
+
unless value.constant? then
|
|
2965
|
+
raise AnyError,"Non-constant value assignment to constant."
|
|
2966
|
+
end
|
|
2967
|
+
# Initialize the type structure.
|
|
2968
|
+
super(name,type,value)
|
|
2969
|
+
|
|
2970
|
+
unless name.empty? then
|
|
2971
|
+
# Named signal, set the hdl-like access to the signal.
|
|
2972
|
+
obj = self # For using the right self within the proc
|
|
2973
|
+
High.space_reg(name) { obj }
|
|
2974
|
+
end
|
|
2975
|
+
|
|
2976
|
+
# Hierarchical type allows access to sub references, so generate
|
|
2977
|
+
# the corresponding methods.
|
|
2978
|
+
if type.struct? then
|
|
2979
|
+
type.each_name do |name|
|
|
2980
|
+
self.define_singleton_method(name) do
|
|
2981
|
+
RefObject.new(self.to_ref,
|
|
2982
|
+
SignalC.new(name,type.get_type(name),
|
|
2983
|
+
value[name]))
|
|
2984
|
+
end
|
|
2985
|
+
end
|
|
2986
|
+
end
|
|
2987
|
+
end
|
|
2988
|
+
|
|
2989
|
+
# Converts to a new reference.
|
|
2990
|
+
def to_ref
|
|
2991
|
+
return RefObject.new(this,self)
|
|
2992
|
+
end
|
|
2993
|
+
|
|
2994
|
+
# Converts to a new expression.
|
|
2995
|
+
def to_expr
|
|
2996
|
+
return self.to_ref
|
|
2997
|
+
end
|
|
2998
|
+
|
|
2999
|
+
# Coerce by converting signal to an expression.
|
|
3000
|
+
def coerce(obj)
|
|
3001
|
+
return [obj,self.to_expr]
|
|
3002
|
+
end
|
|
3003
|
+
|
|
3004
|
+
# Converts the system to HDLRuby::Low and set its +name+.
|
|
3005
|
+
def to_low(name = self.name)
|
|
3006
|
+
return HDLRuby::Low::SignalC.new(name,self.type.to_low,
|
|
3007
|
+
self.value.to_low)
|
|
3008
|
+
end
|
|
3009
|
+
end
|
|
3010
|
+
|
|
3011
|
+
##
|
|
3012
|
+
# Module giving the properties of a high-level block.
|
|
3013
|
+
module HBlock
|
|
3014
|
+
High = HDLRuby::High
|
|
3015
|
+
|
|
3016
|
+
# The namespace
|
|
3017
|
+
attr_reader :namespace
|
|
3018
|
+
|
|
3019
|
+
# The return value when building the scope.
|
|
3020
|
+
attr_reader :return_value
|
|
3021
|
+
|
|
3022
|
+
# Build the block by executing +ruby_block+.
|
|
3023
|
+
def build(&ruby_block)
|
|
3024
|
+
High.space_push(@namespace)
|
|
3025
|
+
@return_value = High.top_user.instance_eval(&ruby_block)
|
|
3026
|
+
High.space_pop
|
|
3027
|
+
@return_value
|
|
3028
|
+
end
|
|
3029
|
+
|
|
3030
|
+
# Opens the block.
|
|
3031
|
+
alias_method :open, :build
|
|
3032
|
+
|
|
3033
|
+
# Converts to a new reference.
|
|
3034
|
+
def to_ref
|
|
3035
|
+
return RefObject.new(this,self)
|
|
3036
|
+
end
|
|
3037
|
+
|
|
3038
|
+
include HScope_missing
|
|
3039
|
+
|
|
3040
|
+
# Creates and adds a new block executed in +mode+, with possible
|
|
3041
|
+
# +name+ and built by executing +ruby_block+.
|
|
3042
|
+
def add_block(mode = nil, name = :"", &ruby_block)
|
|
3043
|
+
# Creates the block.
|
|
3044
|
+
block = High.make_block(mode,name,&ruby_block)
|
|
3045
|
+
# Adds it as a statement.
|
|
3046
|
+
self.add_statement(block)
|
|
3047
|
+
# Use its return value.
|
|
3048
|
+
return block.return_value
|
|
3049
|
+
end
|
|
3050
|
+
|
|
3051
|
+
# Creates a new parallel block with possible +name+ and
|
|
3052
|
+
# built from +ruby_block+.
|
|
3053
|
+
def par(name = :"", &ruby_block)
|
|
3054
|
+
return :par unless ruby_block
|
|
3055
|
+
self.add_block(:par,name,&ruby_block)
|
|
3056
|
+
end
|
|
3057
|
+
|
|
3058
|
+
# Creates a new sequential block with possible +name+ and
|
|
3059
|
+
# built from +ruby_block+.
|
|
3060
|
+
def seq(name = :"", &ruby_block)
|
|
3061
|
+
return :seq unless ruby_block
|
|
3062
|
+
self.add_block(:seq,name,&ruby_block)
|
|
3063
|
+
end
|
|
3064
|
+
|
|
3065
|
+
# Creates a new block with the current mode with possible +name+ and
|
|
3066
|
+
# built from +ruby_block+.
|
|
3067
|
+
def sub(name = :"", &ruby_block)
|
|
3068
|
+
self.add_block(self.mode,name,&ruby_block)
|
|
3069
|
+
end
|
|
3070
|
+
|
|
3071
|
+
# Get the current mode of the block.
|
|
3072
|
+
#
|
|
3073
|
+
# NOTE: for name coherency purpose only.
|
|
3074
|
+
def block
|
|
3075
|
+
return self.mode
|
|
3076
|
+
end
|
|
3077
|
+
|
|
3078
|
+
# Need to be able to declare select operators
|
|
3079
|
+
include Hmux
|
|
3080
|
+
|
|
3081
|
+
# Creates a new if statement with a +condition+ that when met lead
|
|
3082
|
+
# to the execution of the block in +mode+ generated by the
|
|
3083
|
+
# +ruby_block+.
|
|
3084
|
+
#
|
|
3085
|
+
# NOTE: the else part is defined through the helse method.
|
|
3086
|
+
def hif(condition, mode = nil, &ruby_block)
|
|
3087
|
+
# Creates the if statement.
|
|
3088
|
+
self.add_statement(If.new(condition,mode,&ruby_block))
|
|
3089
|
+
end
|
|
3090
|
+
|
|
3091
|
+
# Sets the block executed when the condition is not met to the block
|
|
3092
|
+
# in +mode+ generated by the execution of +ruby_block+.
|
|
3093
|
+
#
|
|
3094
|
+
# Can only be used once.
|
|
3095
|
+
def helse(mode = nil, &ruby_block)
|
|
3096
|
+
# There is a ruby_block: the helse is assumed to be with
|
|
3097
|
+
# the hif in the same block.
|
|
3098
|
+
# Completes the hif or the hcase statement.
|
|
3099
|
+
statement = @statements.last
|
|
3100
|
+
unless statement.is_a?(If) or statement.is_a?(Case) then
|
|
3101
|
+
raise AnyError, "Error: helse statement without hif nor hcase (#{statement.class})."
|
|
3102
|
+
end
|
|
3103
|
+
statement.helse(mode, &ruby_block)
|
|
3104
|
+
end
|
|
3105
|
+
|
|
3106
|
+
# Sets the condition check when the condition is not met to the block,
|
|
3107
|
+
# with a +condition+ that when met lead
|
|
3108
|
+
# to the execution of the block in +mode+ generated by the +ruby_block+.
|
|
3109
|
+
def helsif(condition, mode = nil, &ruby_block)
|
|
3110
|
+
# There is a ruby_block: the helse is assumed to be with
|
|
3111
|
+
# the hif in the same block.
|
|
3112
|
+
# Completes the hif statement.
|
|
3113
|
+
statement = @statements.last
|
|
3114
|
+
unless statement.is_a?(If) then
|
|
3115
|
+
raise AnyError,
|
|
3116
|
+
"Error: helsif statement without hif (#{statement.class})."
|
|
3117
|
+
end
|
|
3118
|
+
statement.helsif(condition, mode, &ruby_block)
|
|
3119
|
+
end
|
|
3120
|
+
|
|
3121
|
+
|
|
3122
|
+
|
|
3123
|
+
# Creates a new case statement with a +value+ used for deciding which
|
|
3124
|
+
# block to execute.
|
|
3125
|
+
#
|
|
3126
|
+
# NOTE: the when part is defined through the hwhen method.
|
|
3127
|
+
def hcase(value)
|
|
3128
|
+
# Creates the case statement.
|
|
3129
|
+
self.add_statement(Case.new(value))
|
|
3130
|
+
end
|
|
3131
|
+
|
|
3132
|
+
# Sets the block of a case structure executed when the +match+ is met
|
|
3133
|
+
# to the block in +mode+ generated by the execution of +ruby_block+.
|
|
3134
|
+
#
|
|
3135
|
+
# Can only be used once.
|
|
3136
|
+
def hwhen(match, mode = nil, &ruby_block)
|
|
3137
|
+
# There is a ruby_block: the helse is assumed to be with
|
|
3138
|
+
# the hif in the same block.
|
|
3139
|
+
# Completes the hcase statement.
|
|
3140
|
+
statement = @statements.last
|
|
3141
|
+
unless statement.is_a?(Case) then
|
|
3142
|
+
raise AnyError,
|
|
3143
|
+
"Error: hwhen statement without hcase (#{statement.class})."
|
|
3144
|
+
end
|
|
3145
|
+
statement.hwhen(match, mode, &ruby_block)
|
|
3146
|
+
end
|
|
3147
|
+
end
|
|
3148
|
+
|
|
3149
|
+
|
|
3150
|
+
##
|
|
3151
|
+
# Describes a high-level block.
|
|
3152
|
+
class Block < Low::Block
|
|
3153
|
+
High = HDLRuby::High
|
|
3154
|
+
|
|
3155
|
+
include HBlock
|
|
3156
|
+
include Hinner
|
|
3157
|
+
|
|
3158
|
+
# Creates a new +mode+ sort of block, with possible +name+
|
|
3159
|
+
# and build it by executing +ruby_block+.
|
|
3160
|
+
def initialize(mode, name=:"", &ruby_block)
|
|
3161
|
+
# Initialize the block.
|
|
3162
|
+
super(mode,name)
|
|
3163
|
+
|
|
3164
|
+
unless name.empty? then
|
|
3165
|
+
# Named block, set the hdl-like access to the block.
|
|
3166
|
+
obj = self # For using the right self within the proc
|
|
3167
|
+
High.space_reg(name) { obj }
|
|
3168
|
+
end
|
|
3169
|
+
|
|
3170
|
+
# Creates the namespace.
|
|
3171
|
+
@namespace = Namespace.new(self)
|
|
3172
|
+
|
|
3173
|
+
# puts "methods = #{self.methods.sort}"
|
|
3174
|
+
build(&ruby_block)
|
|
3175
|
+
end
|
|
3176
|
+
|
|
3177
|
+
# Converts the block to HDLRuby::Low.
|
|
3178
|
+
def to_low
|
|
3179
|
+
# Create the resulting block
|
|
3180
|
+
blockL = HDLRuby::Low::Block.new(self.mode)
|
|
3181
|
+
# Push the namespace for the low generation.
|
|
3182
|
+
High.space_push(@namespace)
|
|
3183
|
+
# Pushes on the name stack for converting the internals of
|
|
3184
|
+
# the block.
|
|
3185
|
+
High.names_push
|
|
3186
|
+
# Add the inner signals
|
|
3187
|
+
self.each_inner { |inner| blockL.add_inner(inner.to_low) }
|
|
3188
|
+
# Add the statements
|
|
3189
|
+
self.each_statement do |statement|
|
|
3190
|
+
blockL.add_statement(statement.to_low)
|
|
3191
|
+
end
|
|
3192
|
+
# Restores the name stack.
|
|
3193
|
+
High.names_pop
|
|
3194
|
+
# Restores the namespace stack.
|
|
3195
|
+
High.space_pop
|
|
3196
|
+
# Return the resulting block
|
|
3197
|
+
return blockL
|
|
3198
|
+
end
|
|
3199
|
+
end
|
|
3200
|
+
|
|
3201
|
+
|
|
3202
|
+
# Describes a timed block.
|
|
3203
|
+
#
|
|
3204
|
+
# NOTE:
|
|
3205
|
+
# * this is the only kind of block that can include time statements.
|
|
3206
|
+
# * this kind of block is not synthesizable!
|
|
3207
|
+
class TimeBlock < Low::TimeBlock
|
|
3208
|
+
High = HDLRuby::High
|
|
3209
|
+
|
|
3210
|
+
include HBlock
|
|
3211
|
+
|
|
3212
|
+
# Creates a new +type+ sort of block with possible +name+
|
|
3213
|
+
# and build it by executing +ruby_block+.
|
|
3214
|
+
def initialize(type, name = :"", &ruby_block)
|
|
3215
|
+
# Initialize the block.
|
|
3216
|
+
super(type,name)
|
|
3217
|
+
|
|
3218
|
+
unless name.empty? then
|
|
3219
|
+
# Named block, set the hdl-like access to the block.
|
|
3220
|
+
obj = self # For using the right self within the proc
|
|
3221
|
+
High.space_reg(name) { obj }
|
|
3222
|
+
end
|
|
3223
|
+
|
|
3224
|
+
# Creates the namespace.
|
|
3225
|
+
@namespace = Namespace.new(self)
|
|
3226
|
+
|
|
3227
|
+
build(&ruby_block)
|
|
3228
|
+
end
|
|
3229
|
+
|
|
3230
|
+
# Adds a wait +delay+ statement in the block.
|
|
3231
|
+
def wait(delay)
|
|
3232
|
+
self.add_statement(TimeWait.new(delay))
|
|
3233
|
+
end
|
|
3234
|
+
|
|
3235
|
+
# Adds a loop until +delay+ statement in the block in +mode+ whose
|
|
3236
|
+
# loop content is built using +ruby_block+.
|
|
3237
|
+
def repeat(delay, mode = nil, &ruby_block)
|
|
3238
|
+
# Build the content block.
|
|
3239
|
+
content = High.make_block(mode,&ruby_block)
|
|
3240
|
+
# Create and add the statement.
|
|
3241
|
+
self.add_statement(TimeRepeat.new(content,delay))
|
|
3242
|
+
end
|
|
3243
|
+
|
|
3244
|
+
# Converts the time block to HDLRuby::Low.
|
|
3245
|
+
def to_low
|
|
3246
|
+
# Create the resulting block
|
|
3247
|
+
blockL = HDLRuby::Low::TimeBlock.new(self.mode)
|
|
3248
|
+
# Add the inner signals
|
|
3249
|
+
self.each_inner { |inner| blockL.add_inner(inner.to_low) }
|
|
3250
|
+
# Add the statements
|
|
3251
|
+
self.each_statement do |statement|
|
|
3252
|
+
blockL.add_statement(statement.to_low)
|
|
3253
|
+
end
|
|
3254
|
+
# Return the resulting block
|
|
3255
|
+
return blockL
|
|
3256
|
+
end
|
|
3257
|
+
end
|
|
3258
|
+
|
|
3259
|
+
|
|
3260
|
+
# Creates a block executed in +mode+, with possible +name+,
|
|
3261
|
+
# that can be timed or not depending on the enclosing object and build
|
|
3262
|
+
# it by executing the enclosing +ruby_block+.
|
|
3263
|
+
#
|
|
3264
|
+
# NOTE: not a method to include since it can only be used with
|
|
3265
|
+
# a behavior or a block. Hence set as module method.
|
|
3266
|
+
def self.make_block(mode = nil, name = :"", &ruby_block)
|
|
3267
|
+
unless mode then
|
|
3268
|
+
# No type of block given, get a default one.
|
|
3269
|
+
if top_user.is_a?(Block) then
|
|
3270
|
+
# There is an upper block, use its mode.
|
|
3271
|
+
mode = top_user.mode
|
|
3272
|
+
else
|
|
3273
|
+
# There is no upper block, use :par as default.
|
|
3274
|
+
mode = :par
|
|
3275
|
+
end
|
|
3276
|
+
end
|
|
3277
|
+
if top_user.is_a?(TimeBlock) then
|
|
3278
|
+
return TimeBlock.new(mode,name,&ruby_block)
|
|
3279
|
+
else
|
|
3280
|
+
return Block.new(mode,name,&ruby_block)
|
|
3281
|
+
end
|
|
3282
|
+
end
|
|
3283
|
+
|
|
3284
|
+
# Creates a specifically timed block in +mode+, with possible +name+
|
|
3285
|
+
# and build it by executing the enclosing +ruby_block+.
|
|
3286
|
+
#
|
|
3287
|
+
# NOTE: not a method to include since it can only be used with
|
|
3288
|
+
# a behavior or a block. Hence set as module method.
|
|
3289
|
+
def self.make_time_block(mode = nil, name = :"", &ruby_block)
|
|
3290
|
+
unless mode then
|
|
3291
|
+
# No type of block given, get a default one.
|
|
3292
|
+
if top_user.is_a?(Block) then
|
|
3293
|
+
# There is an upper block, use its mode.
|
|
3294
|
+
mode = block.mode
|
|
3295
|
+
else
|
|
3296
|
+
# There is no upper block, use :par as default.
|
|
3297
|
+
mode = :par
|
|
3298
|
+
end
|
|
3299
|
+
end
|
|
3300
|
+
return TimeBlock.new(mode,name,&ruby_block)
|
|
3301
|
+
end
|
|
3302
|
+
|
|
3303
|
+
##
|
|
3304
|
+
# Describes a high-level behavior.
|
|
3305
|
+
class Behavior < Low::Behavior
|
|
3306
|
+
High = HDLRuby::High
|
|
3307
|
+
|
|
3308
|
+
# Creates a new behavior executing +block+ activated on a list of
|
|
3309
|
+
# +events+, and built by executing +ruby_block+.
|
|
3310
|
+
# +mode+ can be either :seq or :par for respectively sequential or
|
|
3311
|
+
# parallel.
|
|
3312
|
+
def initialize(mode,*events,&ruby_block)
|
|
3313
|
+
# Initialize the behavior with it.
|
|
3314
|
+
super(nil)
|
|
3315
|
+
# # Save the Location for debugging information
|
|
3316
|
+
# @location = caller_locations
|
|
3317
|
+
# Sets the current behavior
|
|
3318
|
+
@@cur_behavior = self
|
|
3319
|
+
# Add the events.
|
|
3320
|
+
events.each { |event| self.add_event(event) }
|
|
3321
|
+
# Create and add the block.
|
|
3322
|
+
self.block = High.make_block(mode,&ruby_block)
|
|
3323
|
+
# Unset the current behavior
|
|
3324
|
+
@@cur_behavior = nil
|
|
3325
|
+
end
|
|
3326
|
+
|
|
3327
|
+
# Sets an event to the behavior.
|
|
3328
|
+
# NOTE: currently actually adds an event if there are already some!
|
|
3329
|
+
alias_method :at, :add_event
|
|
3330
|
+
|
|
3331
|
+
# Converts the time behavior to HDLRuby::Low.
|
|
3332
|
+
def to_low
|
|
3333
|
+
# Create the low level block.
|
|
3334
|
+
blockL = self.block.to_low
|
|
3335
|
+
# Create the low level events.
|
|
3336
|
+
eventLs = self.each_event.map { |event| event.to_low }
|
|
3337
|
+
# Create and return the resulting low level behavior.
|
|
3338
|
+
behaviorL = HDLRuby::Low::Behavior.new(blockL)
|
|
3339
|
+
eventLs.each(&behaviorL.method(:add_event))
|
|
3340
|
+
return behaviorL
|
|
3341
|
+
end
|
|
3342
|
+
end
|
|
3343
|
+
|
|
3344
|
+
##
|
|
3345
|
+
# Describes a high-level timed behavior.
|
|
3346
|
+
class TimeBehavior < Low::TimeBehavior
|
|
3347
|
+
High = HDLRuby::High
|
|
3348
|
+
|
|
3349
|
+
# Creates a new timed behavior built by executing +ruby_block+.
|
|
3350
|
+
# +mode+ can be either :seq or :par for respectively sequential or
|
|
3351
|
+
def initialize(mode, &ruby_block)
|
|
3352
|
+
# Create a default par block for the behavior.
|
|
3353
|
+
block = High.make_time_block(mode,&ruby_block)
|
|
3354
|
+
# Initialize the behavior with it.
|
|
3355
|
+
super(block)
|
|
3356
|
+
end
|
|
3357
|
+
|
|
3358
|
+
# Converts the time behavior to HDLRuby::Low.
|
|
3359
|
+
def to_low
|
|
3360
|
+
# Create the low level block.
|
|
3361
|
+
blockL = self.block.to_low
|
|
3362
|
+
# Create the low level events.
|
|
3363
|
+
eventLs = self.each_event.map { |event| event.to_low }
|
|
3364
|
+
# Create and return the resulting low level behavior.
|
|
3365
|
+
behaviorL = HDLRuby::Low::TimeBehavior.new(blockL)
|
|
3366
|
+
eventLs.each(&behaviorL.method(:add_event))
|
|
3367
|
+
return behaviorL
|
|
3368
|
+
end
|
|
3369
|
+
end
|
|
3370
|
+
|
|
3371
|
+
|
|
3372
|
+
|
|
3373
|
+
|
|
3374
|
+
|
|
3375
|
+
# Handle the namespaces for accessing the hardware referencing methods.
|
|
3376
|
+
|
|
3377
|
+
# The universe, i.e., the top system type.
|
|
3378
|
+
Universe = SystemT.new(:"") {}
|
|
3379
|
+
|
|
3380
|
+
# The universe does not have input, output, nor inout.
|
|
3381
|
+
class << Universe
|
|
3382
|
+
undef_method :input
|
|
3383
|
+
undef_method :output
|
|
3384
|
+
undef_method :inout
|
|
3385
|
+
undef_method :add_input
|
|
3386
|
+
undef_method :add_output
|
|
3387
|
+
undef_method :add_inout
|
|
3388
|
+
end
|
|
3389
|
+
|
|
3390
|
+
|
|
3391
|
+
# include Hmissing
|
|
3392
|
+
|
|
3393
|
+
# The namespace stack: never empty, the top is a nameless system without
|
|
3394
|
+
# input nor output.
|
|
3395
|
+
Namespaces = [Universe.scope.namespace]
|
|
3396
|
+
private_constant :Namespaces
|
|
3397
|
+
|
|
3398
|
+
# Pushes +namespace+.
|
|
3399
|
+
def self.space_push(namespace)
|
|
3400
|
+
# Emsure namespace is really a namespace.
|
|
3401
|
+
namespace = namespace.to_namespace
|
|
3402
|
+
# Adds the namespace to the top.
|
|
3403
|
+
Namespaces.push(namespace)
|
|
3404
|
+
end
|
|
3405
|
+
|
|
3406
|
+
# Inserts +namespace+ at +index+.
|
|
3407
|
+
def self.space_insert(index,namespace)
|
|
3408
|
+
Namespaces.insert(index.to_i,namespace.to_namespace)
|
|
3409
|
+
end
|
|
3410
|
+
|
|
3411
|
+
# Pops a namespace.
|
|
3412
|
+
def self.space_pop
|
|
3413
|
+
if Namespaces.size <= 1 then
|
|
3414
|
+
raise AnyError, "Internal error: cannot pop further namespaces."
|
|
3415
|
+
end
|
|
3416
|
+
Namespaces.pop
|
|
3417
|
+
end
|
|
3418
|
+
|
|
3419
|
+
# Tells if +namespace+ in included within the stack.
|
|
3420
|
+
def self.space_include?(namespace)
|
|
3421
|
+
return Namespaces.include?(namespace)
|
|
3422
|
+
end
|
|
3423
|
+
|
|
3424
|
+
# Gets the index of a +namespace+ within the stack.
|
|
3425
|
+
def self.space_index(namespace)
|
|
3426
|
+
return Namespaces.index(namespace)
|
|
3427
|
+
end
|
|
3428
|
+
|
|
3429
|
+
# Gets the top of the namespaces stack.
|
|
3430
|
+
def self.space_top
|
|
3431
|
+
Namespaces[-1]
|
|
3432
|
+
end
|
|
3433
|
+
|
|
3434
|
+
# sets the top namespace.
|
|
3435
|
+
def self.space_top=(top)
|
|
3436
|
+
unless top.is_a?(Namespace) then
|
|
3437
|
+
raise "Invalid class for a Namspace: #{top.class}"
|
|
3438
|
+
end
|
|
3439
|
+
Namespaces[-1] = top
|
|
3440
|
+
end
|
|
3441
|
+
|
|
3442
|
+
|
|
3443
|
+
# Gets construct whose namespace is the top of the namespaces stack.
|
|
3444
|
+
def self.top_user
|
|
3445
|
+
self.space_top.user
|
|
3446
|
+
end
|
|
3447
|
+
|
|
3448
|
+
# Gather the result of the execution of +method+ from all the users
|
|
3449
|
+
# of the namespaces.
|
|
3450
|
+
def self.from_users(method)
|
|
3451
|
+
Namespaces.reverse_each.reduce([]) do |res,space|
|
|
3452
|
+
user = space.user
|
|
3453
|
+
if user.respond_to?(method) then
|
|
3454
|
+
res += [*user.send(method)]
|
|
3455
|
+
end
|
|
3456
|
+
end
|
|
3457
|
+
end
|
|
3458
|
+
|
|
3459
|
+
# Iterates over each namespace.
|
|
3460
|
+
#
|
|
3461
|
+
# Returns an enumerator if no ruby block is given.
|
|
3462
|
+
def self.space_each(&ruby_block)
|
|
3463
|
+
# No ruby block? Return an enumerator.
|
|
3464
|
+
return to_enum(:space_each) unless ruby_block
|
|
3465
|
+
# A block? Apply it on each system instance.
|
|
3466
|
+
Namespaces.each(&ruby_block)
|
|
3467
|
+
end
|
|
3468
|
+
|
|
3469
|
+
# Tells if within a system type.
|
|
3470
|
+
def self.in_system?
|
|
3471
|
+
return Namespaces.size > 1
|
|
3472
|
+
end
|
|
3473
|
+
|
|
3474
|
+
# Gets the enclosing system type if any.
|
|
3475
|
+
def self.cur_system
|
|
3476
|
+
if Namespaces.size <= 1 then
|
|
3477
|
+
raise AnyError, "Not within a system type."
|
|
3478
|
+
else
|
|
3479
|
+
return Namespaces.reverse_each.find do |space|
|
|
3480
|
+
space.user.is_a?(Scope) and space.user.parent.is_a?(SystemT)
|
|
3481
|
+
end.user.parent
|
|
3482
|
+
end
|
|
3483
|
+
end
|
|
3484
|
+
|
|
3485
|
+
# The current behavior: by default none.
|
|
3486
|
+
@@cur_behavior = nil
|
|
3487
|
+
|
|
3488
|
+
# Gets the enclosing behavior if any.
|
|
3489
|
+
def self.cur_behavior
|
|
3490
|
+
return @@cur_behavior
|
|
3491
|
+
end
|
|
3492
|
+
|
|
3493
|
+
# Tell if we are in a behavior.
|
|
3494
|
+
def self.in_behavior?
|
|
3495
|
+
top_user.is_a?(Block)
|
|
3496
|
+
end
|
|
3497
|
+
|
|
3498
|
+
# Gets the enclosing block if any.
|
|
3499
|
+
#
|
|
3500
|
+
# NOTE: +level+ allows to get an upper block of the currently enclosing
|
|
3501
|
+
# block.
|
|
3502
|
+
def self.cur_block(level = 0)
|
|
3503
|
+
if Namespaces[-1-level].user.is_a?(Scope) then
|
|
3504
|
+
raise AnyError,
|
|
3505
|
+
"Not within a block: #{Namespaces[-1-level].user.class}"
|
|
3506
|
+
elsif Namespaces[-1-level].user.is_a?(Block) then
|
|
3507
|
+
return Namespaces[-1-level].user
|
|
3508
|
+
else
|
|
3509
|
+
return cur_block(level+1)
|
|
3510
|
+
end
|
|
3511
|
+
end
|
|
3512
|
+
|
|
3513
|
+
# Registers hardware referencing method +name+ to the current namespace.
|
|
3514
|
+
def self.space_reg(name,&ruby_block)
|
|
3515
|
+
# print "registering #{name} in #{Namespaces[-1]}\n"
|
|
3516
|
+
Namespaces[-1].add_method(name,&ruby_block)
|
|
3517
|
+
end
|
|
3518
|
+
|
|
3519
|
+
# Looks up and calls method +name+ from the namespace stack with arguments
|
|
3520
|
+
# +args+ and block +ruby_block+.
|
|
3521
|
+
def self.space_call(name,*args,&ruby_block)
|
|
3522
|
+
# print "space_call with name=#{name}\n"
|
|
3523
|
+
# Ensures name is a symbol.
|
|
3524
|
+
name = name.to_sym
|
|
3525
|
+
# Look from the top of the namespace stack.
|
|
3526
|
+
Namespaces.reverse_each do |space|
|
|
3527
|
+
# puts "space=#{space.singleton_methods}"
|
|
3528
|
+
if space.respond_to?(name) then
|
|
3529
|
+
# print "Found is space user with class=#{space.user.class}\n"
|
|
3530
|
+
# The method is found, call it.
|
|
3531
|
+
return space.send(name,*args,&ruby_block)
|
|
3532
|
+
elsif space.user.respond_to?(name) then
|
|
3533
|
+
# The method is found in the user, call it.
|
|
3534
|
+
return space.user.send(name,*args,&ruby_block)
|
|
3535
|
+
end
|
|
3536
|
+
end
|
|
3537
|
+
# Look in the global methods.
|
|
3538
|
+
if HDLRuby::High.respond_to?(name) then
|
|
3539
|
+
# Found.
|
|
3540
|
+
return HDLRuby::High.send(name,*args,&ruby_block)
|
|
3541
|
+
end
|
|
3542
|
+
# Not found.
|
|
3543
|
+
raise NotDefinedError,
|
|
3544
|
+
"undefined HDLRuby construct, local variable or method `#{name}'."
|
|
3545
|
+
end
|
|
3546
|
+
|
|
3547
|
+
|
|
3548
|
+
|
|
3549
|
+
|
|
3550
|
+
|
|
3551
|
+
|
|
3552
|
+
|
|
3553
|
+
# Extends the standard classes for support of HDLRuby.
|
|
3554
|
+
|
|
3555
|
+
|
|
3556
|
+
# Extends the Numeric class for conversion to a high-level expression.
|
|
3557
|
+
class ::Numeric
|
|
3558
|
+
|
|
3559
|
+
# Tell if the expression can be converted to a value.
|
|
3560
|
+
def to_value?
|
|
3561
|
+
return true
|
|
3562
|
+
end
|
|
3563
|
+
|
|
3564
|
+
# Converts to a new high-level value.
|
|
3565
|
+
def to_value
|
|
3566
|
+
to_expr
|
|
3567
|
+
end
|
|
3568
|
+
|
|
3569
|
+
# Converts to a new delay in picoseconds.
|
|
3570
|
+
def ps
|
|
3571
|
+
return Delay.new(self,:ps)
|
|
3572
|
+
end
|
|
3573
|
+
|
|
3574
|
+
# Converts to a new delay in nanoseconds.
|
|
3575
|
+
def ns
|
|
3576
|
+
return Delay.new(self,:ns)
|
|
3577
|
+
end
|
|
3578
|
+
|
|
3579
|
+
# Converts to a new delay in microseconds.
|
|
3580
|
+
def us
|
|
3581
|
+
return Delay.new(self,:us)
|
|
3582
|
+
end
|
|
3583
|
+
|
|
3584
|
+
# Converts to a new delay in milliseconds.
|
|
3585
|
+
def ms
|
|
3586
|
+
return Delay.new(self,:ms)
|
|
3587
|
+
end
|
|
3588
|
+
|
|
3589
|
+
# Converts to a new delay in seconds.
|
|
3590
|
+
def s
|
|
3591
|
+
return Delay.new(self,:s)
|
|
3592
|
+
end
|
|
3593
|
+
end
|
|
3594
|
+
|
|
3595
|
+
# Extends the Fixnum class for computing for conversion to expression.
|
|
3596
|
+
class ::Fixnum
|
|
3597
|
+
# Converts to a new high-level expression.
|
|
3598
|
+
def to_expr
|
|
3599
|
+
return Value.new(Integer,self)
|
|
3600
|
+
end
|
|
3601
|
+
end
|
|
3602
|
+
|
|
3603
|
+
# Extends the Bignum class for computing for conversion to expression.
|
|
3604
|
+
class ::Bignum
|
|
3605
|
+
# Converts to a new high-level expression.
|
|
3606
|
+
def to_expr
|
|
3607
|
+
return Value.new(Bignum,self)
|
|
3608
|
+
end
|
|
3609
|
+
end
|
|
3610
|
+
|
|
3611
|
+
# Extends the Float class for computing the bit width and conversion
|
|
3612
|
+
# to expression.
|
|
3613
|
+
class ::Float
|
|
3614
|
+
# Converts to a new high-level expression.
|
|
3615
|
+
def to_expr
|
|
3616
|
+
return Value.new(Real,self)
|
|
3617
|
+
end
|
|
3618
|
+
|
|
3619
|
+
# Gets the bit width
|
|
3620
|
+
def width
|
|
3621
|
+
return 64
|
|
3622
|
+
end
|
|
3623
|
+
end
|
|
3624
|
+
|
|
3625
|
+
# Extends the String class for computing conversion to expression.
|
|
3626
|
+
class ::String
|
|
3627
|
+
# Converts to a new high-level expression.
|
|
3628
|
+
def to_expr
|
|
3629
|
+
# Convert the string to a bit string.
|
|
3630
|
+
bstr = BitString.new(self)
|
|
3631
|
+
# Use it to create the new value.
|
|
3632
|
+
return Value.new(Bit[bstr.width],self)
|
|
3633
|
+
end
|
|
3634
|
+
end
|
|
3635
|
+
|
|
3636
|
+
|
|
3637
|
+
# Extends the Hash class for declaring signals of structure types.
|
|
3638
|
+
class ::Hash
|
|
3639
|
+
|
|
3640
|
+
# Converts to a new type.
|
|
3641
|
+
def to_type
|
|
3642
|
+
return TypeStruct.new(:"",:little,self)
|
|
3643
|
+
end
|
|
3644
|
+
|
|
3645
|
+
# Declares a new type definition with +name+ equivalent to current one.
|
|
3646
|
+
def typedef(name)
|
|
3647
|
+
return self.to_type.typedef(name)
|
|
3648
|
+
end
|
|
3649
|
+
|
|
3650
|
+
# Declares high-level input signals named +names+ of the current type.
|
|
3651
|
+
#
|
|
3652
|
+
# Retuns the last declared input.
|
|
3653
|
+
def input(*names)
|
|
3654
|
+
res = nil
|
|
3655
|
+
names.each do |name|
|
|
3656
|
+
res = HDLRuby::High.top_user.
|
|
3657
|
+
add_input(SignalI.new(name,
|
|
3658
|
+
TypeStruct.new(:"",:little,self),:input))
|
|
3659
|
+
end
|
|
3660
|
+
return res
|
|
3661
|
+
end
|
|
3662
|
+
|
|
3663
|
+
# Declares high-level untyped output signals named +names+ of the
|
|
3664
|
+
# current type.
|
|
3665
|
+
#
|
|
3666
|
+
# Retuns the last declared output.
|
|
3667
|
+
def output(*names)
|
|
3668
|
+
res = nil
|
|
3669
|
+
names.each do |name|
|
|
3670
|
+
res = HDLRuby::High.top_user.
|
|
3671
|
+
add_output(SignalI.new(name,
|
|
3672
|
+
TypeStruct.new(:"",:little,self),:output))
|
|
3673
|
+
end
|
|
3674
|
+
return res
|
|
3675
|
+
end
|
|
3676
|
+
|
|
3677
|
+
# Declares high-level untyped inout signals named +names+ of the
|
|
3678
|
+
# current type.
|
|
3679
|
+
#
|
|
3680
|
+
# Retuns the last declared inout.
|
|
3681
|
+
def inout(*names)
|
|
3682
|
+
res = nil
|
|
3683
|
+
names.each do |name|
|
|
3684
|
+
res = HDLRuby::High.top_user.
|
|
3685
|
+
add_inout(SignalI.new(name,
|
|
3686
|
+
TypeStruct.new(:"",:little,self),:inout))
|
|
3687
|
+
end
|
|
3688
|
+
return res
|
|
3689
|
+
end
|
|
3690
|
+
|
|
3691
|
+
# Declares high-level untyped inner signals named +names+ of the
|
|
3692
|
+
# current type.
|
|
3693
|
+
#
|
|
3694
|
+
# Retuns the last declared inner.
|
|
3695
|
+
def inner(*names)
|
|
3696
|
+
res = nil
|
|
3697
|
+
names.each do |name|
|
|
3698
|
+
res = HDLRuby::High.top_user.
|
|
3699
|
+
add_inner(SignalI.new(name,
|
|
3700
|
+
TypeStruct.new(:"",:little,self),:inner))
|
|
3701
|
+
end
|
|
3702
|
+
return res
|
|
3703
|
+
end
|
|
3704
|
+
|
|
3705
|
+
# Declares high-level untyped constant signals by name and value given
|
|
3706
|
+
# by +hsh+ of the current type.
|
|
3707
|
+
#
|
|
3708
|
+
# Retuns the last declared constant.
|
|
3709
|
+
def constant(hsh)
|
|
3710
|
+
res = nil
|
|
3711
|
+
hsh.each do |name,value|
|
|
3712
|
+
res = HDLRuby::High.top_user.
|
|
3713
|
+
add_inner(SignalC.new(name,
|
|
3714
|
+
TypeStruct.new(:"",:little,self),:inner,value))
|
|
3715
|
+
end
|
|
3716
|
+
return res
|
|
3717
|
+
end
|
|
3718
|
+
end
|
|
3719
|
+
|
|
3720
|
+
|
|
3721
|
+
# Extends the Array class for conversion to a high-level expression.
|
|
3722
|
+
class ::Array
|
|
3723
|
+
include HArrow
|
|
3724
|
+
|
|
3725
|
+
# Converts to a new high-level expression.
|
|
3726
|
+
def to_expr
|
|
3727
|
+
# expr = Concat.new
|
|
3728
|
+
expr = Concat.new(TypeTuple.new(:"",:little,*self.map do |elem|
|
|
3729
|
+
elem.to_expr.type
|
|
3730
|
+
end))
|
|
3731
|
+
self.each {|elem| expr.add_expression(elem.to_expr) }
|
|
3732
|
+
expr
|
|
3733
|
+
end
|
|
3734
|
+
|
|
3735
|
+
# Converts to a new high-level reference.
|
|
3736
|
+
def to_ref
|
|
3737
|
+
# expr = RefConcat.new
|
|
3738
|
+
expr = RefConcat.new(TypeTuple.new(:"",:little,*self.map do |elem|
|
|
3739
|
+
elem.to_ref.type
|
|
3740
|
+
end))
|
|
3741
|
+
self.each {|elem| expr.add_ref(elem.to_ref) }
|
|
3742
|
+
expr
|
|
3743
|
+
end
|
|
3744
|
+
|
|
3745
|
+
# Converts to a new type.
|
|
3746
|
+
def to_type
|
|
3747
|
+
if self.size == 1 and
|
|
3748
|
+
( self[0].is_a?(Range) or self[0].respond_to?(:to_i) ) then
|
|
3749
|
+
# Vector type case
|
|
3750
|
+
return bit[*self]
|
|
3751
|
+
else
|
|
3752
|
+
# Tuple type case.
|
|
3753
|
+
return TypeTuple.new(:"",:little,*self)
|
|
3754
|
+
end
|
|
3755
|
+
end
|
|
3756
|
+
|
|
3757
|
+
# Declares a new type definition with +name+ equivalent to current one.
|
|
3758
|
+
def typedef(name)
|
|
3759
|
+
return self.to_type.typedef(name)
|
|
3760
|
+
end
|
|
3761
|
+
|
|
3762
|
+
# SignalI creation through the array take as type.
|
|
3763
|
+
|
|
3764
|
+
# Declares high-level input signals named +names+ of the current type.
|
|
3765
|
+
def input(*names)
|
|
3766
|
+
High.top_user.make_inputs(self.to_type,*names)
|
|
3767
|
+
end
|
|
3768
|
+
|
|
3769
|
+
# Declares high-level untyped output signals named +names+ of the
|
|
3770
|
+
# current type.
|
|
3771
|
+
def output(*names)
|
|
3772
|
+
High.top_user.make_outputs(self.to_type,*names)
|
|
3773
|
+
end
|
|
3774
|
+
|
|
3775
|
+
# Declares high-level untyped inout signals named +names+ of the
|
|
3776
|
+
# current type.
|
|
3777
|
+
def inout(*names)
|
|
3778
|
+
High.top_user.make_inouts(self.to_type,*names)
|
|
3779
|
+
end
|
|
3780
|
+
|
|
3781
|
+
# Declares high-level inner signals named +names+ of the
|
|
3782
|
+
# current type.
|
|
3783
|
+
def inner(*names)
|
|
3784
|
+
High.top_user.make_inners(self.to_type,*names)
|
|
3785
|
+
end
|
|
3786
|
+
|
|
3787
|
+
# Declares high-level inner constants named from +hsh+ with names
|
|
3788
|
+
# and corresponding values.
|
|
3789
|
+
def constant(hsh)
|
|
3790
|
+
High.top_user.make_constants(self.to_type,hsh)
|
|
3791
|
+
end
|
|
3792
|
+
|
|
3793
|
+
# Creates a hcase statement executing +ruby_block+ on the element of
|
|
3794
|
+
# the array selected by +value+
|
|
3795
|
+
def hcase(value,&ruby_block)
|
|
3796
|
+
High.cur_block.hcase(value)
|
|
3797
|
+
self.each.with_index do |elem,i|
|
|
3798
|
+
High.cur_block.hwhen(i) { ruby_block.call(elem) }
|
|
3799
|
+
end
|
|
3800
|
+
end
|
|
3801
|
+
|
|
3802
|
+
# Array construction shortcuts
|
|
3803
|
+
|
|
3804
|
+
# Create an array whose number of elements is given by the content
|
|
3805
|
+
# of the current array, filled by +obj+ objects.
|
|
3806
|
+
# If +obj+ is nil, +ruby_block+ is used instead for filling the array.
|
|
3807
|
+
def call(obj = nil, &ruby_block)
|
|
3808
|
+
unless self.size == 1 then
|
|
3809
|
+
raise AnyError, "Invalid array for call opertor."
|
|
3810
|
+
end
|
|
3811
|
+
number = self[0].to_i
|
|
3812
|
+
if obj then
|
|
3813
|
+
return Array.new(number,obj)
|
|
3814
|
+
else
|
|
3815
|
+
return Array.new(number,&ruby_block)
|
|
3816
|
+
end
|
|
3817
|
+
end
|
|
3818
|
+
|
|
3819
|
+
# Create an array of instances of system +name+, using +args+ as
|
|
3820
|
+
# arguments.
|
|
3821
|
+
#
|
|
3822
|
+
# NOTE: the array must have a single element that is an integer.
|
|
3823
|
+
def make(name,*args)
|
|
3824
|
+
# Check the array and get the number of elements.
|
|
3825
|
+
size = self[0]
|
|
3826
|
+
unless self.size == 1 and size.is_a?(::Integer)
|
|
3827
|
+
raise AnyError,
|
|
3828
|
+
"Invalid array for declaring a list of instances."
|
|
3829
|
+
end
|
|
3830
|
+
# Get the system to instantiate.
|
|
3831
|
+
systemT = High.space_call(name)
|
|
3832
|
+
# Get the name of the instance from the arguments.
|
|
3833
|
+
nameI = args.shift.to_s
|
|
3834
|
+
# Create the instances.
|
|
3835
|
+
instances = size.times.map do |i|
|
|
3836
|
+
systemT.instantiate((nameI + "[#{i}]").to_sym,*args)
|
|
3837
|
+
end
|
|
3838
|
+
nameI = nameI.to_sym
|
|
3839
|
+
# Add them to the top system
|
|
3840
|
+
High.space_top.user.add_groupI(nameI,*instances)
|
|
3841
|
+
# Register and return the result.
|
|
3842
|
+
High.space_reg(nameI) { High.space_top.user.get_groupI(nameI) }
|
|
3843
|
+
return High.space_top.user.get_groupI(nameI)
|
|
3844
|
+
end
|
|
3845
|
+
end
|
|
3846
|
+
|
|
3847
|
+
|
|
3848
|
+
# Extends the symbol class for auto declaration of input or output.
|
|
3849
|
+
class ::Symbol
|
|
3850
|
+
High = HDLRuby::High
|
|
3851
|
+
|
|
3852
|
+
# Tell if the expression can be converted to a value.
|
|
3853
|
+
def to_value?
|
|
3854
|
+
return true
|
|
3855
|
+
end
|
|
3856
|
+
|
|
3857
|
+
# Converts to a new value.
|
|
3858
|
+
#
|
|
3859
|
+
# Returns nil if no value can be obtained from it.
|
|
3860
|
+
def to_value
|
|
3861
|
+
str = self.to_s
|
|
3862
|
+
return nil if str[0] != "_" # Bit string are prefixed by "_"
|
|
3863
|
+
# Remove the "_" not needed any longer.
|
|
3864
|
+
str = str[1..-1]
|
|
3865
|
+
# Get and check the type
|
|
3866
|
+
type = str[0]
|
|
3867
|
+
if type == "0" or type == "1" or type == "z" or type == "Z" then
|
|
3868
|
+
# Default binary
|
|
3869
|
+
type = "b"
|
|
3870
|
+
else
|
|
3871
|
+
# Not a default type
|
|
3872
|
+
str = str[1..-1]
|
|
3873
|
+
end
|
|
3874
|
+
return nil if str.empty?
|
|
3875
|
+
return nil unless ["b","u","s"].include?(type)
|
|
3876
|
+
# Get the width if any.
|
|
3877
|
+
if str[0].match(/[0-9]/) then
|
|
3878
|
+
width = str.scan(/[0-9]*/)[0]
|
|
3879
|
+
else
|
|
3880
|
+
width = nil
|
|
3881
|
+
end
|
|
3882
|
+
# puts "width=#{width}"
|
|
3883
|
+
old_str = str # Save the string it this state since its first chars
|
|
3884
|
+
# can be erroneously considered as giving the width
|
|
3885
|
+
str = str[width.size..-1] if width
|
|
3886
|
+
# Get the base and the value
|
|
3887
|
+
base = str[0]
|
|
3888
|
+
# puts "base=#{base}\n"
|
|
3889
|
+
unless ["b", "o", "d", "h"].include?(base) then
|
|
3890
|
+
# No base found, default is bit
|
|
3891
|
+
base = "b"
|
|
3892
|
+
# And the width was actually a part of the value.
|
|
3893
|
+
value = old_str
|
|
3894
|
+
width = nil
|
|
3895
|
+
else
|
|
3896
|
+
# Get the value.
|
|
3897
|
+
value = str[1..-1]
|
|
3898
|
+
end
|
|
3899
|
+
# puts "value=#{value}"
|
|
3900
|
+
# Compute the bit width and the value
|
|
3901
|
+
case base
|
|
3902
|
+
when "b" then
|
|
3903
|
+
# base 2, compute the width
|
|
3904
|
+
width = width ? width.to_i : value.size
|
|
3905
|
+
# Check the value
|
|
3906
|
+
return nil unless value.match(/^[0-1zxZX]+$/)
|
|
3907
|
+
when "o" then
|
|
3908
|
+
# base 8, compute the width
|
|
3909
|
+
width = width ? width.to_i : value.size * 3
|
|
3910
|
+
# Check the value
|
|
3911
|
+
if value.match(/^[0-7xXzZ]+$/) then
|
|
3912
|
+
# 4-state value, conpute the correspondig bit string.
|
|
3913
|
+
value = value.each_char.map do |c|
|
|
3914
|
+
c = c.upcase
|
|
3915
|
+
if c == "X" or c.upcase == "Z" then
|
|
3916
|
+
c * 3
|
|
3917
|
+
else
|
|
3918
|
+
c.to_i(8).to_s(2).rjust(3,"0")
|
|
3919
|
+
end
|
|
3920
|
+
end.join
|
|
3921
|
+
else
|
|
3922
|
+
# Invalid value
|
|
3923
|
+
return nil
|
|
3924
|
+
end
|
|
3925
|
+
when "d" then
|
|
3926
|
+
# base 10, compute the width
|
|
3927
|
+
width = width ? width.to_i : value.to_i.to_s(2).size + 1
|
|
3928
|
+
# Check the value
|
|
3929
|
+
return nil unless value.match(/^[0-9]+$/)
|
|
3930
|
+
# Compute it (base 10 values cannot be 4-state!)
|
|
3931
|
+
value = value.to_i.to_s(2)
|
|
3932
|
+
when "h" then
|
|
3933
|
+
# base 16, compute the width
|
|
3934
|
+
width = width ? width.to_i : value.size * 4
|
|
3935
|
+
# Check the value
|
|
3936
|
+
if value.match(/^[0-9a-fA-FxXzZ]+$/) then
|
|
3937
|
+
# 4-state value, conpute the correspondig bit string.
|
|
3938
|
+
value = value.each_char.map do |c|
|
|
3939
|
+
c = c.upcase
|
|
3940
|
+
if c == "X" or c.upcase == "Z" then
|
|
3941
|
+
c * 4
|
|
3942
|
+
else
|
|
3943
|
+
c.to_i(16).to_s(2).rjust(4,"0")
|
|
3944
|
+
end
|
|
3945
|
+
end.join
|
|
3946
|
+
else
|
|
3947
|
+
# Invalid value
|
|
3948
|
+
return nil
|
|
3949
|
+
end
|
|
3950
|
+
else
|
|
3951
|
+
# Unknown base
|
|
3952
|
+
return nil
|
|
3953
|
+
end
|
|
3954
|
+
# Compute the type.
|
|
3955
|
+
case type
|
|
3956
|
+
when "b" then
|
|
3957
|
+
type = bit[width]
|
|
3958
|
+
when "u" then
|
|
3959
|
+
type = unsigned[width]
|
|
3960
|
+
when "s" then
|
|
3961
|
+
type = signed[width]
|
|
3962
|
+
else
|
|
3963
|
+
# Unknown type
|
|
3964
|
+
return nil
|
|
3965
|
+
end
|
|
3966
|
+
# puts "type.width=#{type.width}, value=#{value}"
|
|
3967
|
+
# Create and return the value.
|
|
3968
|
+
return Value.new(type,value)
|
|
3969
|
+
end
|
|
3970
|
+
|
|
3971
|
+
alias_method :to_expr, :to_value
|
|
3972
|
+
end
|
|
3973
|
+
|
|
3974
|
+
# Extends the range class to support to_low
|
|
3975
|
+
class ::Range
|
|
3976
|
+
# Convert the first and last to HDLRuby::Low
|
|
3977
|
+
def to_low
|
|
3978
|
+
first = self.first
|
|
3979
|
+
first = first.respond_to?(:to_low) ? first.to_low : first
|
|
3980
|
+
last = self.last
|
|
3981
|
+
last = last.respond_to?(:to_low) ? last.to_low : last
|
|
3982
|
+
return (first..last)
|
|
3983
|
+
end
|
|
3984
|
+
|
|
3985
|
+
# Iterates over the range as hardware.
|
|
3986
|
+
#
|
|
3987
|
+
# Returns an enumerator if no ruby block is given.
|
|
3988
|
+
def heach(&ruby_block)
|
|
3989
|
+
# No ruby block? Return an enumerator.
|
|
3990
|
+
return to_enum(:heach) unless ruby_block
|
|
3991
|
+
# Order the bounds to be able to iterate.
|
|
3992
|
+
first,last = self.first, self.last
|
|
3993
|
+
first,last = first > last ? [last,first] : [first,last]
|
|
3994
|
+
# Iterate.
|
|
3995
|
+
(first..last).each(&ruby_block)
|
|
3996
|
+
end
|
|
3997
|
+
end
|
|
3998
|
+
|
|
3999
|
+
|
|
4000
|
+
|
|
4001
|
+
|
|
4002
|
+
# Methods for managing the conversion to HDLRuby::Low
|
|
4003
|
+
|
|
4004
|
+
# Methods for generating uniq names in context
|
|
4005
|
+
|
|
4006
|
+
# The stack of names for creating new names without conflicts.
|
|
4007
|
+
NameStack = [ Set.new ]
|
|
4008
|
+
|
|
4009
|
+
# Pushes on the name stack.
|
|
4010
|
+
def self.names_push
|
|
4011
|
+
NameStack.push(Set.new)
|
|
4012
|
+
end
|
|
4013
|
+
|
|
4014
|
+
# Pops from the name stack.
|
|
4015
|
+
def self.names_pop
|
|
4016
|
+
NameStack.pop
|
|
4017
|
+
end
|
|
4018
|
+
|
|
4019
|
+
# Adds a +name+ to the top of the stack.
|
|
4020
|
+
def self.names_add(name)
|
|
4021
|
+
NameStack[-1].add(name.to_s)
|
|
4022
|
+
end
|
|
4023
|
+
|
|
4024
|
+
# Checks if a +name+ is present in the stack.
|
|
4025
|
+
def self.names_has?(name)
|
|
4026
|
+
NameStack.find do |names|
|
|
4027
|
+
names.include?(name)
|
|
4028
|
+
end
|
|
4029
|
+
end
|
|
4030
|
+
|
|
4031
|
+
# Creates and adds the new name from +base+ that do not collides with the
|
|
4032
|
+
# exisiting names.
|
|
4033
|
+
def self.names_create(base)
|
|
4034
|
+
base = base.to_s.clone
|
|
4035
|
+
# Create a non-conflicting name
|
|
4036
|
+
if self.names_has?(base) then
|
|
4037
|
+
count = 0
|
|
4038
|
+
while (self.names_has?(base + count.to_s)) do
|
|
4039
|
+
count += 1
|
|
4040
|
+
end
|
|
4041
|
+
base << count.to_s
|
|
4042
|
+
end
|
|
4043
|
+
# Add and return it
|
|
4044
|
+
self.names_add(base)
|
|
4045
|
+
# puts "created name: #{base}"
|
|
4046
|
+
return base.to_sym
|
|
4047
|
+
end
|
|
4048
|
+
|
|
4049
|
+
|
|
4050
|
+
|
|
4051
|
+
|
|
4052
|
+
# Standard vector types.
|
|
4053
|
+
Integer = TypeSigned.new(:integer)
|
|
4054
|
+
Natural = TypeUnsigned.new(:natural)
|
|
4055
|
+
Bignum = TypeSigned.new(:bignum,HDLRuby::Infinity..0)
|
|
4056
|
+
Real = TypeFloat.new(:float)
|
|
4057
|
+
|
|
4058
|
+
|
|
4059
|
+
end
|
|
4060
|
+
|
|
4061
|
+
# Tell if already configured.
|
|
4062
|
+
$HDLRuby_configure = false
|
|
4063
|
+
|
|
4064
|
+
# Enters in HDLRuby::High mode.
|
|
4065
|
+
def self.configure_high
|
|
4066
|
+
if $HDLRuby_configure then
|
|
4067
|
+
# Already configured.
|
|
4068
|
+
return
|
|
4069
|
+
end
|
|
4070
|
+
# Now HDLRuby will be configured.
|
|
4071
|
+
$HDLRuby_configure = true
|
|
4072
|
+
include HDLRuby::High
|
|
4073
|
+
class << self
|
|
4074
|
+
# For main, missing methods are looked for in the namespaces.
|
|
4075
|
+
def method_missing(m, *args, &ruby_block)
|
|
4076
|
+
# print "method_missing in class=#{self.class} with m=#{m}\n"
|
|
4077
|
+
# Is the missing method an immediate value?
|
|
4078
|
+
value = m.to_value
|
|
4079
|
+
return value if value and args.empty?
|
|
4080
|
+
# puts "Universe methods: #{Universe.namespace.methods}"
|
|
4081
|
+
# Not a value, but maybe it is in the namespaces
|
|
4082
|
+
if Namespaces[-1].respond_to?(m) then
|
|
4083
|
+
# Yes use it.
|
|
4084
|
+
Namespaces[-1].send(m,*args,&ruby_block)
|
|
4085
|
+
else
|
|
4086
|
+
# puts "here: #{m}"
|
|
4087
|
+
# No, true error
|
|
4088
|
+
raise NotDefinedError, "undefined HDLRuby construct, local variable or method `#{m}'."
|
|
4089
|
+
end
|
|
4090
|
+
end
|
|
4091
|
+
end
|
|
4092
|
+
|
|
4093
|
+
# Generate the standard signals
|
|
4094
|
+
$clk = Universe.scope.inner :__universe__clk__
|
|
4095
|
+
$rst = Universe.scope.inner :__universe__rst__
|
|
4096
|
+
|
|
4097
|
+
|
|
4098
|
+
|
|
4099
|
+
# Tells HDLRuby has finised booting.
|
|
4100
|
+
def self.booting?
|
|
4101
|
+
false
|
|
4102
|
+
end
|
|
4103
|
+
end
|