HDLRuby 2.7.5 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -133,6 +133,8 @@ module HDLRuby::High
133
133
  module Hmissing
134
134
  High = HDLRuby::High
135
135
 
136
+ NAMES = { }
137
+
136
138
  # Missing methods may be immediate values, if not, they are looked up
137
139
  # in the upper level of the namespace if any.
138
140
  def method_missing(m, *args, &ruby_block)
@@ -140,6 +142,20 @@ module HDLRuby::High
140
142
  # Is the missing method an immediate value?
141
143
  value = m.to_value
142
144
  return value if value and args.empty?
145
+ # Or is it a uniq name generator?
146
+ if (m[-1] == '?') then
147
+ # Yes
148
+ m = m[0..-2]
149
+ return NAMES[m] = HDLRuby.uniq_name(m)
150
+ end
151
+ # Is in a previous uniq name?
152
+ if (m[-1] == '!') then
153
+ pm = m[0..-2]
154
+ if NAMES.key?(pm) then
155
+ # Yes, returns the current corresponding uniq name.
156
+ return self.send(NAMES[pm],*args,&ruby_block)
157
+ end
158
+ end
143
159
  # No, is there an upper namespace, i.e. is the current object
144
160
  # present in the space?
145
161
  if High.space_index(self) then
@@ -328,6 +344,7 @@ module HDLRuby::High
328
344
  def initialize(name, *mixins, &ruby_block)
329
345
  # Initialize the system type structure.
330
346
  super(name,Scope.new(name,self))
347
+ # puts "new systemT=#{self}"
331
348
 
332
349
  # Initialize the set of extensions to transmit to the instances'
333
350
  # eigen class
@@ -357,6 +374,28 @@ module HDLRuby::High
357
374
  make_instantiater(name,SystemI,&ruby_block)
358
375
  end
359
376
 
377
+
378
+ # Tell if the current system is a descedent of +system+
379
+ def of?(system)
380
+ # Maybe self is system.
381
+ if (self == system) then
382
+ # Yes, consider it is adescendent of system.
383
+ return true
384
+ else
385
+ # Look into the generators.
386
+ @generators.each do |generator|
387
+ return true if generator.of?(system)
388
+ end
389
+ # Look into the included systems.
390
+ @to_includes.each do |included|
391
+ return true if included.of?(system)
392
+ end
393
+ end
394
+ # Not found.
395
+ return false
396
+ end
397
+
398
+
360
399
  # Converts to a namespace user.
361
400
  def to_user
362
401
  # Returns the scope.
@@ -555,6 +594,7 @@ module HDLRuby::High
555
594
 
556
595
  # Sets the generators of the expanded result.
557
596
  expanded.add_generator(self)
597
+ # puts "expanded=#{expanded}"
558
598
  @to_includes.each { |system| expanded.add_generator(system) }
559
599
  # Also for the previously includeds. */
560
600
  self.scope.each_included.each { |system| expanded.add_generator(system) }
@@ -618,9 +658,8 @@ module HDLRuby::High
618
658
 
619
659
  # Create the instance and sets its eigen system to +eigen+.
620
660
  instance = @instance_class.new(i_name,eigen)
661
+ # puts "instance=#{instance}"
621
662
  eigen.eigenize(instance)
622
- # puts "instance interface=#{instance.each_signal.to_a.size}"
623
- # puts "eigen interface=#{eigen.each_signal.to_a.size}"
624
663
 
625
664
  # Extend the instance.
626
665
  instance.eigen_extend(@singleton_instanceO)
@@ -832,8 +871,7 @@ module HDLRuby::High
832
871
  # Initialize the set of included systems.
833
872
  @includes = {}
834
873
 
835
- # Builds the scope if a ruby block is provided
836
- # (which means the scope is not the top of a system).
874
+ # Builds the scope if a ruby block is provided.
837
875
  self.build(&ruby_block) if block_given?
838
876
  end
839
877
 
@@ -944,18 +982,20 @@ module HDLRuby::High
944
982
  # Set the namespace for buidling the scope.
945
983
  High.space_push(@namespace)
946
984
  # Build the scope.
947
- # @return_value = High.top_user.instance_eval(&ruby_block)
948
- res = High.top_user.instance_eval(&ruby_block)
985
+ @return_value = High.top_user.instance_eval(&ruby_block)
986
+ # res = High.top_user.instance_eval(&ruby_block)
949
987
  High.space_pop
