lib/HDLRuby/hruby_rsim.rb in HDLRuby-2.11.11 vs lib/HDLRuby/hruby_rsim.rb in HDLRuby-2.11.12

- old
+ new

@@ -64,11 +64,10 @@ # end # end @sig_active.each do |sig| next if (sig.c_value.eql?(sig.f_value)) # next if (sig.c_value.to_vstr == sig.f_value.to_vstr) - # puts "sig.c_value: #{sig.c_value.to_vstr}, sig.f_value=#{sig.f_value.to_vstr}" sig.each_anyedge { |beh| @sig_exec << beh } if (sig.c_value.zero?) then # puts "sig.c_value=#{sig.c_value.content}" sig.each_posedge { |beh| @sig_exec << beh } elsif (!sig.c_value.zero?) then @@ -106,10 +105,12 @@ def sim(simout) HDLRuby.show "Initializing Ruby-level simulator..." HDLRuby.show "#{Time.now}#{show_mem}" # Merge the included. self.merge_included! + # Process par in seq. + self.par_in_seq2seq! # Initializes the time. @time = 0 # Initializes the time and signals execution buffers. @tim_exec = [] @sig_exec = [] @@ -129,10 +130,13 @@ # Initialize the untimed objects. self.init_untimeds # puts "End of init_untimed." + # Maybe there is nothing to execute. + return if @total_timed_behaviors == 0 + # Is there more than one timed behavior. if @total_timed_behaviors <= 1 then # No, no need of multithreading. @multithread = false # Simple execute the block of the behavior. @@ -488,10 +492,16 @@ # Access the current and future value. attr_accessor :c_value, :f_value ## Initialize the simulation for +systemT+ def init_sim(systemT) + # Recurse on the sub signals if any. + if self.each_signal.any? then + self.each_signal {|sig| sig.init_sim(systemT) } + return + end + # No sub signal, really initialize the current signal. if self.value then @c_value = self.value.execute(:par).to_value @f_value = @c_value.to_value # puts "init signal value at=#{@c_value.to_bstr}" # The signal is considered active. @@ -504,22 +514,31 @@ end end ## Adds behavior +beh+ activated on a positive edge of the signal. def add_posedge(beh) + # Recurse on the sub signals. + self.each_signal {|sig| sig.add_posedge(beh) } + # Apply on current signal. @posedge_behaviors ||= [] @posedge_behaviors << beh end ## Adds behavior +beh+ activated on a negative edge of the signal. def add_negedge(beh) + # Recurse on the sub signals. + self.each_signal {|sig| sig.add_negedge(beh) } + # Apply on current signal. @negedge_behaviors ||= [] @negedge_behaviors << beh end ## Adds behavior +beh+ activated on a any edge of the signal. def add_anyedge(beh) + # Recurse on the sub signals. + self.each_signal {|sig| sig.add_anyedge(beh) } + # Apply on current signal. @anyedge_behaviors ||= [] @anyedge_behaviors << beh end ## Iterates over the behaviors activated on a positive edge. @@ -541,13 +560,13 @@ end ## Execute the expression. def execute(mode) - # puts "Executing signal=#{self.fullname}" - # return mode == :par ? self.c_value : self.f_value + # puts "Executing signal=#{self.fullname} in mode=#{mode} with c_value=#{self.c_value} and f_value=#{self.f_value}" return @mode == :seq ? self.f_value : self.c_value + # return @mode == :seq || mode == :seq ? self.f_value : self.c_value end ## Assigns +value+ the the reference. def assign(mode,value) # Set the next value. @@ -647,14 +666,16 @@ # Decribes a transmission statement. class Transmit ## Initialize the simulation for system +systemT+. def init_sim(systemT) self.left.init_sim(systemT) + self.right.init_sim(systemT) end ## Executes the statement. def execute(mode) + # puts "execute Transmit in mode=#{mode} for left=#{self.left.object.name}" self.left.assign(mode,self.right.execute(mode)) end end @@ -668,10 +689,11 @@ self.no.init_sim(systemT) if self.no end ## Executes the statement. def execute(mode) + # puts "execute hif with mode=#{mode}" # Check the main condition. if !(self.condition.execute(mode).zero?) then self.yes.execute(mode) else # Check the other conditions (elsif) @@ -846,20 +868,42 @@ self.each_statement { |stmnt| stmnt.init_sim(systemT) } end ## Executes the statement. def execute(mode) + # puts "execute block of mode=#{self.mode}" self.each_statement { |stmnt| stmnt.execute(self.mode) } end ## Returns the name of the signal with its hierarchy. def fullname @fullname ||= self.parent.fullname + ":" + self.name.to_s return @fullname end end + class If + ## Returns the name of the signal with its hierarchy. + def fullname + return self.parent.fullname + end + end + + class When + ## Returns the name of the signal with its hierarchy. + def fullname + return self.parent.fullname + end + end + + class Case + ## Returns the name of the signal with its hierarchy. + def fullname + return self.parent.fullname + end + end + # Describes a timed block. # # NOTE: # * this is the only kind of block that can include time statements. # * this kind of block is not synthesizable! @@ -887,12 +931,13 @@ ## Initialize the simulation for system +systemT+. def init_sim(systemT) # Add the connection to the list of untimed objets. systemT.add_untimed(self) - # Recurse on the left. + # Recurse on the left and right. self.left.init_sim(systemT) + self.right.init_sim(systemT) # Process the sensitivity list. # Is it a clocked behavior? events = [] # Generate the events list from the right values. # First get the references. @@ -912,11 +957,11 @@ refs.each {|ref| ref.object.add_anyedge(self) } end ## Executes the statement. def execute(mode) - # puts "connection = #{self}" if self.left.is_a?(RefObject) && self.left.object.name.to_s.include?("xnor") + # puts "connection left=#{left} right=#{right}" self.left.assign(mode,self.right.execute(mode)) end end @@ -924,10 +969,15 @@ ## # Describes an expression. # # NOTE: this is an abstract class which is not to be used directly. class Expression + ## Initialize the simulation for system +systemT+. + def init_sim(systemT) + # By default: do nothing. + end + ## Executes the expression in +mode+ (:blocking or :nonblocking) # NOTE: to be overrided. def execute(mode) raise "execute must be implemented in class #{self.class}" end @@ -935,10 +985,15 @@ ## # Describes a value. class Value + ## Initialize the simulation for system +systemT+. + def init_sim(systemT) + # Nothing to do. + end + # include Vprocess ## Executes the expression. def execute(mode) return self @@ -947,22 +1002,29 @@ ## # Describes a cast. class Cast + ## Initialize the simulation for system +systemT+. + def init_sim(systemT) + # Recurse on the child. + self.child.init_sim(systemT) + end + ## Executes the expression. def execute(mode) - # Recurse on the child. - # res = tocast.execute(mode) + # puts "child=#{self.child}" + # puts "child object=#{self.child.object}(#{self.child.object.name})" if self.child.is_a?(RefObject) # Shall we reverse the content of a concat. if self.child.is_a?(Concat) && self.type.direction != self.child.type.direction then # Yes, do it. res = self.child.execute(mode,:reverse) else res = self.child.execute(mode) end + # puts "res=#{res}" # Cast it. res = res.cast(self.type,true) # Returns the result. return res end @@ -979,10 +1041,16 @@ ## # Describes an unary operation. class Unary + ## Initialize the simulation for system +systemT+. + def init_sim(systemT) + # Recurse on the child. + self.child.init_sim(systemT) + end + ## Execute the expression. def execute(mode) # puts "Unary with operator=#{self.operator}" # Recurse on the child. tmp = self.child.execute(mode) @@ -994,10 +1062,17 @@ ## # Describes an binary operation. class Binary + ## Initialize the simulation for system +systemT+. + def init_sim(systemT) + # Recurse on the children. + self.left.init_sim(systemT) + self.right.init_sim(systemT) + end + ## Execute the expression. def execute(mode) # Recurse on the children. tmpl = self.left.execute(mode) tmpr = self.right.execute(mode) @@ -1010,10 +1085,17 @@ ## # Describes a selection operation (generalization of the ternary operator). # # NOTE: choice is using the value of +select+ as an index. class Select + ## Initialize the simulation for system +systemT+. + def init_sim(systemT) + # Recurse on the children. + self.select.init_sim(systemT) + self.each_choice { |choice| choice.init_sim(systemT) } + end + ## Execute the expression. def execute(mode) unless @mask then # Need to initialize the execution of the select. width = (@choices.size-1).width @@ -1031,10 +1113,16 @@ ## # Describes a concatenation expression. class Concat + ## Initialize the simulation for system +systemT+. + def init_sim(systemT) + # Recurse on the children. + self.each_expression { |expr| expr.init_sim(systemT) } + end + ## Execute the expression. def execute(mode, reverse=false) # Recurse on the children. tmpe = self.each_expression.map { |expr| expr.execute(mode) } # Ensure the order of the elements matches the type. @@ -1216,10 +1304,47 @@ ## # Describes a high-level object reference: no low-level equivalent! class RefObject ## Initialize the simulation for system +systemT+. def init_sim(systemT) + # puts "init_sim for RefObject=#{self}" @sim = systemT + + # Modify the exectute and assign methods if the object has + # sub signals (for faster execution). + if self.object.each_signal.any? then + ## Execute the expression. + self.define_singleton_method(:execute) do |mode| + # Recurse on the children. + iter = self.object.each_signal + iter = iter.reverse_each unless self.object.type.direction == :big + tmpe = iter.map {|sig| sig.execute(mode) } + # Concatenate the result. + # return tmpe.reduce(:concat) + return Vprocess.concat(*tmpe) + end + ## Assigns +value+ the the reference. + self.define_singleton_method(:assign) do |mode,value| + # puts "RefObject #{self} assign with object=#{self.object}" + # Flatten the value type. + value.type = [value.type.width].to_type + pos = 0 + width = 0 + # Recurse on the children. + iter = self.object.each_signal + iter = iter.reverse_each unless self.object.type.direction == :big + iter.each do |sig| + width = sig.type.width + sig.assign(mode,value[(pos+width-1).to_expr..pos.to_expr]) + # Tell the signal changed. + if !(sig.c_value.eql?(sig.f_value)) then + @sim.add_sig_active(sig) + end + # Prepare for the next reference. + pos += width + end + end + end end ## Execute the expression. def execute(mode) return self.object.execute(mode)