lib/HDLRuby/hruby_verilog.rb in HDLRuby-2.4.27 vs lib/HDLRuby/hruby_verilog.rb in HDLRuby-2.4.28
- old
+ new
@@ -12,22 +12,25 @@
# The list of base types used both in verilog and HDLRuby
VERILOG_BASE_TYPES = ["signed"]
+ # The list of signals that are actually verilog regs.
+ VERILOG_REGS = []
+
# Sample of very handy for programming.
# puts "class=#{self.yes.class}" # Confirm class of self.yes.
# puts "methods=#{self.right.methods}" # Confirm method of self.right.
# puts "outputs=#{outputs}" # Confirm outputs
# each. do |*arg| # I forgot this.
# puts args
# end
# Global variable used for indentation and structure (temporary).
-$space_count = 0 # Count used for increasing indent by if statement. (temporary)
+# $space_count = 0 # Count used for increasing indent by if statement. (temporary)
$vector_reg = "" # For storing signal type at structure declaration. (temporary)
$vector_cnt = 0 # For allocating numbers at structure declaration. (temporary)
# class Fixnum
# def to_verilog
@@ -99,26 +102,84 @@
# class of Represent blocking substitution or nonblocking assignment.
# Enhance Transmit with generation of verilog code.
class Transmit
# Converts the system to Verilog code.
- def to_verilog(mode = nil)
+ # def to_verilog(mode = nil)
+ def to_verilog(spc = 3)
# Determine blocking assignment or nonblocking substitution from mode and return it.
- code = "#{self.left.to_verilog} #{mode == "seq" ? "=" : "<="} #{self.right.to_verilog};\n"
+ # code = "#{self.left.to_verilog} #{mode == "seq" ? "=" : "<="} #{self.right.to_verilog};\n"
+ code = "#{" " * spc}#{self.left.to_verilog} #{self.block.mode == :seq ? "=" : "<="} #{self.right.to_verilog};"
return code
end
end
# To scheduling to the Block.
# Enhance Block with generation of verilog code.
class Block
- # Converts the system to Verilog code.
- def to_verilog(mode = nil)
- # No translation is done in this class.
- puts "Block to_verilog not found" # For debugging
+ # # Converts the system to Verilog code.
+ # def to_verilog(mode = nil)
+ # # No translation is done in this class.
+ # puts "Block to_verilog not found" # For debugging
+ # end
+
+ # Converts the system to Verilog code adding 'spc' spaces at the begining
+ # of each line.
+ def to_verilog(spc = 3)
+ code = "begin"
+ code << " : #{name_to_verilog(self.name)}" if self.name && !self.name.empty?
+ code << "\n" if block.each_inner.any?
+ # Declaration of "inner" part within "always".
+ block.each_inner do |inner|
+ # if regs.include?(inner.name) then
+ if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then
+ # code << " reg"
+ code << "#{" " * (spc+3)}reg"
+ else
+ code << "#{" " * (spc+3)}wire"
+ end
+
+ # Variable has "base", but if there is width etc, it is not in "base".
+ # It is determined by an if.
+ if inner.type.base?
+ if inner.type.base.base?
+ # code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog};\n"
+ code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog}"
+ else
+ # code << "#{inner.type.to_verilog} #{inner.to_verilog};\n"
+ code << "#{inner.type.to_verilog} #{inner.to_verilog}"
+ end
+ else
+ # code << " #{inner.type.to_verilog}#{inner.to_verilog};\n"
+ code << " #{inner.type.to_verilog}#{inner.to_verilog}"
+ end
+ if inner.value then
+ # There is an initial value.
+ code << " = #{inner.value.to_verilog}"
+ end
+ code << ";\n"
+ end
+
+ # Translate the block that finished scheduling.
+ block.each_statement do |statement|
+ #code << "\n #{statement.to_verilog(behavior.block.mode.to_s)}"
+ # code << "\n#{" "*spc}#{statement.to_verilog(behavior.block.mode.to_s)}"
+ if statement.is_a?(Block) then
+ code << "\n#{" " * (spc+3)}#{statement.to_verilog(spc+3)}"
+ else
+ code << "\n#{statement.to_verilog(spc+3)}"
+ end
+ end
+ # Close the block."
+ code << "\n#{" "*spc}end"
+ return code
end
+
+
+
+
# Extract and convert to verilog the TimeRepeat statements.
# NOTE: work only on the current level of the block (should be called
# through each_block_deep).
def repeat_to_verilog!
code = ""
@@ -134,11 +195,11 @@
block = st.statement.flatten(st.statement.mode.to_s)
# Declaration of "inner" part within "always".
block.each_inner do |inner|
# if regs.include?(inner.name) then
- if regs.include?(inner.to_verilog) then
+ if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then
code << " reg"
else
code << " wire"
end
@@ -1429,111 +1490,142 @@
def to_getrange
return "#{self.content.to_verilog}"
end
end
+
# Used to transrate if.
# Enhance If with generation of verilog code.
class If
- # Converts the system to Verilog code.
- def to_verilog(mode = nil)
+ # # Converts the system to Verilog code.
+ # def to_verilog(mode = nil)
+ # Converts to Verilog code, checking adding 'spc' spaces at the begining
+ # of each line.
+ def to_verilog(spc = 3)
$blocking = false
- if ($space_count == 0) then
- result = " " * ($space_count) # Indented based on space_count.
- else
- result = ""
- end
- $space_count += 1 # Add count to be used for indentation.
+ # if ($space_count == 0) then
+ # result = " " * ($space_count) # Indented based on space_count.
+ # else
+ # result = ""
+ # end
+ # $space_count += 1 # Add count to be used for indentation.
+ result = " " * spc # Indented based on space_count.
- result << "if (#{self.condition.to_verilog}) begin\n"
+ # result << "if (#{self.condition.to_verilog}) begin\n"
+ result << "if (#{self.condition.to_verilog}) "
# Check if there is yes (if) and output yes or less.
if self.respond_to? (:yes)
- self.yes.each_statement do |statement|
- result << "#{" " * $space_count} #{statement.to_verilog(mode)}"
- end
- result << "#{" " * $space_count} end\n"
+ # self.yes.each_statement do |statement|
+ # result << "#{" " * $space_count} #{statement.to_verilog(mode)}"
+ # end
+ # result << "#{" " * $space_count} end\n"
+ result << self.yes.to_verilog(spc)
end
# If noif (else if) exists, it outputs it.
# Since noif is directly under, respond_to is unnecessary.
self.each_noif do |condition, block|
- result << "#{" " * $space_count} else if (#{condition.to_verilog}) begin\n"
- block.each_statement do |statement|
- result << "#{" " * $space_count} #{statement.to_verilog(mode)}"
- end
- result << "#{" "* $space_count} end\n"
+ # result << "#{" " * $space_count} else if (#{condition.to_verilog}) begin\n"
+ result << "\n#{" "*spc}else if (#{condition.to_verilog}) "
+ # block.each_statement do |statement|
+ # result << "#{" " * $space_count} #{statement.to_verilog(mode)}"
+ # end
+ # result << "#{" "* $space_count} end\n"
+ result << block.to_verilog(spc)
end
# Check if there is no (else) and output no or less.
- if self.no.respond_to? (:mode)
- result << "#{" " * $space_count} else begin\n"
- self.no.each_statement do |statement|
- result << "#{" " * $space_count} #{statement.to_verilog(mode)}"
- end
- result << "#{" " * $space_count} end\n"
+ if self.no.respond_to?(:mode)
+ # result << "#{" " * $space_count} else begin\n"
+ result << "\n#{" " * spc}else "
+ # self.no.each_statement do |statement|
+ # result << "#{" " * $space_count} #{statement.to_verilog(mode)}"
+ # end
+ # result << "#{" " * $space_count} end\n"
+ result << self.no.to_verilog(spc)
end
- $space_count -= 1 # Since the output ends, reduce the count.
+ # $space_count -= 1 # Since the output ends, reduce the count.
return result
end
end
# Used to translate case
class Case
- def to_verilog(mode = nil)
+ # def to_verilog(mode = nil)
+ #
+ # Converts to Verilog code, checking if variables are register
+ # or wire adding 'spc' spaces at the begining of each line.
+ def to_verilog(spc = 3)
- if ($space_count == 0) then
- result = " " * ($space_count) # Indented based on space_count.
- else
- result = ""
- end
- $space_count += 1 # Add count to be used for indentation.
+ # if ($space_count == 0) then
+ # result = " " * ($space_count) # Indented based on space_count.
+ # else
+ # result = ""
+ # end
+ # $space_count += 1 # Add count to be used for indentation.
+ result = " " * spc # Indented based on space_count.
result = ""
result << "case(#{self.value.to_verilog})\n"
# n the case statement, each branch is partitioned by when. Process each time when.
self.each_when do |whens|
# Reads and stores the numbers and expressions stored in when.
- result << " " + " " *$space_count + "#{whens.match.to_verilog}: "
- if whens.statement.each_statement.count > 1 then
- result << "begin\n"
- whens.statement.each_statement do |statement|
- result << " "+ " " *$space_count +"#{statement.to_verilog}"
- end
- result << " " + " " *$space_count + "end\n"
- elsif whens.statement.each_statement.count == 1 then
- whens.statement.each_statement do |statement|
- result << "#{statement.to_verilog}"
- end
+ # result << " " + " " *$space_count + "#{whens.match.to_verilog}: "
+ result << " " * (spc+3) + "#{whens.match.to_verilog}: "
+
+ # if whens.statement.each_statement.count > 1 then
+ # result << "begin\n"
+ # whens.statement.each_statement do |statement|
+ # result << " "+ " " *$space_count +"#{statement.to_verilog}"
+ # end
+ # result << " " + " " *$space_count + "end\n"
+ # elsif whens.statement.each_statement.count == 1 then
+ # whens.statement.each_statement do |statement|
+ # result << "#{statement.to_verilog}"
+ # end
+ # else
+ # # Empty statement case.
+ # result << "\n"
+ # end
+ if whens.statement.each_statement.count >= 1 then
+ result << whens.statement.to_verilog(spc+3)
else
- # Empty statement case.
result << "\n"
end
end
- # The default part is stored in default instead of when. Reads and processes in the same way as when.
+ # # The default part is stored in default instead of when. Reads and processes in the same way as when.
+ # if self.default then
+ # if self.default.each_statement.count > 1 then
+ # result << " " + " " *$space_count + "default: begin\n"
+ # self.default.each_statement do |statement|
+ # result << " " + " " *$space_count + "#{statement.to_verilog}"
+ # end
+ # result << " end\n"
+ # elsif self.default.each_statement.count == 1 then
+ # result << " " + " " *$space_count + "default: "
+ # self.default.each_statement do |statement|
+ # result << "#{statement.to_verilog}"
+ # end
+ # end
+ # end
if self.default then
- if self.default.each_statement.count > 1 then
- result << " " + " " *$space_count + "default: begin\n"
- self.default.each_statement do |statement|
- result << " " + " " *$space_count + "#{statement.to_verilog}"
- end
- result << " end\n"
- elsif self.default.each_statement.count == 1 then
- result << " " + " " *$space_count + "default: "
- self.default.each_statement do |statement|
- result << "#{statement.to_verilog}"
- end
- end
+ if self.default.each_statement.count >= 1 then
+ result << self.default.each_statement.to_verilog(spc+3)
+ else
+ result << "\n"
+ end
end
- result << " " + " " *$space_count + "endcase\n" # Conclusion.
+ # result << " " + " " *$space_count + "endcase\n" # Conclusion.
+ result << " " * spc + "endcase\n" # Conclusion.
- $space_count -= 1 # Since the output ends, reduce the count.
+ # $space_count -= 1 # Since the output ends, reduce the count.
return result # Return case after translation.
end
end
# Translate expression of combination circuit.
@@ -1695,12 +1787,13 @@
end
# Look at the unit of time, convert the time to ps and output it.
# One of two people, TimeWait and Delay.
class TimeWait
- def to_verilog(mode=nil)
- return self.delay.to_verilog + "\n"
+ # def to_verilog(mode=nil)
+ def to_verilog(spc = 3)
+ return (" " * spc) + self.delay.to_verilog + "\n"
end
end
class Delay
def to_verilog
time = self.value.to_s
@@ -1774,27 +1867,23 @@
# Converts the system to Verilog code.
def to_verilog
- # Preprocessing
- # Force seq block to par: ULTRA TEMPORARY! ICIICI
- self.each_behavior do |behavior|
- behavior.each_block_deep do |block|
- block.set_mode!(:par) unless block.is_a?(TimeBlock)
- end
- end
# Detect the registers
- regs = []
+ # regs = []
+ HDLRuby::Low::VERILOG_REGS.clear
# The left values.
self.each_behavior do |behavior|
# behavior.block.each_statement do |statement|
# regs << statement.left.to_verilog if statement.is_a?(Transmit)
# end
behavior.each_block_deep do |block|
block.each_statement do |statement|
- regs << statement.left.to_verilog if statement.is_a?(Transmit)
+ if statement.is_a?(Transmit)
+ HDLRuby::Low::VERILOG_REGS << statement.left.to_verilog
+ end
end
end
end
# # puts "regs has clk?: #{regs.include?("clk")}"
# # puts "for system #{self.name}"
@@ -1807,23 +1896,31 @@
# regs.delete(connection.left.to_verilog)
# end
# # puts "Now regs has clk?: #{regs.include?("clk")}"
# And the initialized signals.
self.each_output do |output|
- regs << output.to_verilog if output.value
+ # regs << output.to_verilog if output.value
+ HDLRuby::Low::VERILOG_REGS << output.to_verilog if output.value
end
self.each_inner do |inner|
- regs << inner.to_verilog if inner.value
+ # regs << inner.to_verilog if inner.value
+ HDLRuby::Low::VERILOG_REGS << inner.to_verilog if inner.value
end
# And the array types signals.
self.each_signal do |sig|
- # regs << sig.to_verilog if sig.type.is_a?(TypeVector) && sig.type.base.is_a?(TypeVector)
- regs << sig.to_verilog if sig.type.vector? && sig.type.base.vector?
+ # # regs << sig.to_verilog if sig.type.is_a?(TypeVector) && sig.type.base.is_a?(TypeVector)
+ # regs << sig.to_verilog if sig.type.vector? && sig.type.base.vector?
+ if sig.type.vector? && sig.type.base.vector? then
+ HDLRuby::Low::VERILOG_REGS << sig.to_verilog
+ end
end
self.each_inner do |sig|
- # regs << sig.to_verilog if sig.type.is_a?(TypeVector) && sig.type.base.is_a?(TypeVector)
- regs << sig.to_verilog if sig.type.vector? && sig.type.base.vector?
+ # # regs << sig.to_verilog if sig.type.is_a?(TypeVector) && sig.type.base.is_a?(TypeVector)
+ # regs << sig.to_verilog if sig.type.vector? && sig.type.base.vector?
+ if sig.type.vector? && sig.type.base.vector? then
+ HDLRuby::Low::VERILOG_REGS << sig.to_verilog
+ end
end
# Code generation
inputs = 0
outputs = 0
@@ -1888,11 +1985,12 @@
self.each_output do |output|
if output.type.respond_to? (:each_type) then
$vector_reg = "#{output.to_verilog}"
$vector_cnt = 0
output.type.each_type do |type|
- if regs.include?(type.name) then
+ # if regs.include?(type.name) then
+ if HDLRuby::Low::VERILOG_REGS.include?(type.name) then
code << " output reg"
else
code << " output"
end
# code << "#{type.to_verilog} #{$vector_reg}:#{$vector_cnt};\n"
@@ -1904,11 +2002,12 @@
code << ";\n"
$vector_cnt += 1
end
else
# if regs.include?(output.name) then
- if regs.include?(output.to_verilog) then
+ # if regs.include?(output.to_verilog) then
+ if HDLRuby::Low::VERILOG_REGS.include?(output.to_verilog) then
code << " output reg"
else
code << " output"
end
# code << "#{output.type.to_verilog} #{output.to_verilog};\n"
@@ -1935,12 +2034,13 @@
end
end
# Declare "inner".
self.each_inner do |inner|
- # if regs.include?(inner.name) then
- if regs.include?(inner.to_verilog) then
+ # # if regs.include?(inner.name) then
+ # if regs.include?(inner.to_verilog) then
+ if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then
code << " reg"
else
code << " wire"
end
@@ -1964,12 +2064,13 @@
end
# If there is scope in scope, translate it.
self.each_scope do |scope|
scope.each_inner do |inner|
- # if regs.include?(inner.name) then
- if regs.include?(inner.to_verilog) then
+ # # if regs.include?(inner.name) then
+ # if regs.include?(inner.to_verilog) then
+ if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then
code << " reg "
else
code << " wire "
end
@@ -2056,11 +2157,12 @@
# Extract and translate the TimeRepeat separately.
behavior.each_block_deep do |blk|
code << blk.repeat_to_verilog!
end
# And generate an initial block.
- code << " initial begin\n"
+ # code << " initial begin\n"
+ code << " initial "
else
# Generate a standard process.
code << " always @( "
# If there is no "always" condition, it is always @("*").
if behavior.each_event.to_a.empty? then
@@ -2081,57 +2183,60 @@
code << "#{event.last.ref.to_verilog}"
else
code << "#{event.last.type.to_s} #{event.last.ref.to_verilog}"
end
end
- code << " ) begin\n"
+ # code << " ) begin\n"
+ code << " ) "
end
- # Perform "scheduling" using the method "flatten".
- block = behavior.block.flatten(behavior.block.mode.to_s)
+ # # Perform "scheduling" using the method "flatten".
+ # block = behavior.block.flatten(behavior.block.mode.to_s)
+ # code << block.to_verilog(regs)
+ code << behavior.block.to_verilog
- # Declaration of "inner" part within "always".
- block.each_inner do |inner|
- # if regs.include?(inner.name) then
- if regs.include?(inner.to_verilog) then
- code << " reg"
- else
- code << " wire"
- end
+ # # Declaration of "inner" part within "always".
+ # block.each_inner do |inner|
+ # # if regs.include?(inner.name) then
+ # if regs.include?(inner.to_verilog) then
+ # code << " reg"
+ # else
+ # code << " wire"
+ # end
- # Variable has "base", but if there is width etc, it is not in "base".
- # It is determined by an if.
- if inner.type.base?
- if inner.type.base.base?
- # code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog};\n"
- code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog}"
- else
- # code << "#{inner.type.to_verilog} #{inner.to_verilog};\n"
- code << "#{inner.type.to_verilog} #{inner.to_verilog}"
- end
- else
- # code << " #{inner.type.to_verilog}#{inner.to_verilog};\n"
- code << " #{inner.type.to_verilog}#{inner.to_verilog}"
- end
- if inner.value then
- # There is an initial value.
- code << " = #{inner.value.to_verilog}"
- end
- code << ";\n"
- end
+ # # Variable has "base", but if there is width etc, it is not in "base".
+ # # It is determined by an if.
+ # if inner.type.base?
+ # if inner.type.base.base?
+ # # code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog};\n"
+ # code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog}"
+ # else
+ # # code << "#{inner.type.to_verilog} #{inner.to_verilog};\n"
+ # code << "#{inner.type.to_verilog} #{inner.to_verilog}"
+ # end
+ # else
+ # # code << " #{inner.type.to_verilog}#{inner.to_verilog};\n"
+ # code << " #{inner.type.to_verilog}#{inner.to_verilog}"
+ # end
+ # if inner.value then
+ # # There is an initial value.
+ # code << " = #{inner.value.to_verilog}"
+ # end
+ # code << ";\n"
+ # end
- # Translate the block that finished scheduling.
- block.each_statement do |statement|
- code << "\n #{statement.to_verilog(behavior.block.mode.to_s)}"
- end
+ # # Translate the block that finished scheduling.
+ # block.each_statement do |statement|
+ # code << "\n #{statement.to_verilog(behavior.block.mode.to_s)}"
+ # end
- $fm.fm_par.clear()
+ # $fm.fm_par.clear()
- code << "\n end\n\n"
+ # code << "\n end\n\n"
end
# Conclusion.
- code << "endmodule"
+ code << "\nendmodule"
return code
end
end
end