950
- # Now gain access to the result within the sub scope.
951
- if (res.is_a?(HRef)) then
952
- @return_value = res.type.inner(HDLRuby.uniq_name)
953
- High.space_push(@namespace)
954
- @return_value <= res
955
- High.space_pop
956
- else
957
- @return_value = res
958
- end
988
+ # # Now gain access to the result within the sub scope.
989
+ # # if (res.is_a?(HRef)) then
990
+ # if (res.is_a?(HExpression)) then
991
+ # High.space_push(@namespace)
992
+ # @return_value = res.type.inner(HDLRuby.uniq_name)
993
+ # @return_value <= res
994
+ # High.space_pop
995
+ # @return_value = RefObject.new(self,@return_value)
996
+ # else
997
+ # @return_value = res
998
+ # end
959
999
  # This will be the return value.
960
1000
  @return_value
961
1001
  end
@@ -1087,10 +1127,12 @@ module HDLRuby::High
1087
1127
  # Declares a sub scope with possible +name+ and built from +ruby_block+.
1088
1128
  def sub(name = :"", &ruby_block)
1089
1129
  # Creates the new scope.
1090
- scope = Scope.new(name,&ruby_block)
1091
- # puts "new scope=#{scope}"
1130
+ # scope = Scope.new(name,&ruby_block)
1131
+ scope = Scope.new(name)
1092
1132
  # Add it
1093
1133
  self.add_scope(scope)
1134
+ # Build it.
1135
+ scope.build(&ruby_block)
1094
1136
  # puts "self=#{self}"
1095
1137
  # puts "self scopes=#{self.each_scope.to_a.join(",")}"
1096
1138
  # Use its return value
@@ -1965,9 +2007,6 @@ module HDLRuby::High
1965
2007
  &ruby_block)
1966
2008
  # ruby_block.call(*args)
1967
2009
  end
1968
- # sub do
1969
- # ruby_block.call(*args,*other_block)
1970
- # end
1971
2010
  end
1972
2011
  else
1973
2012
  define_method(name.to_sym) do |*args,&other_block|
@@ -1975,10 +2014,8 @@ module HDLRuby::High
1975
2014
  sub(HDLRuby.uniq_name(name)) do
1976
2015
  HDLRuby::High.top_user.instance_exec(*args,*other_block,
1977
2016
  &ruby_block)
2017
+ # ruby_block.call(*args,*other_block)
1978
2018
  end
1979
- # sub do
1980
- # ruby_block.call(*args,*other_block)
1981
- # end
1982
2019
  end
1983
2020
  end
1984
2021
  end
@@ -2105,6 +2142,54 @@ module HDLRuby::High
2105
2142
  self.eigen_extend(@systemT.public_namespace)
2106
2143
  end
2107
2144
 
2145
+ # Adds alternative system +systemT+
2146
+ def choice(configuration = {})
2147
+ # Process the argument.
2148
+ configuration.each do |k,v|
2149
+ k = k.to_sym
2150
+ unless v.is_a?(SystemT) then
2151
+ raise "Invalid class for a system type: #{v.class}"
2152
+ end
2153
+ # Create an eigen system.
2154
+ eigen = v.instantiate(HDLRuby.uniq_name(self.name)).systemT
2155
+ # Ensure its interface corresponds.
2156
+ my_signals = self.each_signal.to_a
2157
+ if (eigen.each_signal.with_index.find { |sig,i|
2158
+ !sig.eql?(my_signals[i])
2159
+ }) then
2160
+ raise "Invalid system for configuration: #{systemT.name}."
2161
+ end
2162
+ # Add it.
2163
+ # At the HDLRuby::High level
2164
+ @choices = { self.name => self.systemT } unless @choices
2165
+ @choices[k] = eigen
2166
+ # At the HDLRuby::Low level
2167
+ self.add_systemT(eigen)
2168
+ end
2169
+ end
2170
+
2171
+ # (Re)Configuration of system instance to systemT designated by +sys+.
2172
+ # +sys+ may be the index or the name of the configuration, the first
2173
+ # configuration being named by the systemI name.
2174
+ def configure(sys)
2175
+ if sys.respond_to?(:to_i) then
2176
+ # The argument is an index.
2177
+ # Create the (re)configuration node.
2178
+ High.top_user.add_statement(
2179
+ Configure.new(RefObject.new(RefThis.new,self),sys.to_i))
2180
+ else
2181
+ # The argument is a name (should be).
2182
+ # Get the index corresponding to the name.
2183
+ num = @choices.find_index { |k,_| k == sys.to_sym }
2184
+ unless num then
2185
+ raise "Invalid name for configuration: #{sys.to_s}"
2186
+ end
2187
+ # Create the (re)configuration node.
2188
+ High.top_user.add_statement(
2189
+ Configure.new(RefObject.new(RefThis.new,self),num))
2190
+ end
2191
+ end
2192
+
2108
2193
  # include Hmissing
