class RubyRTL::VhdlGenerator
Constants
- VHDL_OP
expressions ===¶ ↑
Attributes
archi_elements[RW]
entity[RW]
ios[RW]
Public Instance Methods
adapt_name(name,kind)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 205 def adapt_name name,kind name=name.to_s case kind when :comb name+="_c" when :reg name+="_r" when :var name+="_v" end name end
clean_vhdl(code)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 42 def clean_vhdl(code) txt=code.finalize txt.gsub! /;(\s*)\)/,")" txt.gsub! /,(\s*)\)/,")" (code=Code.new) << txt return code end
default_init(type)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 523 def default_init type case type when BitType return "'0'" when BitVectorType return "(others=>'0')" when UintType return "to_unsigned(0,#{type.bitwidth})" when IntType return "to_signed(0,#{type.bitwidth})" else raise "Cannot provide default init value for type #{type}" end ret end
gen_archi(circuit)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 141 def gen_archi circuit body=circuit.ast.body archi_elements=body.stmts.collect{|stmt| stmt.accept(self)} archi=Code.new archi << "architecture rtl of #{circuit.name.downcase}_c is" archi.indent=2 @fsm_defs.each do |decl| archi << decl end @typedecls.each do |typedecl| archi << typedecl.accept(self) end @sigs.each do |sig,name| archi << "signal #{name} : #{sig.type.accept(self)};" end archi.indent=0 archi << "begin" archi.indent=2 archi.newline archi_elements.each do |element| archi << element archi.newline end archi.indent=0 archi.newline archi << "end rtl;" archi end
gen_entity(circuit)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 124 def gen_entity circuit entity=Code.new entity << "entity #{name=circuit.name.downcase}_c is" entity.indent=2 entity << "port (" entity.indent=4 if circuit.has_sequential_statements entity << "reset_n : in std_logic;" entity << "clk : in std_logic;" end ios.each{|io| entity << io} entity.indent=2 entity << ");" entity.indent=0 entity << "end #{name}_c;" end
gen_ieee_header()
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 105 def gen_ieee_header header=Code.new header << "-- automatically generated by RubyRTL" header << "library ieee;" header << "use ieee.std_logic_1164.all;" header << "use ieee.numeric_std.all;" header.newline header end
gen_package_call(circuit)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 115 def gen_package_call circuit name=circuit.name.downcase code=Code.new code << "library #{name}_lib;" code << "use #{name}_lib.#{name}_package.all;" code.newline code end
gen_ruby_rtl_package_call()
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 50 def gen_ruby_rtl_package_call code=Code.new code << "library ruby_rtl;" code << "use ruby_rtl.ruby_rtl_package.all;" code.newline code end
gen_ruby_rtl_type_package()
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 58 def gen_ruby_rtl_type_package code=Code.new code << gen_ieee_header code << "package ruby_rtl_type_package is " code.newline code.indent=2 $typedefs.each do |name,definition| case definition when RecordType code << definition_s=definition.accept(self,name) else definition_s=definition.accept(self) case definition when IntType,UIntType,BitType header="sub" else header="" end code << "#{header}type #{name} is #{definition_s};" end code.newline end code.indent=0 code << "end package;" code.save_as "ruby_rtl_type_package.vhd" end
gen_type_package()
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 85 def gen_type_package name=@circuit.name.downcase return unless ast=@circuit.ast typdecls=ast.decls.select{|decl| decl.is_a?(TypeDecl)} package=Code.new package << gen_ieee_header package << "package #{name}_package is" package.indent=2 package.newline typdecls.each do |decl| definition=decl.definition.accept(self,decl.name) package << definition package.newline end package.indent=0 package << "end package;" puts package.finalize package.save_as "#{name}_package.vhd" end
generate(circuit)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 11 def generate circuit puts "[+] VHDL code generation" code=Code.new @circuit=circuit @ios,@archi_elements=[],[] @sigs={} @fsm_defs=[] @sequentials=[] @states={} gen_ruby_rtl_type_package root=circuit.ast return unless root gen_type_package() #root.ios.each{|io| io.accept(self)} @typedecls=root.decls.select{|decl| decl.is_a? TypeDecl} non_typedecls=root.decls.reject{|decl| decl.is_a? TypeDecl} non_typedecls.each{|decl| decl.accept(self)} code << gen_ieee_header() code << gen_ruby_rtl_package_call() code << gen_package_call(circuit) code << gen_entity(circuit) code.newline code << gen_archi(circuit) code=clean_vhdl(code) puts code.finalize code.save_as "#{name=circuit.name.downcase}.vhd" end
state_body(state)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 451 def state_body state code=Code.new state.body.each{|stmt| code << stmt.accept(self)} code end
state_cases(fsm)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 434 def state_cases fsm code=Code.new code << "case #{fsm.name}_state is" code.indent=2 fsm.states.each do |state| code << "when #{state.name} =>" code.indent=4 code << state_body(state) code.indent=2 end code << "when others =>" code << " null;" code.indent=0 code << "end case;" code end
visitAssign(assign,args=nil)
click to toggle source
visitBinary(bin,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 475 def visitBinary bin,args=nil lhs=bin.lhs.accept(self) op=VHDL_OP[bin.op] || bin.op rhs=bin.rhs.accept(self) "(#{lhs} #{op} #{rhs})" end
visitBitLit(bit_lit,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 548 def visitBitLit bit_lit,args=nil "'#{bit_lit.val}'" end
visitBitType(bit,args=nil)
click to toggle source
visitBitVectorLit(bit_lit,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 552 def visitBitVectorLit bit_lit,args=nil "\"#{bit_lit.val}\"" end
visitBitVectorType(bv,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 506 def visitBitVectorType bv,args=nil range="#{bv.bitwidth-1} downto 0" "std_logic_vector(#{range})" end
visitBody(body,args=nil)
click to toggle source
statement
# File lib/ruby_rtl/vhdl_generator.rb, line 326 def visitBody body,args=nil code=Code.new body.stmts.each{|stmt| code << stmt.accept(self)} code end
visitCase(case_,args=nil)
click to toggle source
case / switch
# File lib/ruby_rtl/vhdl_generator.rb, line 369 def visitCase case_,args=nil cond=case_.cond.accept(self) code=Code.new code << "case #{cond} is" code.indent=2 code << case_.body.accept(self) code.indent=0 code << "end case;" code end
visitCombinatorial(comb,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 297 def visitCombinatorial comb,args=nil code=Code.new label=comb.label code << "#{label} : process(all) --VHDL'08" code << "begin" code.indent=2 code << comb.body.accept(self) code.indent=0 code << "end process;" code end
visitComment(comment,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 170 def visitComment comment,args=nil "-- #{comment.str}" end
visitCompDecl(comp_decl,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 268 def visitCompDecl comp_decl,args=nil comp=comp_decl.comp instance_name=comp_decl.name sig_decls=comp.ast.decls.select{|node| node.is_a? SigDecl} inputs =sig_decls.select{|decl| decl.sig.is_a? Input}.map(&:sig) outputs=sig_decls.select{|decl| decl.sig.is_a? Output}.map(&:sig) instanciation=Code.new instanciation << "#{instance_name} : entity work.#{comp.name}_c" instanciation.indent=2 instanciation << "port map(" instanciation.indent=4 inputs.each do |input| actual_sig_name="#{instance_name}_#{input.name}" @sigs.merge!({input => actual_sig_name}) instanciation << "#{input.name} => #{actual_sig_name}," end outputs.each do |output| actual_sig_name="#{instance_name}_#{output.name}" @sigs.merge!(output => actual_sig_name) instanciation << "#{output.name} => #{actual_sig_name}," end instanciation.indent=2 instanciation << ");" instanciation.indent=0 instanciation.newline instanciation end
visitElse(else_,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 359 def visitElse else_,args=nil body=else_.body.accept(self) code=Code.new code << "else " code.indent=2 code << body code.indent=0 code end
visitElsif(elsif_,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 348 def visitElsif elsif_,args=nil cond=elsif_.cond.accept(self) body=elsif_.body.accept(self) code=Code.new code << "elsif #{cond} then" code.indent=2 code << body code.indent=0 code end
visitEnumType(enum_type,name)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 223 def visitEnumType enum_type,name if name "type #{name} is (#{enum_type.items.join(',')});" else idx=$typedefs.values.index(enum_type) $typedefs.keys[idx] end end
visitFsm(fsm,args=nil)
click to toggle source
FSM ===¶ ↑
# File lib/ruby_rtl/vhdl_generator.rb, line 393 def visitFsm fsm,args=nil @fsm=fsm state_names=fsm.states.map{|state| state.name}.join(",") @fsm_defs << "type #{fsm.name}_state_t is (#{state_names});" @fsm_defs << "signal #{fsm.name}_state : #{fsm.name}_state_t;" body=Code.new body << "#{fsm.name}_update : process(reset_n,clk)" body << "begin" body.indent=2 body << "if reset_n='0' then" body.indent=4 body << "#{fsm.name}_state <= #{fsm.states.first.name};" fsm.assignments.each do |assign| lhs=assign.lhs.accept(self) rhs=default_init(assign.lhs.type) body << "#{lhs} <= #{rhs};" end body.indent=2 body << "elsif rising_edge(clk) then" body.indent=4 body << "if sreset='1' then" body.indent=6 body << "#{fsm.name}_state <= #{fsm.states.first.name};" fsm.assignments.each do |assign| lhs=assign.lhs.accept(self) rhs=default_init(assign.lhs.type) body << "#{lhs} <= #{rhs};" end body.indent=4 body << "else " body.indent=6 body << state_cases(fsm) body.indent=4 body << "end if;" body.indent=2 body << "end if;" body.indent=0 body << "end process;" body end
visitFuncCall(func,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 482 def visitFuncCall func,args=nil name=func.name argus=func.args.map{|arg| arg.accept(self)}.join(',') "#{name}(#{argus})" end
visitIf(if_,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 332 def visitIf if_,args=nil cond=if_.cond.accept(self) if_body=if_.body.accept(self) code=Code.new code << "if #{cond} then" code.indent=2 code << if_body code.indent=0 if_.elsifs.each{|elsif_| code << elsif_.accept(self) } code << if_.else.accept(self) if if_.else code << "end if;" code end
visitIndexed(indexed,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 488 def visitIndexed indexed,args=nil lhs=indexed.lhs.accept(self) rhs=indexed.rhs.accept(self) case indexed.rhs when RUIntLit else conv_int_start="to_integer(" conv_int_end =")" end puts indexed.rhs "#{lhs}(#{conv_int_start}#{rhs}#{conv_int_end})" end
visitInput(input,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 174 def visitInput input,args=nil name=@sigs[input] || input.name adapt_name(name,args) end
visitIntLit(int,args=nil)
click to toggle source
visitIntType(int,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 516 def visitIntType int,args=nil range="#{int.bitwidth-1} downto 0" "signed(#{range})" end
visitMemoryType(memtype,name)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 250 def visitMemoryType memtype,name if name range="0 to #{memtype.size-1}" type=memtype.type.accept(self) "array(#{range}) of #{type}" else idx=$typedefs.values.index(memtype) $typedefs.keys[idx] end end
visitNext(next_state,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 462 def visitNext next_state,args=nil "#{@fsm.name}_state <= #{next_state.name};" end
visitOutput(output,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 179 def visitOutput output,args=nil name=@sigs[output] || output.name adapt_name(name,args) end
visitRIntLit(lit,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 556 def visitRIntLit lit,args=nil lit.val end
visitRUIntLit(lit,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 560 def visitRUIntLit lit,args=nil lit.val end
visitRecordType(rectype,name)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 232 def visitRecordType rectype,name if name code=Code.new code << "record" code.indent=2 rectype.hash.each do |name,type| type_s=type.accept(self) code << "#{name} : #{type_s};" end code.indent=0 code << "end record;" code else idx=$typedefs.values.index(rectype) $typedefs.keys[idx] end end
visitSequential(sequential,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 309 def visitSequential sequential,args=nil code=Code.new label=sequential.label code << "#{label} : process(clk)" code << "begin" code.indent=2 code << "if rising_edge(clk) then" code.indent=4 code << sequential.body.accept(self) code.indent=2 code << "end if;" code.indent=0 code << "end process;" code end
visitSig(sig,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 200 def visitSig sig,args=nil name=sig.name adapt_name(name,args) end
visitSigDecl(decl,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 184 def visitSigDecl decl,args=nil name=decl.name name.sub!(/@/,'') type=decl.sig.type.accept(self) case decl.sig when Input ios << "#{name} : in #{type};" when Output ios << "#{name} : out #{type};" when Sig @sigs.merge!(decl.sig => name) else raise "ERROR : visitSigDecl : neither input ou output" end end
visitState(state,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 457 def visitState state,args=nil code << "when #{state.name}" code end
visitTypeDecl(decl,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 218 def visitTypeDecl decl,args=nil definition=decl.definition.accept(self,decl.name) "type #{decl.name} is #{definition};" end
visitUIntLit(uint,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 544 def visitUIntLit uint,args=nil "to_unsigned(#{uint.val},#{uint.type.bitwidth})" end
visitUIntType(uint,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 511 def visitUIntType uint,args=nil range="#{uint.bitwidth-1} downto 0" "unsigned(#{range})" end
visitWhen(when_,args=nil)
click to toggle source
# File lib/ruby_rtl/vhdl_generator.rb, line 380 def visitWhen when_,args=nil unless (value=when_.value).is_a? Symbol value=when_.value.accept(self) end code=Code.new code << "when #{value} =>" code.indent=2 code << when_.body.accept(self) code.indent=0 code end