# A library for parsing Verilog source code. #-- # Copyright 2006-2007 Suraj N. Kurapati # See the file named LICENSE for details. require 'ruby-vpi/util' class VerilogParser attr_reader :modules # Parses the given Verilog source code. def initialize aInput input = aInput.dup # strip comments input.gsub! %r{//.*$}, '' input.gsub! %r{/\*.*?\*/}m, '' @modules = input.scan(%r{(module.*?;)(.*?)endmodule}m).map do |matches| Module.new(*matches) end end class Module attr_reader :decl, :body, :name, :ports, :input_ports, :output_ports, :clock_port, :reset_port def initialize aDecl, aBody @decl = aDecl.strip @body = aBody @decl =~ %r{module\s+(\w+)\s*(?:\#\(.*?\))?\s*(?:\((.*?)\))?\s*;}m @name, portDecls = $1, $2.to_s @ports = portDecls.split(',').map {|decl| Port.new decl, self} @input_ports = @ports.select {|p| p.input?} @output_ports = @ports.select {|p| p.output?} @clock_port = @ports.find {|p| p.name =~ /clock|clo?c?k/i} @reset_port = @ports.find {|p| p.name =~ /reset|re?se?t/i} end class Port attr_reader :decl, :name def initialize aDecl, aModule @decl = aDecl @name = aDecl.scan(/\S+/).last parser = /\b(input|output|inout)\b[^;]*\b#{@name}\b/m aDecl =~ parser || aModule.body =~ parser @type = $1 end def input? @type != 'output' end def output? @type != 'input' end end end end class String # Converts this string containing Verilog # code into syntactically correct Ruby code. def verilog_to_ruby content = self.dup # single-line comments content.gsub! %r{//(.*)$}, '#\1' # multi-line comments content.gsub! %r{/\*.*?\*/}m, "\n=begin\n\\0\n=end\n" # preprocessor directives content.gsub! %r{`include}, '#\0' content.gsub! %r{`define\s+(\w+)\s+(.+)} do "#{$1.to_ruby_const_name} = #{$2}" end content.gsub! %r{`+}, '' # numbers content.gsub! %r{\d*\'([dohb]\w+)}, '0\1' # ranges content.gsub! %r{(\S)\s*:\s*(\S)}, '\1..\2' content end end