2109
2194
 
2110
2195
  # Missing methods are looked for in the public namespace of the
@@ -2141,8 +2226,11 @@ module HDLRuby::High
2141
2226
  # systemIL.properties[:low2high] = self.hdr_id
2142
2227
  # self.properties[:high2low] = systemIL
2143
2228
  # Adds the other systemTs.
2144
- self.each_systemT do |systemT|
2145
- systemIL.add_systemT(systemT.to_low) unless systemT == self.systemT
2229
+ self.each_systemT do |systemTc|
2230
+ if systemTc != self.systemT
2231
+ systemTcL = systemTc.to_low
2232
+ systemIL.add_systemT(systemTcL)
2233
+ end
2146
2234
  end
2147
2235
  return systemIL
2148
2236
  end
@@ -2419,6 +2507,18 @@ module HDLRuby::High
2419
2507
  end
2420
2508
  end
2421
2509
 
2510
+ ##
2511
+ # Describes a timed terminate statement: not synthesizable!
2512
+ class TimeTerminate < Low::TimeTerminate
2513
+ include HStatement
2514
+
2515
+ # Converts the repeat statement to HDLRuby::Low.
2516
+ def to_low
2517
+ return HDLRuby::Low::TimeTerminate.new
2518
+ end
2519
+ end
2520
+
2521
+
2422
2522
 
2423
2523
  ##
2424
2524
  # Module giving high-level expression properties
@@ -2671,6 +2771,20 @@ module HDLRuby::High
2671
2771
  #
2672
2772
  # NOTE: +rng+ can be a single expression in which case it is an index.
2673
2773
  def [](rng)
2774
+ if rng.is_a?(::Range) then
2775
+ first = rng.first
2776
+ if (first.is_a?(::Integer)) then
2777
+ first = self.type.size+first if first < 0
2778
+ end
2779
+ last = rng.last
2780
+ if (last.is_a?(::Integer)) then
2781
+ last = self.type.size+last if last < 0
2782
+ end
2783
+ rng = first..last
2784
+ end
2785
+ if rng.is_a?(::Integer) && rng < 0 then
2786
+ rng = self.type.size+rng
2787
+ end
2674
2788
  if rng.respond_to?(:to_expr) then
2675
2789
  # Number range: convert it to an expression.
2676
2790
  rng = rng.to_expr
@@ -3007,6 +3121,7 @@ module HDLRuby::High
3007
3121
 
3008
3122
  # Creates a new reference from a +base+ reference and named +object+.
3009
3123
  def initialize(base,object)
3124
+ # puts "New RefObjet with base=#{base}, object=#{object.name}"
3010
3125
  if object.respond_to?(:type) then
3011
3126
  # Typed object, so typed reference.
3012
3127
  super(object.type)
@@ -3043,7 +3158,7 @@ module HDLRuby::High
3043
3158
 
3044
3159
  # Converts the name reference to a HDLRuby::Low::RefName.
3045
3160
  def to_low
3046
- # puts "to_low with base=#{@base} @object=#{@object}"
3161
+ # puts "to_low with base=#{@base} @object=#{@object.name}"
3047
3162
  refNameL = HDLRuby::Low::RefName.new(self.type.to_low,
3048
3163
  @base.to_ref.to_low,@object.name)
3049
3164
  # # For debugging: set the source high object
@@ -3340,6 +3455,27 @@ module HDLRuby::High
3340
3455
  end
3341
3456
 
3342
3457
 
