lib/HDLRuby/hruby_rsim.rb in HDLRuby-2.11.5 vs lib/HDLRuby/hruby_rsim.rb in HDLRuby-2.11.7
- old
+ new
@@ -17,10 +17,15 @@
class SystemT
# Tell if the simulation is in multithread mode or not.
attr_reader :multithread
+ ## Add untimed objet +obj+
+ def add_untimed(obj)
+ @untimeds << obj
+ end
+
## Add timed behavior +beh+.
# Returns the id of the timed behavior.
def add_timed_behavior(beh)
@timed_behaviors << beh
@total_timed_behaviors += 1
@@ -39,25 +44,36 @@
@sig_active << sig
end
## Advance the global simulator.
def advance
- # Display the time
- self.show_time
+ # # Display the time
+ # self.show_time
shown_values = {}
# Get the behaviors waiting on activated signals.
until @sig_active.empty? do
- # # Update the signals.
- # @sig_active.each { |sig| sig.c_value = sig.f_value }
# puts "sig_active.size=#{@sig_active.size}"
+ # puts "sig_active=#{@sig_active.map {|sig| sig.fullname}}"
# Look for the behavior sensitive to the signals.
+ # @sig_active.each do |sig|
+ # sig.each_anyedge { |beh| @sig_exec << beh }
+ # if (sig.c_value.zero? && !sig.f_value.zero?) then
+ # # puts "sig.c_value=#{sig.c_value.content}"
+ # sig.each_posedge { |beh| @sig_exec << beh }
+ # elsif (!sig.c_value.zero? && sig.f_value.zero?) then
+ # sig.each_negedge { |beh| @sig_exec << beh }
+ # 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? && !sig.f_value.zero?) then
+ 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? && sig.f_value.zero?) then
+ elsif (!sig.c_value.zero?) then
sig.each_negedge { |beh| @sig_exec << beh }
end
end
# Update the signals.
@sig_active.each { |sig| sig.c_value = sig.f_value }
@@ -79,10 +95,12 @@
@sig_active.uniq! {|sig| sig.object_id }
# puts "@sig_active.size=#{@sig_active.size}"
# Advance time.
@time = (@timed_behaviors.min {|b0,b1| b0.time <=> b1.time }).time
end
+ # Display the time
+ self.show_time
end
## Run the simulation from the current systemT and outputs the resuts
# on simout.
def sim(simout)
@@ -93,10 +111,12 @@
# Initializes the time.
@time = 0
# Initializes the time and signals execution buffers.
@tim_exec = []
@sig_exec = []
+ # Initilize the list of untimed objects.
+ @untimeds = []
# Initialize the list of currently exisiting timed behavior.
@timed_behaviors = []
# Initialize the list of activated signals.
@sig_active = []
# Initializes the total number of timed behaviors (currently
@@ -105,10 +125,14 @@
# Initilizes the simulation.
self.init_sim(self)
# Initialize the displayer.
self.show_init(simout)
+ # Initialize the untimed objects.
+ self.init_untimeds
+ # puts "End of init_untimed."
+
# 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.
@@ -203,10 +227,21 @@
# Recurse on the signals.
self.each_signal { |sig| sig.init_sim(systemT) }
# Recure on the scope.
self.scope.init_sim(systemT)
end
+
+ ## Initialize the untimed objects.
+ def init_untimeds
+ @untimeds.each do |obj|
+ if obj.is_a?(Behavior) then
+ obj.block.execute(:seq)
+ else
+ obj.execute(:seq)
+ end
+ end
+ end
## Initialize run for executing +ruby_block+
def run_init(&ruby_block)
@mutex.synchronize(&ruby_block)
end
@@ -335,10 +370,12 @@
return self.block.execute(mode)
end
## Initialize the simulation for system +systemT+.
def init_sim(systemT)
+ # Add the behavior to the list of untimed objects.
+ systemT.add_untimed(self)
# Process the sensitivity list.
# Is it a clocked behavior?
events = self.each_event.to_a
if events.empty? then
# No events, this is not a clock behavior.
@@ -349,10 +386,11 @@
node.is_a?(RefObject) && !node.leftvalue? &&
!node.parent.is_a?(RefObject)
end.to_a
# Keep only one ref per signal.
refs.uniq! { |node| node.fullname }
+ # puts "refs=#{refs.map {|node| node.fullname}}"
# Remove the inner signals from the list.
self.block.each_inner do |inner|
refs.delete_if {|r| r.name == inner.name }
end
# Generate the event.
@@ -514,12 +552,12 @@
def assign(mode,value)
# Set the next value.
@f_value = value
# Set the mode.
@mode = mode
- # puts "assign #{value.content} (#{value.content.class}) with self.type.width=#{self.type.width} while value.type.width=#{value.type.width}" if self.name.to_s.include?("idx")
- # @f_value = value.cast(self.type) # Cast inserted by HDLRuby normally
+ # puts "assign #{value.content} (#{value.content.class}) with self.type.width=#{self.type.width} while value.type.width=#{value.type.width}" if self.name.to_s.include?("xnor")
+ @f_value = value.cast(self.type) # Cast not always inserted by HDLRuby normally
end
## Assigns +value+ at +index+ (integer or range).
def assign_at(mode,value,index)
# @f_value = @f_value.assign_at(mode,value,index)
@@ -665,22 +703,22 @@
# Describes a case statement.
class Case
## Initialize the simulation for system +systemT+.
def init_sim(systemT)
self.each_when { |wh| wh.init_sim(systemT) }
- self.default.init_sim(systemT)
+ self.default.init_sim(systemT) if self.default
end
## Executes the statement.
def execute(mode)
unless self.each_when.find do |wh|
if wh.match.eql?(self.value.execute(mode)) then
wh.statement.execute(mode)
return
end
end
- self.default.execute(mode)
+ self.default.execute(mode) if self.default
end
end
end
@@ -847,10 +885,12 @@
# Describes a connection.
class Connection
## 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.
self.left.init_sim(systemT)
# Process the sensitivity list.
# Is it a clocked behavior?
events = []
@@ -859,10 +899,12 @@
refs = self.right.each_node_deep.select do |node|
node.is_a?(RefObject) && !node.parent.is_a?(RefObject)
end.to_a
# Keep only one ref per signal.
refs.uniq! { |node| node.fullname }
+ # puts "connection input: #{self.left.fullname}"
+ # puts "connection refs=#{refs.map {|node| node.fullname}}"
# # Generate the event.
# events = refs.map {|ref| Event.new(:anyedge,ref) }
# # Add them to the behavior for further processing.
# events.each {|event| self.add_event(event) }
# Now process the events: add the connection to the corresponding
@@ -870,11 +912,11 @@
refs.each {|ref| ref.object.add_anyedge(self) }
end
## Executes the statement.
def execute(mode)
- # puts "connection = #{self}"
+ # puts "connection = #{self}" if self.left.is_a?(RefObject) && self.left.object.name.to_s.include?("xnor")
self.left.assign(mode,self.right.execute(mode))
end
end
@@ -970,13 +1012,21 @@
#
# NOTE: choice is using the value of +select+ as an index.
class Select
## Execute the expression.
def execute(mode)
+ unless @mask then
+ # Need to initialize the execution of the select.
+ width = (@choices.size-1).width
+ width = 1 if width == 0
+ @mask = 2**width - 1
+ @choices.concat([@choices[-1]] * (2**width-@choices.size))
+ end
# Recurse on the select.
- tmps = self.select.execute(mode)
+ tmps = self.select.execute(mode).to_i & @mask
+ # puts "select tmps=#{tmps}, @choices.size=#{@choices.size}"
# Recurse on the selection result.
- return @choices[tmps.to_i].execute(mode)
+ return @choices[tmps].execute(mode)
end
end
##