###############################################################
|
###############################################################
|
#
|
#
|
# File: soc_def.rb
|
# File: soc_def.rb
|
#
|
#
|
# Author: Christian Hättich
|
# Author: Christian Hättich
|
#
|
#
|
# Project: System-On-Chip Maker
|
# Project: System-On-Chip Maker
|
#
|
#
|
# Target: Linux / Windows / Mac
|
# Target: Linux / Windows / Mac
|
#
|
#
|
# Language: ruby
|
# Language: ruby
|
#
|
#
|
#
|
#
|
###############################################################
|
###############################################################
|
#
|
#
|
#
|
#
|
# Copyright (C) 2014 Christian Hättich - feddischson [ at ] opencores.org
|
# Copyright (C) 2014 Christian Hättich - feddischson [ at ] opencores.org
|
#
|
#
|
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
# (at your option) any later version.
|
# (at your option) any later version.
|
#
|
#
|
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
#
|
#
|
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
# along with this program. If not, see .
|
# along with this program. If not, see .
|
#
|
#
|
#
|
#
|
###############################################################
|
###############################################################
|
#
|
#
|
# Description:
|
# Description:
|
# This class represents a System-on-chip and derives
|
# This class represents a System-on-chip and derives
|
# the functionallity from Component.
|
# the functionallity from Component.
|
# The two important fields are
|
# The two important fields are
|
# - @cores: holds all core-instances
|
# - @cores: holds all core-instances
|
# - cons: holds all connections
|
# - cons: holds all connections
|
# In addition, the field @static is used to store
|
# In addition, the field @static is used to store
|
# static parameters, which are set for cores used in this SOC.
|
# static parameters, which are set for cores used in this SOC.
|
#
|
#
|
###############################################################
|
###############################################################
|
|
|
module SOCMaker
|
module SOCMaker
|
class SOCDef < Component
|
class SOCDef < Component
|
include ERR
|
include ERR
|
include YAML_EXT
|
include YAML_EXT
|
|
|
attr_accessor :cores
|
attr_accessor :cores
|
attr_accessor :cons
|
attr_accessor :cons
|
attr_accessor :static
|
attr_accessor :static
|
def initialize( name, version, toplevel, options = {} )
|
def initialize( name, version, toplevel, options = {} )
|
|
|
init_with( { 'name' => name,
|
init_with( { 'name' => name,
|
'version' => version,
|
'version' => version,
|
'toplevel' => toplevel }.merge( options ) )
|
'toplevel' => toplevel }.merge( options ) )
|
|
|
end
|
end
|
|
|
def encode_with( coder )
|
def encode_with( coder )
|
super coder
|
super coder
|
%w[ cores cons static ].
|
%w[ cores cons static ].
|
each { |v| coder[ v ] = instance_variable_get "@#{v}" }
|
each { |v| coder[ v ] = instance_variable_get "@#{v}" }
|
end
|
end
|
|
|
def init_with( coder )
|
def init_with( coder )
|
super coder
|
super coder
|
@cores = coder[ 'cores' ] || {}
|
@cores = coder[ 'cores' ] || {}
|
@static = coder[ 'static' ] || {}
|
@static = coder[ 'static' ] || {}
|
@cons = coder[ 'cons' ] || {}
|
@cons = coder[ 'cons' ] || {}
|
end
|
end
|
|
|
def verify
|
def verify
|
super( true )
|
super( true )
|
|
|
@cores.each do |core_name, core_inst|
|
@cores.each do |core_name, core_inst|
|
core_inst.verify
|
core_inst.verify
|
end
|
end
|
|
|
end
|
end
|
|
|
|
|
def get_and_ensure_dst_dir!( core_name )
|
|
dst_dir = File.expand_path(
|
|
File.join(
|
|
SOCMaker::conf[ :build_dir ],
|
|
SOCMaker::conf[ :hdl_dir ],
|
|
core_name ) )
|
|
FileUtils.mkdir_p dst_dir
|
|
return dst_dir
|
|
end
|
|
|
|
|
|
|
|
|
|
# SOCMaker::logger.error( "instantiation #{inst_name} is already in use" )
|
# SOCMaker::logger.error( "instantiation #{inst_name} is already in use" )
|
def inst_in_use?( inst_name )
|
def inst_in_use?( inst_name )
|
@cores[ inst_name.to_sym ] != nil or
|
@cores[ inst_name.to_sym ] != nil or
|
@cons[ inst_name.to_sym ] != nil
|
@cons[ inst_name.to_sym ] != nil
|
end
|
end
|
|
|
def rm( inst_name )
|
def rm( inst_name )
|
|
|
if @cores[ inst_name.to_sym ] != nil
|
if @cores[ inst_name.to_sym ] != nil
|
# TODO: remove also all related connections
|
# TODO: remove also all related connections
|
@cores.delete( inst_name.to_sym )
|
@cores.delete( inst_name.to_sym )
|
elsif @cons[ inst_name.to_sym ] != nil
|
elsif @cons[ inst_name.to_sym ] != nil
|
@cons.delete( inst_name.to_sym )
|
@cons.delete( inst_name.to_sym )
|
else
|
else
|
return false
|
return false
|
end
|
end
|
return true
|
return true
|
end
|
end
|
|
|
|
|
def add_core( name, version, inst_name )
|
def add_core( name, version, inst_name )
|
|
|
return false if inst_in_use?( inst_name )
|
return false if inst_in_use?( inst_name )
|
|
|
# check, if the core exits in our library
|
# check, if the core exits in our library
|
# if not: an error will be raised
|
# if not: an error will be raised
|
SOCMaker::lib.get_core( name, version )
|
SOCMaker::lib.get_core( name, version )
|
|
|
@cores[ inst_name.to_sym ] = SOCMaker::CoreInst.new( name+version )
|
@cores[ inst_name.to_sym ] = SOCMaker::CoreInst.new( name+version )
|
end
|
end
|
|
|
|
|
def ifc_in_use?( inst_name, ifc_name )
|
def ifc_in_use?( inst_name, ifc_name )
|
|
|
# go through all connections and check,
|
# go through all connections and check,
|
# that non of the interfaces we want to connect is used
|
# that non of the interfaces we want to connect is used
|
@cons.each do |_con_name, con_def|
|
@cons.each do |_con_name, con_def|
|
return true if con_def[ :mapping ][ 0 ][ inst_name.to_sym] == ifc_name.to_sym
|
return true if con_def[ :mapping ][ 0 ][ inst_name.to_sym] == ifc_name.to_sym
|
return true if con_def[ :mapping ][ 1 ][ inst_name.to_sym] == ifc_name.to_sym
|
return true if con_def[ :mapping ][ 1 ][ inst_name.to_sym] == ifc_name.to_sym
|
end
|
end
|
return false
|
return false
|
|
|
end
|
end
|
|
|
|
|
|
|
|
def get_core_def( inst )
|
|
if @cores[ inst.to_sym ] != nil
|
|
return @cores[ inst.to_sym ].defn
|
|
elsif inst == @name
|
|
return self
|
|
else
|
|
perr_if( true,
|
|
"Instance '#{inst}' does not exist in SOC '#{self.name}'" )
|
|
end
|
|
end
|
|
|
|
|
|
|
def add_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )
|
def add_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )
|
|
|
return nil if inst_in_use?( con_name )
|
return nil if inst_in_use?( con_name )
|
|
|
|
|
[ [ inst1, ifc1_name ],
|
[ [ inst1, ifc1_name ],
|
[ inst2, ifc2_name ] ].each do |sub_arr|
|
[ inst2, ifc2_name ] ].each do |sub_arr|
|
perr_if( ifc_in_use?( sub_arr[ 0 ], sub_arr[ 1 ] ),
|
perr_if( ifc_in_use?( sub_arr[ 0 ], sub_arr[ 1 ] ),
|
"Interface #{sub_arr[ 1 ]} of instance '#{sub_arr[ 0 ]}' is already in use " )
|
"Interface #{sub_arr[ 1 ]} of instance '#{sub_arr[ 0 ]}' is already in use " )
|
end
|
end
|
|
|
[ inst1, inst2 ].each do |inst|
|
|
perr_if( @cores[ inst.to_sym ] == nil,
|
|
"Instance '#{inst}' does not exist in SOC '#{self.name}'" )
|
|
end
|
|
|
|
# get the core-specs
|
core_spec_1 = get_core_def( inst1 )
|
core_spec_1 = SOCMaker::lib.get_core( @cores[ inst1.to_sym ].type )
|
core_spec_2 = get_core_def( inst2 )
|
core_spec_2 = SOCMaker::lib.get_core( @cores[ inst2.to_sym ].type )
|
|
|
|
[ [ core_spec_1, ifc1_name ],
|
[ [ core_spec_1, ifc1_name ],
|
[ core_spec_2, ifc2_name ] ].each do |sub_arr|
|
[ core_spec_2, ifc2_name ] ].each do |sub_arr|
|
perr_if( sub_arr[ 0 ].interfaces[ sub_arr[ 1 ].to_sym ] == nil,
|
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}' " )
|
"Interface '#{sub_arr[ 1 ]}' dosn't exist in core '#{sub_arr[0].name}' " )
|
end
|
end
|
|
|
# check name and version of the ifcs which will be connected
|
# check name and version of the ifcs which will be connected
|
perr_if( core_spec_1.interfaces[ ifc1_name.to_sym ].name !=
|
perr_if( core_spec_1.interfaces[ ifc1_name.to_sym ].name !=
|
core_spec_2.interfaces[ ifc2_name.to_sym ].name ||
|
core_spec_2.interfaces[ ifc2_name.to_sym ].name ||
|
core_spec_1.interfaces[ ifc1_name.to_sym ].version !=
|
core_spec_1.interfaces[ ifc1_name.to_sym ].version !=
|
core_spec_2.interfaces[ ifc2_name.to_sym ].version,
|
core_spec_2.interfaces[ ifc2_name.to_sym ].version,
|
"Can't connect #{
|
"Can't connect #{
|
core_spec_1.interfaces[ ifc1_name.to_sym ].name } - #{
|
core_spec_1.interfaces[ ifc1_name.to_sym ].name } - #{
|
core_spec_2.interfaces[ ifc2_name.to_sym ].name } : #{
|
core_spec_2.interfaces[ ifc2_name.to_sym ].name } : #{
|
core_spec_1.interfaces[ ifc1_name.to_sym ].version } - #{
|
core_spec_1.interfaces[ ifc1_name.to_sym ].version } - #{
|
core_spec_2.interfaces[ ifc2_name.to_sym ].version }" )
|
core_spec_2.interfaces[ ifc2_name.to_sym ].version }" )
|
|
|
|
|
@cons[ con_name.to_sym ] = {
|
@cons[ con_name.to_sym ] = {
|
:rule => "or",
|
:rule => "or",
|
:mapping => [ { inst1.to_sym => ifc1_name.to_sym },
|
:mapping => [ { inst1.to_sym => ifc1_name.to_sym },
|
{ inst2.to_sym => ifc2_name.to_sym } ] }
|
{ inst2.to_sym => ifc2_name.to_sym } ] }
|
|
return false
|
end
|
end
|
|
|
def set_param( instance, param, value )
|
def set_param( instance, param, value )
|
|
|
# get instance
|
# get instance
|
core_inst = @cores[ instance.to_sym ]
|
core_inst = @cores[ instance.to_sym ]
|
perr_if( core_inst == nil,
|
perr_if( core_inst == nil,
|
"Can't find '#{instance}' in SOC" )
|
"Can't find '#{instance}' in SOC" )
|
|
|
# get the core-definition
|
# get the core-definition
|
core_def = SOCMaker::lib.get_core( core_inst.type )
|
core_def = SOCMaker::lib.get_core( core_inst.type )
|
|
|
# check if parameter exist
|
# check if parameter exist
|
if core_def.inst_parameters[ param.to_sym ] != nil
|
if core_def.inst_parameters[ param.to_sym ] != nil
|
core_inst.params[ param.to_sym ] = value
|
core_inst.params[ param.to_sym ] = value
|
else
|
else
|
perr_if( true,
|
perr_if( true,
|
"Parameter '#{param}' not found in '#{core_def.name}'" )
|
"Parameter '#{param}' not found in '#{core_def.name}'" )
|
end
|
end
|
|
|
end
|
end
|
|
|
def get_param( instance, param )
|
def get_param( instance, param )
|
|
|
# get instance
|
# get instance
|
core_inst = @cores[ instance.to_sym ]
|
core_inst = @cores[ instance.to_sym ]
|
perr_if( core_inst == nil,
|
perr_if( core_inst == nil,
|
"Can't find '#{instance}' in SOC" )
|
"Can't find '#{instance}' in SOC" )
|
param_val = core_inst.params[ param.to_sym ]
|
param_val = core_inst.params[ param.to_sym ]
|
perr_if( param_val == nil,
|
perr_if( param_val == nil,
|
"Can't find parameter '#{param}' in '#{instance}'" )
|
"Can't find parameter '#{param}' in '#{instance}'" )
|
return param_val
|
return param_val
|
end
|
end
|
|
|
|
|
def set_sparam( core, param, value )
|
def set_sparam( core, param, value )
|
|
|
#get instance
|
#get instance
|
|
|
# check, if we are instantiating this core
|
# check, if we are instantiating this core
|
perr_if( @cores.select{ |name,inst| inst.type == core }.size == 0,
|
perr_if( @cores.select{ |name,inst| inst.type == core }.size == 0,
|
"Core '#{core}' is not instantiated in this SOC" )
|
"Core '#{core}' is not instantiated in this SOC" )
|
|
|
# get the core-definition
|
# get the core-definition
|
core_def = SOCMaker::lib.get_core( core )
|
core_def = SOCMaker::lib.get_core( core )
|
|
|
# check if parameter exist
|
# check if parameter exist
|
perr_if( core_def.static_parameters.select{ |f,p| p.parameters[ param.to_sym ] != nil }.size == 0,
|
perr_if( core_def.static_parameters.select{ |f,p| p.parameters[ param.to_sym ] != nil }.size == 0,
|
"Parameter '#{param}' not found in '#{core_def.name}'" )
|
"Parameter '#{param}' not found in '#{core_def.name}'" )
|
|
|
@static[ core.to_sym ] ||= {}
|
@static[ core.to_sym ] ||= {}
|
@static[ core.to_sym ][ param.to_sym ] = value
|
@static[ core.to_sym ][ param.to_sym ] = value
|
end
|
end
|
|
|
def get_sparam( core, param )
|
def get_sparam( core, param )
|
perr_if( @static[ core.to_sym ] == nil,
|
perr_if( @static[ core.to_sym ] == nil,
|
"Core '#{core}' does not exist in this SOC" )
|
"Core '#{core}' does not exist in this SOC" )
|
|
|
perr_if( @static[ core.to_sym ][ param.to_sym ] == nil,
|
perr_if( @static[ core.to_sym ][ param.to_sym ] == nil,
|
"Parameter '#{param}' does not exist for core '#{core}'" )
|
"Parameter '#{param}' does not exist for core '#{core}'" )
|
|
|
return @static[ core.to_sym ][ param.to_sym ]
|
return @static[ core.to_sym ][ param.to_sym ]
|
end
|
end
|
|
|
|
|
|
|
def gen_toplevel( coder = VHDLCoder.new() )
|
def gen_toplevel( coder = VHDLCoder.new() )
|
|
|
file_name = @name
|
file_name = @name.dup
|
|
|
if coder.is_a?( VHDLCoder )
|
if coder.is_a?( VHDLCoder )
|
file_name << ".vhd"
|
file_name << ".vhd"
|
elsif coder.is_a?( VerilogCoder )
|
elsif coder.is_a?( VerilogCoder )
|
file_name << ".v"
|
file_name << ".v"
|
else
|
else
|
perr_if( true,
|
perr_if( true,
|
"No valid coder" )
|
"No valid coder" )
|
end
|
end
|
|
|
|
|
SOCMaker::logger.proc( "START of creating top-level '" + file_name + "'" )
|
SOCMaker::logger.proc( "START of creating top-level '" + file_name + "'" )
|
|
|
|
|
#
|
#
|
# Create a unique list of cores and
|
# Create a unique list of cores and
|
# add every core to your implementation.
|
# add every core to your implementation.
|
# Even if there are multiple instances of a core,
|
# Even if there are multiple instances of a core,
|
# we need to decalre it only once
|
# we need to decalre it only once
|
#
|
#
|
@cores.values.uniq{|x| x.type }.each do |inst; spec|
|
@cores.values.uniq{|x| x.type }.each do |inst; spec|
|
|
|
spec = SOCMaker::lib.get_core( inst.type )
|
spec = SOCMaker::lib.get_core( inst.type )
|
SOCMaker::lib.check_nil( spec, "Can't find #{ inst.type } in SOC library" )
|
SOCMaker::lib.check_nil( spec, "Can't find #{ inst.type } in SOC library" )
|
|
|
coder.add_core_declaration( inst.type, spec )
|
coder.add_core_declaration( inst.type, spec )
|
end
|
end
|
|
|
#core_instances = {}
|
#core_instances = {}
|
#@cores.each do |inst_name, _core_inst|
|
#@cores.each do |inst_name, _core_inst|
|
# # the corresponding core from SOC lib
|
# # the corresponding core from SOC lib
|
# core_def = SOCMaker::lib.get_core( _core_inst[ :type ] )
|
# core_def = SOCMaker::lib.get_core( _core_inst[ :type ] )
|
# core_instances[ inst_name ] = SOCMaker::CoreInst.new( core_def, _core_inst[ :params ] )
|
# core_instances[ inst_name ] = SOCMaker::CoreInst.new( core_def, _core_inst[ :params ] )
|
#end
|
#end
|
|
|
|
|
@cores.each do |inst_name, inst|
|
@cores.each do |inst_name, inst|
|
coder.add_core_inst( inst_name.to_s, inst )
|
coder.add_core_inst( inst_name.to_s, inst )
|
end
|
end
|
|
|
|
|
|
|
# Iterate over all connections:
|
# Iterate over all connections:
|
# - create signal instances
|
# - create signal instances
|
# - add assignments
|
# - add assignments
|
#
|
#
|
@cons.each do |con_name, con_def|
|
@cons.each do |con_name, con_def|
|
gen_toplevel_con( con_name.to_s,
|
gen_toplevel_con( con_name.to_s,
|
con_def[ :rule ],
|
con_def[ :rule ],
|
con_def[ :mapping ][0],
|
con_def[ :mapping ][0],
|
con_def[ :mapping ][1],
|
con_def[ :mapping ][1],
|
coder )
|
coder )
|
|
|
end
|
end
|
|
|
SOCMaker::logger.proc( "writing top-level" )
|
SOCMaker::logger.proc( "writing top-level" )
|
|
|
file_dir = File.join( SOCMaker::conf[ :build_dir ],
|
file_dir = File.join( SOCMaker::conf[ :build_dir ],
|
SOCMaker::conf[ :hdl_dir ] )
|
SOCMaker::conf[ :hdl_dir ] )
|
::FileUtils.mkdir_p file_dir
|
::FileUtils.mkdir_p file_dir
|
file_path = File.join( file_dir, file_name )
|
file_path = File.join( file_dir, file_name )
|
File.open( file_path, 'w' ) do |f|
|
File.open( file_path, 'w' ) do |f|
|
f.write( coder.get_entity( self, "test" ) )
|
f.write( coder.get_entity( self, "test" ) )
|
end
|
end
|
SOCMaker::logger.proc( "END of creating top-level" )
|
SOCMaker::logger.proc( "END of creating top-level" )
|
|
|
end
|
end
|
|
|
|
|
def gen_toplevel_con( name, rule, src, dst, coder )
|
def gen_toplevel_con( name, rule, src, dst, coder )
|
|
|
src_inst = {};
|
src_inst = {};
|
dst_inst = {};
|
dst_inst = {};
|
|
|
# fetch somehow the spec
|
# fetch somehow the spec
|
ifc_spec = SOCMaker::lib.get_ifc(
|
ifc_spec = SOCMaker::lib.get_ifc(
|
@cores[ src.keys.first ].defn.interfaces[ src.values.first ].name,
|
get_core_def( src.keys.first.to_s ).interfaces[ src.values.first ].name,
|
@cores[ src.keys.first ].defn.interfaces[ src.values.first ].version )
|
get_core_def( src.keys.first.to_s ).interfaces[ src.values.first ].version )
|
|
|
length_tmp = {};
|
|
|
|
|
port_used_tmp = {};
|
ifc_spec.ports.keys.each do |_name|
|
ifc_spec.ports.keys.each do |_name|
|
|
# TODO: bis dahin konnte angenommen werden, dass self auch eine Art instanz ist,
|
|
# aber hier geht das nicht mehr, weil get_len nur für CoreInst definiert ist.
|
|
#
|
|
|
|
|
# create a length table
|
# create a length table
|
length_tmp[ _name ] = []
|
port_used_tmp[ _name ] = false
|
dst.each do |inst_name, ifc_name|
|
dst.each do |inst_name, ifc_name|
|
length_tmp[ _name ] << @cores[ inst_name ].get_len( ifc_name, _name )
|
port_used_tmp[ _name ] ||= get_core_def( inst_name ).implements_port?( ifc_name, _name )
|
end
|
end
|
src.each do |inst_name, ifc_name|
|
src.each do |inst_name, ifc_name|
|
length_tmp[ _name ] << @cores[ inst_name ].get_len( ifc_name, _name )
|
port_used_tmp[ _name ] ||= get_core_def( inst_name ).implements_port?( ifc_name, _name )
|
end
|
end
|
|
|
end
|
end
|
|
|
# getting the maximum length for each signal
|
# getting the maximum length for each signal
|
max_length = Hash[ length_tmp.map{ |key, arr| [ key, arr.max ] } ]
|
# max_length = Hash[ length_tmp.map{ |key, arr| [ key, arr.max ] } ]
|
|
|
coder.ifc_declaration( ifc_spec, name, max_length )
|
# coder.ifc_declaration( ifc_spec, name, max_length )
|
|
|
|
|
|
|
src.keys.each do |inst_name|
|
src.keys.each do |inst_name|
|
src_inst[ inst_name ] = @cores[ inst_name ]
|
src_inst[ inst_name ] = @cores[ inst_name ]
|
end
|
end
|
dst.keys.each do |inst_name|
|
dst.keys.each do |inst_name|
|
dst_inst[ inst_name ] = @cores[ inst_name ]
|
dst_inst[ inst_name ] = @cores[ inst_name ]
|
end
|
end
|
|
|
|
|
|
|
coder.ifc_assignment( ifc_spec, name, max_length, src_inst, dst_inst, src, dst )
|
# coder.ifc_assignment( ifc_spec, name, max_length, src_inst, dst_inst, src, dst )
|
|
|
end
|
end
|
|
|
def copy_files
|
def copy_files
|
|
|
SOCMaker::logger.proc( "START of copying all HDL files" )
|
SOCMaker::logger.proc( "START of copying all HDL files" )
|
|
|
#
|
#
|
# Create a unique list of cores and
|
# Create a unique list of cores and
|
# for every core, create a directory and copy files
|
# for every core, create a directory and copy files
|
#
|
#
|
@cores.values.uniq{|x| x.type }.each do |core_inst; core_def, dst_dir|
|
@cores.values.uniq{|x| x.type }.each do |core_inst; core_def, dst_dir|
|
|
|
core_def = SOCMaker::lib.get_core( core_inst.type )
|
core_def = SOCMaker::lib.get_core( core_inst.type )
|
|
|
# create destination directory name and ensure, that it is exist
|
# create destination directory name and ensure, that it is exist
|
dst_dir = get_and_ensure_dst_dir!( core_def.name )
|
dst_dir = get_and_ensure_dst_dir!( core_def.name )
|
|
|
# copy each file into destination dir
|
# copy each file into destination dir
|
core_def.hdlfiles.each do |file, val|
|
core_def.hdlfiles.each do |file, val|
|
file_path = File.join( core_def.dir, val.path )
|
file_path = File.join( core_def.dir, val.path )
|
dst_path = File.join( dst_dir, file.to_s )
|
dst_path = File.join( dst_dir, val.path )
|
SOCMaker::logger.proc( "copy #{file_path} to #{ dst_path} " )
|
SOCMaker::logger.proc( "copy #{file_path} to #{ dst_path} " )
|
|
FileUtils.mkdir_p(File.dirname(dst_path))
|
FileUtils.cp( file_path, dst_path )
|
FileUtils.cp( file_path, dst_path )
|
end
|
end
|
|
|
|
|
|
|
#
|
#
|
# handle the static parameters
|
# handle the static parameters
|
# (search and replace in pakckage/include files)
|
# (search and replace in pakckage/include files)
|
core_def.static_parameters.each do |file, param|
|
core_def.static_parameters.each do |file, param|
|
|
|
token_val_map = {}
|
token_val_map = {}
|
param.parameters.each do |n,p|
|
param.parameters.each do |n,p|
|
|
|
if @static[ core_inst.type.to_sym ] != nil and
|
if @static[ core_inst.type.to_sym ] != nil and
|
@static[ core_inst.type.to_sym ][ n ] != nil
|
@static[ core_inst.type.to_sym ][ n ] != nil
|
|
|
# use value defined in soc-spec
|
# use value defined in soc-spec
|
token_val_map[ p.token ] = @static[ core_inst.type.to_sym ][ n ]
|
token_val_map[ p.token ] = @static[ core_inst.type.to_sym ][ n ]
|
else
|
else
|
# use default value from core-spec
|
# use default value from core-spec
|
token_val_map[ p.token ] = p.default
|
token_val_map[ p.token ] = p.default
|
end
|
end
|
|
|
end
|
end
|
|
|
# create file paths
|
# create file paths
|
src_path = File.join( core_def.dir, param.path )
|
src_path = File.join( core_def.dir, param.path )
|
dst_dir = get_and_ensure_dst_dir!( core_def.name )
|
dst_dir = get_and_ensure_dst_dir!( core_def.name )
|
dst_path = File.join( dst_dir, param.file_dst )
|
dst_path = File.join( dst_dir, param.file_dst )
|
|
|
|
|
# process each line of input file
|
# process each line of input file
|
# and replace tokens by value via
|
# and replace tokens by value via
|
# regular expression
|
# regular expression
|
File.open( dst_path, 'w' ) do |dst_f|
|
File.open( dst_path, 'w' ) do |dst_f|
|
File.open( src_path ) do |src_f|
|
File.open( src_path ) do |src_f|
|
SOCMaker::logger.proc( "create #{dst_path} from #{ src_path} " )
|
SOCMaker::logger.proc( "create #{dst_path} from #{ src_path} " )
|
while line = src_f.gets
|
while line = src_f.gets
|
token_val_map.each { |token, val| line = line.sub( Regexp.new( token.to_s ), val.to_s ) }
|
token_val_map.each { |token, val| line = line.sub( Regexp.new( token.to_s ), val.to_s ) }
|
dst_f.puts line
|
dst_f.puts line
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
|
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
|
|
SOCMaker::logger.proc( "END of copying all HDL files" )
|
SOCMaker::logger.proc( "END of copying all HDL files" )
|
end
|
end
|
|
|
|
|
def ==(o)
|
def ==(o)
|
o.class == self.class &&
|
o.class == self.class &&
|
o.cores == self.cores &&
|
o.cores == self.cores &&
|
o.cons == self.cons &&
|
o.cons == self.cons &&
|
o.static == self.static &&
|
o.static == self.static &&
|
super( o )
|
super( o )
|
end
|
end
|
|
|
|
|
|
def to_s
|
|
|
|
tmp = "_________ SOC #{@name}: _______\n" +
|
|
super +
|
|
"\n__connections__\n"
|
|
|
|
@cons.each do |_con_name, con_def|
|
|
tmp += "#{_con_name}: #{con_def}\n"
|
|
end
|
|
|
|
tmp += "\n__cores__\n"
|
|
@cores.each do |inst_name, inst|
|
|
tmp += "#{inst_name}:\n#{inst}\n"
|
|
end
|
|
tmp += "'''''''''''''''''''''''''''''''''''\n"
|
|
return tmp
|
|
end
|
|
|
|
|
end # class SOCSpec
|
end # class SOCSpec
|
end # module SOCMaker
|
end # module SOCMaker
|
|
|
|
|
# vim: noai:ts=2:sw=2
|
# vim: noai:ts=2:sw=2
|
|
|