3458
+ ##
3459
+ # Describes a systemI (re)configure statement: not synthesizable!
3460
+ class Configure < Low::Configure
3461
+ High = HDLRuby::High
3462
+
3463
+ include HStatement
3464
+
3465
+ # Creates a new (re)configure statement for system instance refered
3466
+ # by +ref+ with system number +num+.
3467
+ def initialize(ref,num)
3468
+ super(ref,num)
3469
+ end
3470
+
3471
+ # Converts the connection to HDLRuby::Low.
3472
+ def to_low
3473
+ return HDLRuby::Low::Configure.new(self.ref.to_low, self.index)
3474
+ end
3475
+
3476
+ end
3477
+
3478
+
3343
3479
  ##
3344
3480
  # Describes a connection.
3345
3481
  class Connection < Low::Connection
@@ -3608,6 +3744,15 @@ module HDLRuby::High
3608
3744
  High.space_push(@namespace)
3609
3745
  @return_value = High.top_user.instance_eval(&ruby_block)
3610
3746
  High.space_pop
3747
+ # if @return_value.is_a?(HExpression) then
3748
+ # res = @return_value
3749
+ # High.space_push(@namespace)
3750
+ # @return_value = res.type.inner(HDLRuby.uniq_name)
3751
+ # puts "@return_value name=#{@return_value.name}"
3752
+ # @return_value <= res
3753
+ # High.space_pop
3754
+ # @return_value = RefObject.new(self,@return_value)
3755
+ # end
3611
3756
  @return_value
3612
3757
  end
3613
3758
 
@@ -3764,6 +3909,11 @@ module HDLRuby::High
3764
3909
  def hprint(*args)
3765
3910
  self.add_statement(Print.new(*args))
3766
3911
  end
3912
+
3913
+ # Terminate the simulation.
3914
+ def terminate
3915
+ self.add_statement(TimeTerminate.new)
3916
+ end
3767
3917
  end
3768
3918
 
3769
3919
 
@@ -3797,7 +3947,7 @@ module HDLRuby::High
3797
3947
  # Converts the block to HDLRuby::Low.
3798
3948
  def to_low
3799
3949
  # Create the resulting block
3800
- blockL = HDLRuby::Low::Block.new(self.mode)
3950
+ blockL = HDLRuby::Low::Block.new(self.mode,self.name)
3801
3951
  # # For debugging: set the source high object
3802
3952
  # blockL.properties[:low2high] = self.hdr_id
3803
3953
  # self.properties[:high2low] = blockL
@@ -164,6 +164,21 @@ module HDLRuby::Low
164
164
  end
165
165
 
166
166
 
167
+ # Handling the (re)configuration.
168
+
169
+ # Gets the configuration wrapper if any.
170
+ def wrapper
171
+ return defined? @wrapper ? @wrapper : nil
172
+ end
173
+
174
+ # Sets the configuration wrapper to +systemT+.
175
+ def wrapper=(systemT)
176
+ unless systemT.is_a?(SystemT) then
177
+ raise "Invalid class for a wrapper system type: #{systemT}."
178
+ end
179
+ @wrapper = systemT
180
+ end
181
+
167
182
 
168
183
  # Handling the signals.
169
184
 
@@ -432,6 +447,27 @@ module HDLRuby::Low
432
447
  end
433
448
  end
434
449
  end
450
+
451
+ # Iterates over the systemT deeply if any in order of reference
452
+ # to ensure the refered elements are processed first.
453
+ #
454
+ # Returns an enumerator if no ruby block is given.
455
+ def each_systemT_deep_ref(&ruby_block)
456
+ # No ruby block? Return an enumerator.
457
+ return to_enum(:each_systemT_deep_ref) unless ruby_block
458
+ # A ruby block?
459
+ # Recurse on the systemT accessible through the instances.
460
+ self.scope.each_scope_deep do |scope|
461
+ scope.each_systemI do |systemI|
462
+ # systemI.systemT.each_systemT_deep(&ruby_block)
463
+ systemI.each_systemT do |systemT|
464
+ systemT.each_systemT_deep_ref(&ruby_block)
465
+ end
466
+ end
467
+ end
468
+ # Finally apply it to current.
469
+ ruby_block.call(self)
470
+ end
435
471
  end
436
472
 
437
473
 
