URL
https://opencores.org/ocsvn/soc_maker/soc_maker/trunk
Subversion Repositories soc_maker
[/] [soc_maker/] [trunk/] [lib/] [soc_maker/] [soc_def.rb] - Rev 10
Compare with Previous | Blame | View Log
################################################################# File: soc_def.rb## Author: Christian Hättich## Project: System-On-Chip Maker## Target: Linux / Windows / Mac## Language: ruby#################################################################### Copyright (C) 2014 Christian Hättich - feddischson [ at ] opencores.org## This program is free software: you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation, either version 3 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program. If not, see <http://www.gnu.org/licenses/>.################################################################### Description:# This class represents a System-on-chip and derives# the functionallity from Component.# The two important fields are# - @cores: holds all core-instances# - cons: holds all connections# In addition, the field @static is used to store# static parameters, which are set for cores used in this SOC.################################################################module SOCMakerclass SOCDef < Componentinclude ERRinclude YAML_EXTattr_accessor :coresattr_accessor :consattr_accessor :staticdef initialize( name, id, toplevel, optional = {} )init_with( { 'name' => name,'id' => id,'toplevel' => toplevel }.merge( optional ) )enddef encode_with( coder )super coder%w[ cores cons static ].each { |v| coder[ v ] = instance_variable_get "@#{v}" }enddef init_with( coder )super coder@cores = coder[ 'cores' ] || {}@static = coder[ 'static' ] || {}@cons = coder[ 'cons' ] || {}enddef consistency_checksuper@cores.values.each do |inst|inst.consistency_checkendend# SOCMaker::logger.error( "instantiation #{inst_name} is already in use" )def inst_in_use?( inst_name )@cores[ inst_name.to_sym ] != nil or@cons[ inst_name.to_sym ] != nilenddef rm( inst_name )if @cores[ inst_name.to_sym ] != nil# TODO: remove also all related connections@cores.delete( inst_name.to_sym )elsif @cons[ inst_name.to_sym ] != nil@cons.delete( inst_name.to_sym )elsereturn falseendreturn trueenddef add_core( id, inst_name )return false if inst_in_use?( inst_name )# check, if the core exits in our library# if not: an error will be raisedSOCMaker::lib.get_core( id )@cores[ inst_name.to_sym ] = SOCMaker::CoreInst.new( id )enddef ifc_in_use?( inst_name, ifc_name )# go through all connections and check,# that non of the interfaces we want to connect is used@cons.each do |_con_name, con_def|return true if con_def[ :mapping ][ 0 ][ inst_name.to_sym] == ifc_name.to_symreturn true if con_def[ :mapping ][ 1 ][ inst_name.to_sym] == ifc_name.to_symendreturn falseenddef port_length( ifc_name, port_name, inst )if @cores[ inst.to_sym ] != nilreturn @cores[ inst ].port_length( ifc_name, port_name )elsereturn nilendenddef core_definition( inst )if @cores[ inst.to_sym ] != nilreturn @cores[ inst.to_sym ].defnelsif inst == @toplevelreturn selfelsereturn nilendend#def add_to_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )def add_to_connection( *args )if args.size == 4inst1 = @toplevelifc1_name = args[ 0 ]inst2 = args[ 1 ]ifc2_name = args[ 2 ]con_name = args[ 3 ]elsif args.size == 5inst1 = args[ 0 ]ifc1_name = args[ 1 ]inst2 = args[ 2 ]ifc2_name = args[ 3 ]con_name = args[ 4 ]elseperr_if( true, "FATAL: wrong number of arguments (#{args.size}) for add_to_connection (3 or 4)" )endperr_if( @cons[ con_name.to_sym ] == nil, "Connection instance #{con_name} not found" )@cons[ con_name.to_sym ][:mapping][0][ inst1.to_sym ] = ifc1_name.to_sym@cons[ con_name.to_sym ][:mapping][1][ inst2.to_sym ] = ifc2_name.to_symend#def add_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )def add_connection( *args )if args.size == 4inst1 = @toplevelifc1_name = args[ 0 ]inst2 = args[ 1 ]ifc2_name = args[ 2 ]con_name = args[ 3 ]elsif args.size == 5inst1 = args[ 0 ]ifc1_name = args[ 1 ]inst2 = args[ 2 ]ifc2_name = args[ 3 ]con_name = args[ 4 ]elseperr_if( true, "FATAL: wrong number of arguments (#{args.size}) for add_connection (3 or 4)" )endif @cores[ con_name.to_sym ] != nilreturn nilelsif @cons[ con_name.to_sym ] != nilreturn add_to_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )end[ [ inst1, ifc1_name ],[ inst2, ifc2_name ] ].each do |sub_arr|perr_if( ifc_in_use?( sub_arr[ 0 ], sub_arr[ 1 ] ),"Interface #{sub_arr[ 1 ]} of instance '#{sub_arr[ 0 ]}' is already in use " )endcore_def_1 = core_definition( inst1 )core_def_2 = core_definition( inst2 )perr_if( !core_def_1, "Can't find core #{inst1}" )perr_if( !core_def_2, "Can't find core #{inst2}" )[ [ core_def_1, ifc1_name ],[ core_def_2, ifc2_name ] ].each do |sub_arr|perr_if( sub_arr[ 0 ].interfaces[ sub_arr[ 1 ].to_sym ] == nil,"Interface '#{sub_arr[ 1 ]}' dosn't exist in core '#{sub_arr[0].name}' \n" +"The following interfaces do exist: '#{sub_arr[0].interfaces.keys}'" )end# check id of the ifcs which will be connectedperr_if( core_def_1.interfaces[ ifc1_name.to_sym ].id !=core_def_2.interfaces[ ifc2_name.to_sym ].id,"Can't connect #{core_def_1.interfaces[ ifc1_name.to_sym ].id} with #{core_def_2.interfaces[ ifc2_name.to_sym ].id} " )@cons[ con_name.to_sym ] = {:rule => "or",:mapping => [ { inst1.to_sym => ifc1_name.to_sym },{ inst2.to_sym => ifc2_name.to_sym } ] }return falseenddef set_param( instance, param, value )# get instancecore_inst = @cores[ instance.to_sym ]perr_if( core_inst == nil,"Can't find '#{instance}' in SOC" )# get the core-definitioncore_def = SOCMaker::lib.get_core( core_inst.type )# check if parameter existif core_def.inst_parameters[ param.to_sym ] != nilcore_inst.params[ param.to_sym ] = valueelseperr_if( true,"Parameter '#{param}' not found in '#{core_def.name}'" )endenddef get_param( instance, param )# get instancecore_inst = @cores[ instance.to_sym ]perr_if( core_inst == nil,"Can't find '#{instance}' in SOC" )param_val = core_inst.params[ param.to_sym ]perr_if( param_val == nil,"Can't find parameter '#{param}' in '#{instance}'" )return param_valenddef set_sparam( core, param, value )#get instance# check, if we are instantiating this coreperr_if( @cores.select{ |name,inst| inst.type == core }.size == 0,"Core '#{core}' is not instantiated in this SOC" )# get the core-definitioncore_def = SOCMaker::lib.get_core( core )# check if parameter existperr_if( core_def.static_parameters.select{ |f,p| p.parameters[ param.to_sym ] != nil }.size == 0,"Parameter '#{param}' not found in '#{core_def.name}'" )@static[ core.to_sym ] ||= {}@static[ core.to_sym ][ param.to_sym ] = valueenddef get_sparam( core, param )perr_if( @static[ core.to_sym ] == nil,"Core '#{core}' does not exist in this SOC" )perr_if( @static[ core.to_sym ][ param.to_sym ] == nil,"Parameter '#{param}' does not exist for core '#{core}'" )return @static[ core.to_sym ][ param.to_sym ]enddef copy_filesSOCMaker::logger.proc( "START of copying all HDL files" )## Create a unique list of cores and# for every core, create a directory and copy files#@cores.values.uniq{|x| x.type }.each do |core_inst; core_def, dst_dir|core_def = SOCMaker::lib.get_core( core_inst.type )# create destination directory name and ensure, that it is existdst_dir = Component.get_and_ensure_dst_dir!( core_def.dir_name )# copy each file into destination dircore_def.hdlfiles.each do |file, val|file_path = File.join( core_def.dir, val.path )dst_path = File.join( dst_dir, val.path )SOCMaker::logger.proc( "copy #{file_path} to #{ dst_path} " )FileUtils.mkdir_p(File.dirname(dst_path))FileUtils.cp( file_path, dst_path )end## handle the static parameters# (search and replace in pakckage/include files)core_def.static_parameters.each do |file, sparam|token_val_map = {}sparam.parameters.each do |n,sparam_entry|if @static[ core_inst.type.to_sym ] != nil and@static[ core_inst.type.to_sym ][ n ] != nil# use value defined in soc-spectmp = @static[ core_inst.type.to_sym ][ n ]else# use default value from core-spectmp = sparam_entry.defaultendif sparam_entry.type == "enum"token_val_map[ sparam_entry.token ] = sparam_entry.choice[ tmp ]elsif sparam_entry.type == "bool"if tmp == truetoken_val_map[ sparam_entry.token ] = sparam_entry.choiceelsetoken_val_map[ sparam_entry.token ] = ""endelsetoken_val_map[ sparam_entry.token ] = tmpendend# create file pathssrc_path = File.join( core_def.dir, sparam.path )dst_dir = Component::get_and_ensure_dst_dir!( core_def.dir_name )dst_path = File.join( dst_dir, sparam.file_dst )# process each line of input file# and replace tokens by value via# regular expressionFile.open( dst_path, 'w' ) do |dst_f|File.open( src_path ) do |src_f|SOCMaker::logger.proc( "create #{dst_path} from #{ src_path} " )while line = src_f.getstoken_val_map.each { |token, val| line = line.sub( Regexp.new( '\b' + token.to_s + '\b' ), val.to_s ) }dst_f.puts lineendendendendendSOCMaker::logger.proc( "END of copying all HDL files" )enddef ==(o)o.class == self.class &&o.cores == self.cores &&o.cons == self.cons &&o.static == self.static &&super( o )enddef to_stmp = "_________ SOC #{@name}: _______\n" +super +"\n__connections__\n"@cons.each do |_con_name, con_def|tmp += "#{_con_name}: #{con_def}\n"endtmp += "\n__cores__\n"@cores.each do |inst_name, inst|tmp += "#{inst_name}:\n#{inst}\n"endtmp += "'''''''''''''''''''''''''''''''''''\n"return tmpendend # class SOCSpecend # module SOCMaker# vim: noai:ts=2:sw=2
