URL
https://opencores.org/ocsvn/soc_maker/soc_maker/trunk
Subversion Repositories soc_maker
[/] [soc_maker/] [trunk/] [lib/] [soc_maker/] [core_inst.rb] - Rev 6
Go to most recent revision | Compare with Previous | Blame | View Log
###############################################################
#
# File: core_inst.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 core instantiation within
# a SOC. It contains a params (parameters) hash,
# which defines, which parameters are set to which values.
# The type field is used to identify the SOCMaker::CoreDef
# and the field @defn is initialized as reference to
# the corresponding CoreDef instance.
#
#
###############################################################
module SOCMaker
class CoreInst
include ERR
attr_accessor :defn
attr_accessor :type
attr_accessor :params
def initialize( type, params = {} )
init_with( 'type' => type,
'params' => params )
verify
end
def encode_with( coder )
%w[ type params ].
each { |v| coder[ v ] = instance_variable_get "@#{v}" }
end
def init_with( coder )
serr_if( coder[ 'type' ] == nil,
"no type is provided for a core instance",
field: "type" )
@type = coder[ 'type' ]
@params = coder[ 'params' ] || {}
serr_if( !@params.is_a?( Hash ), 'Parameters are not given as hash',
field: 'params' )
end
def ports
@ports.each_with_index do |(name, port_def), i|
yield( name.to_s, port_def[ :len ], port_def[ :dir ], i==@ports.size-1 )
end
end
def generics
@defn.generics do |name, type, default_value, is_last|
value = @params[ name.to_sym ];
value = value
value = default_value if value == nil
yield( name.to_s, type, value, is_last )
end
end
def get_len( ifc_name, port_spec_name, inst = nil )
if inst == nil
tmp = @defn.interfaces[ ifc_name.to_sym ].
ports.select{ |key,hash| hash.defn == port_spec_name.to_s }.
keys.first.to_s
return tmp.size == 0 ? 0 : @ports[ tmp.to_sym ][ :len ]
else
if inst == @name
return get_len( ifc_name, port_spec_name )
else
return @defn.get_len( ifc_name, port_spec_name, inst )
end
end
end
def implements_port?( ifc_name, port_spec_name )
@defn.implements_port?( ifc_name, port_spec_name )
end
def get_port( ifc_name, port_spec_name )
tmp = @defn.interfaces[ ifc_name.to_sym ].
ports.select{ |key,hash| hash.defn == port_spec_name.to_s }.
keys.first.to_s
return [ tmp, @ports[ tmp.to_sym ] ]
end
def verify
@defn = SOCMaker::lib.get_core( @type )
# check, if the instance parameters in the core definition
@params.each do |param_name, value|
verr_if( @defn.inst_parameters[ param_name ] == nil,
"Parameter not found: " + param_name.to_s,
field: 'params' )
end
## auto-complete parameters with default values
@defn.inst_parameters.each do |param_name, param|
# auto-complete to default values
@params[ param_name ] ||= param.default
end
# @_params ||= {}
# if @params != nil
# @params.each do |name, val|
#
# param_type = defn.inst_parameters[ name ].type
#
# if val.is_a? String
# eval_match = SOCMaker::conf[ :eval_regex ].match( val )
# #TODO error handling
# if eval_match
# #eval_func = eval_match.captures[0]
# @_params[ name ] = { value: eval( eval_str ).to_s, type: param_type }
# else
# @_params[ name ] = { value: val, type: param_type }
# end
# else
# @_params[ name ] = { value: val, type: param_type }
# end
# end
# end
@ports ||= {}
@defn.ports do |port_name, port_dir, port_len, is_last |
if port_len.is_a?( String )
param_match = SOCMaker::conf[ :length_regex ].match( port_len )
if param_match and @params[ port_len.to_sym ] != nil
tmp =@params[ port_len.to_sym ]
tmp = tmp.to_i if tmp.is_a?( String )
@ports[ port_name.to_sym ] = { len: tmp, dir: port_dir }
else
SOCMaker::logger.error( "Failed to evaluate #{port_len} for port #{port_name}" )
end
else
@ports[ port_name.to_sym ] = { len: port_len, dir: port_dir }
end
end
lerr_if( @defn == nil, 'Core not found in lib',
field: 'cores' )
end
def get_core_def( inst )
tmp = @defn.get_core_def( inst )
if tmp != nil
return tmp
elsif inst == @name
return self
else
return nil
end
end
def gen_toplevel( coder = VHDLCoder.new() )
#
# create filename
#
file_name = @defn.name.dup
if coder.is_a?( VHDLCoder )
file_name << ".vhd"
elsif coder.is_a?( VerilogCoder )
file_name << ".v"
else
perr_if( true,
"No valid coder" )
end
SOCMaker::logger.proc( "START of creating top-level '" + file_name + "'" )
SOCMaker::logger.proc( "verifying first ..." )
# TODO: this is a fix, that the parameters in core_inst.ports are updated.
# A good approach for verifying, which checks the whole consistency, needs
# to be done
@defn.cores.each do |inst_name, inst|
inst.verify
end
#
# Create a unique list of cores and
# add every core to your implementation.
# Even if there are multiple instances of a core,
# we need to decalre it only once
#
@defn.cores.values.uniq{|x| x.type }.each do |inst; spec|
spec = SOCMaker::lib.get_core( inst.type )
SOCMaker::lib.check_nil( spec, "Can't find #{ inst.type } in SOC library" )
coder.add_core_declaration( inst.type, spec )
end
#core_instances = {}
#@cores.each do |inst_name, _core_inst|
# # the corresponding core from SOC lib
# core_def = SOCMaker::lib.get_core( _core_inst[ :type ] )
# core_instances[ inst_name ] = SOCMaker::CoreInst.new( core_def, _core_inst[ :params ] )
#end
@defn.cores.each do |inst_name, inst|
coder.add_core_inst( inst_name.to_s, inst )
end
# Iterate over all connections:
# - create signal instances
# - add assignments
#
@defn.cons.each do |con_name, con_def|
gen_toplevel_con( con_name.to_s,
con_def[ :rule ],
con_def[ :mapping ][0],
con_def[ :mapping ][1],
coder )
end
SOCMaker::logger.proc( "writing top-level" )
file_dir = File.join( SOCMaker::conf[ :build_dir ],
SOCMaker::conf[ :hdl_dir ] )
::FileUtils.mkdir_p file_dir
file_path = File.join( file_dir, file_name )
File.open( file_path, 'w' ) do |f|
f.write( coder.get_entity( self, "test" ) )
end
SOCMaker::logger.proc( "END of creating top-level" )
end
def gen_toplevel_con( name, rule, src, dst, coder )
src_inst = {};
dst_inst = {};
# fetch somehow the spec
ifc_spec = SOCMaker::lib.get_ifc(
get_core_def( src.keys.first.to_s ).interfaces[ src.values.first ].name,
get_core_def( src.keys.first.to_s ).interfaces[ src.values.first ].version )
#port_used = {};
length_tmp = {};
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
#port_used[ _name ] = false
#dst.each do |inst_name, ifc_name|
# port_used[ _name ] ||= get_core_def( inst_name ).implements_port?( ifc_name, _name )
#end
#src.each do |inst_name, ifc_name|
# port_used[ _name ] ||= get_core_def( inst_name ).implements_port?( ifc_name, _name )
#end
length_tmp[ _name ] = []
dst.each do |inst_name, ifc_name|
length_tmp[ _name ] << get_len( ifc_name, _name, inst_name )
end
src.each do |inst_name, ifc_name|
length_tmp[ _name ] << get_len( ifc_name, _name, inst_name )
end
end
# getting the maximum length for each signal
max_length = Hash[ length_tmp.map{ |key, arr| [ key, arr.max ] } ]
p max_length
coder.ifc_declaration( ifc_spec, name, max_length )
src.keys.each do |inst_name|
src_inst[ inst_name ] = @defn.cores[ inst_name ]
end
dst.keys.each do |inst_name|
dst_inst[ inst_name ] = @defn.cores[ inst_name ]
end
coder.ifc_assignment( ifc_spec, name, max_length, src_inst, dst_inst, src, dst )
end
def to_s
"type: #{type}\n" +
"params: #{params}\n"
end
def ==(o)
o.class == self.class &&
o.type == self.type &&
o.params == self.params
end
end # CoreInst
end # SOCMaker
# vim: noai:ts=2:sw=2
Go to most recent revision | Compare with Previous | Blame | View Log