@@ -2500,8 +2536,8 @@ module HDLRuby::Low
2500
2536
  # NOTE: an instance can actually represented muliple layers
2501
2537
  # of systems, the first one being the one actually instantiated
2502
2538
  # in the final RTL code.
2503
- # This layring can be used for describing software or partial
2504
- # reconfiguration.
2539
+ # This layering can be used for describing software or partial
2540
+ # (re)configuration.
2505
2541
  class SystemI
2506
2542
 
2507
2543
  include Hparent
@@ -2564,13 +2600,16 @@ module HDLRuby::Low
2564
2600
  @name = name.to_sym
2565
2601
  end
2566
2602
 
2567
- ## Adds a system layer.
2603
+ ## Adds a system configuration.
2568
2604
  def add_systemT(systemT)
2569
2605
  # puts "add_systemT #{systemT.name} to systemI #{self.name}"
2570
2606
  # Check and add the systemT.
2571
2607
  if !systemT.is_a?(SystemT) then
2572
2608
  raise AnyError, "Invalid class for a system type: #{systemT.class}"
2573
2609
  end
2610
+ # Set the base configuration of the added system.
2611
+ systemT.wrapper = self.systemT
2612
+ # Add it.
2574
2613
  @systemTs << systemT
2575
2614
  end
2576
2615
 
@@ -3781,6 +3820,93 @@ module HDLRuby::Low
3781
3820
  end
3782
3821
  end
3783
3822
  end
3823
+ end
3824
+
3825
+
3826
+ ##
3827
+ # Describes a system instance (re)configuration statement: not synthesizable!
3828
+ class Configure < Statement
3829
+
3830
+ # attr_reader :systemI, :systemT, :index
3831
+ attr_reader :ref, :index
3832
+
3833
+ # Creates a new (re)configure statement of system instance refered by
3834
+ # +ref+ with system number +index+
3835
+ def initialize(ref,index)
3836
+ super()
3837
+ # Process the arguments.
3838
+ index = index.to_i
3839
+ unless ref.is_a?(Ref) then
3840
+ raise "Invalid class for a reference: #{ref.class}."
3841
+ end
3842
+ # Sets the arguments.
3843
+ @ref = ref
3844
+ ref.parent = self
3845
+ @index = index
3846
+ # @systemT = systemI.each_systemT.to_a[index]
3847
+ # # Check the systemT is valid.
3848
+ # unless @systemT then
3849
+ # raise "Invalid configuration index: #{index}."
3850
+ # end
3851
+ end
3852
+
3853
+ # Comparison for hash: structural comparison.
3854
+ def eql?(obj)
3855
+ return false unless obj.is_a?(Configure)
3856
+ return false unless @ref.eql?(obj.ref)
3857
+ return false unless @index.eql?(obj.index)
3858
+ return true
3859
+ end
3860
+
3861
+ # Iterates over each object deeply.
3862
+ #
3863
+ # Returns an enumerator if no ruby block is given.
3864
+ def each_deep(&ruby_block)
3865
+ # No ruby block? Return an enumerator.
3866
+ return to_enum(:each_deep) unless ruby_block
3867
+ # A ruby block? First apply it to current.
3868
+ ruby_block.call(self)
3869
+ # Then apply on the reference.
3870
+ @ref.each_deep(&ruby_block)
3871
+ end
3872
+
3873
+ # Hash function.
3874
+ def hash
3875
+ return (@ref.hash + @index.hash).hash
3876
+ end
3877
+
3878
+ # Clones (deeply)
3879
+ def clone
3880
+ return Configure.new(@ref.clone,@index)
3881
+ end
3882
+
3883
+ # Iterates over the nodes deeply if any.
3884
+ def each_node_deep(&ruby_block)
3885
+ # No ruby block? Return an enumerator.
3886
+ return to_enum(:each_node_deep) unless ruby_block
3887
+ # A ruby block? First apply it to current.
3888
+ ruby_block.call(self)
3889
+ # And recurse on the reference.
3890
+ @ref.each_node_deep(&ruby_block)
3891
+ end
3892
+
3893
+ # Iterates over all the blocks contained in the current block.
3894
+ def each_block_deep(&ruby_block)
3895
+ # No ruby block? Return an enumerator.
3896
+ return to_enum(:each_block_deep) unless ruby_block
3897
+ # A ruby block?
3898
+ # Nothing more to do anyway.
3899
+ end
3900
+
3901
+ # Iterates over all the statements contained in the current block.
3902
+ def each_statement_deep(&ruby_block)
3903
+ # No ruby block? Return an enumerator.
3904
+ return to_enum(:each_statement_deep) unless ruby_block
3905
+ # A ruby block?
3906
+ # Apply it on self.
3907
+ ruby_block.call(self)
3908
+ # And that's all.
3909
+ end
3784
3910
 
