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)