3785
3911
  end
3786
3912
 
@@ -3989,6 +4115,82 @@ module HDLRuby::Low
3989
4115
  end
3990
4116
 
3991
4117
 
4118
+ ##
4119
+ # Describes a timed terminate statement: not synthesizable!
4120
+ class TimeTerminate < Statement
4121
+
4122
+ # Creates a new timed terminate statement that terminate execution.
4123
+ def initialize
4124
+ super()
4125
+ end
4126
+
4127
+ # Iterates over each object deeply.
4128
+ #
4129
+ # Returns an enumerator if no ruby block is given.
4130
+ def each_deep(&ruby_block)
4131
+ # No ruby block? Return an enumerator.
4132
+ return to_enum(:each_deep) unless ruby_block
4133
+ # A ruby block? First apply it to current.
4134
+ ruby_block.call(self)
4135
+ # And that's all.
4136
+ end
4137
+
4138
+ # Iterates over all the nodes.
4139
+ def each_node(&ruby_block)
4140
+ # No ruby block? Return an enumerator.
4141
+ return to_enum(:each_node) unless ruby_block
4142
+ # A ruby block?
4143
+ # Nothing to do anyway.
4144
+ end
4145
+
4146
+ # Iterates over all the nodes deeply.
4147
+ def each_node_deep(&ruby_block)
4148
+ # No ruby block? Return an enumerator.
4149
+ return to_enum(:each_node_deep) unless ruby_block
4150
+ # A ruby block?
4151
+ # Apply of current node.
4152
+ ruby_block.call(self)
4153
+ # And that's all.
4154
+ end
4155
+
4156
+ # Iterates over all the statements deeply.
4157
+ def each_statement_deep(&ruby_block)
4158
+ # No ruby block? Return an enumerator.
4159
+ return to_enum(:each_statement_deep) unless ruby_block
4160
+ # A ruby block?
4161
+ # Apply of current node.
4162
+ ruby_block.call(self)
4163
+ # And that's all.
4164
+ end
4165
+
4166
+ # Iterates over all the blocks contained in the current block.
4167
+ def each_block_deep(&ruby_block)
4168
+ # No ruby block? Return an enumerator.
4169
+ return to_enum(:each_block_deep) unless ruby_block
4170
+ # A ruby block?
4171
+ # Nothing to do anyway.
4172
+ end
4173
+
4174
+ # Comparison for hash: structural comparison.
4175
+ def eql?(obj)
4176
+ return false unless obj.is_a?(TimeTerminate)
4177
+ return true
4178
+ end
4179
+
4180
+ # Hash function.
4181
+ def hash
4182
+ return TimeTerminate.hash
4183
+ end
4184
+
4185
+ # Clones the TimeRepeat (deeply)
4186
+ def clone
4187
+ return TimeTerminate.new
4188
+ end
4189
+ end
4190
+
4191
+
4192
+
4193
+
3992
4194
  ##
3993
4195
  # Describes a block.
3994
4196
  class Block < Statement
@@ -4058,6 +4260,7 @@ module HDLRuby::Low
4058
4260
 
4059
4261
  # Adds inner signal +signal+.
4060
4262
  def add_inner(signal)
4263
+ # puts "add inner=#{signal.name} in block=#{self}"
4061
4264
  # Check and add the signal.
4062
4265
  unless signal.is_a?(SignalI)
4063
4266
  raise AnyError,
@@ -4087,6 +4290,7 @@ module HDLRuby::Low
4087
4290
 
4088
4291
  ## Gets an inner signal by +name+.
4089
4292
  def get_inner(name)
4293
+ # puts "name=#{name}, inners=#{@inners.each_key.to_a}"
4090
4294
  return @inners[name.to_sym]
4091
4295
  end
4092
4296
  alias_method :get_signal, :get_inner