URL
https://opencores.org/ocsvn/soc_maker/soc_maker/trunk
Subversion Repositories soc_maker
Compare Revisions
- This comparison shows the changes necessary to convert path
/soc_maker/trunk/lib/soc_maker
- from Rev 8 to Rev 9
- ↔ Reverse comparison
Rev 8 → Rev 9
/parameter.rb
63,8 → 63,8
attr_accessor :description |
attr_accessor :choice |
|
def initialize( type, options = {} ) |
init_with( { 'type' => type }.merge( options ) ) |
def initialize( type, optional = {} ) |
init_with( { 'type' => type }.merge( optional ) ) |
end |
|
def encode_with( coder ) |
/hdl_coder.rb
267,7 → 267,7
tmp = "#{port_tmp_name} <= " |
# loop over instances |
src_inst_sel.each_with_index do |(inst_name, inst), i| |
( tmp_name, port) = inst.get_port( src_ifc_sel[ inst_name ], port_name ) |
( tmp_name, port) = inst.port( src_ifc_sel[ inst_name ], port_name ) |
if port != nil |
if port[ :len ] < length[ port_name ] |
tmp << "\"" + "0" * ( length[ port_name ] - port[ :len ] ) + "\" & " |
291,7 → 291,7
# assign to destination |
dst_inst_sel.each_with_index do |(inst_name, inst), i| |
if not inst == nil #TODO |
( tmp_name, port) = inst.get_port( dst_ifc_sel[ inst_name ], port_name ) |
( tmp_name, port) = inst.port( dst_ifc_sel[ inst_name ], port_name ) |
if port != nil |
tmp << "#{inst_name}_#{tmp_name} <= #{port_tmp_name}" |
tmp << "( #{port[ :len ]}-1 downto 0 )" if port[ :len ] > 1 |
310,7 → 310,7
# dst_inst_sel.each_with_index do |(inst_name, inst), i| |
# p inst_name |
# p port_name |
# ( tmp_name, port) = inst.get_port( dst_ifc_sel[ inst_name ], port_name ) |
# ( tmp_name, port) = inst.port( dst_ifc_sel[ inst_name ], port_name ) |
# tmp << "#{inst_name}_#{tmp_name} <= ( others => 'X' );\n" |
# end |
# @asgn_part << tmp; |
/conf.rb
62,10 → 62,10
return @@inst |
end |
|
def initialize( options = {} ) |
def initialize( optional = {} ) |
|
|
init_with( options.merge( { 'data' => { |
init_with( optional.merge( { 'data' => { |
# the name of this application/tool |
:app_name => 'SOC-Maker', |
|
122,7 → 122,12
|
@data_ro = { |
|
:yaml_classes => [ SOCMaker::CoreDef, SOCMaker::SOCDef, SOCMaker::IfcSpc, SOCMaker::LibInc, SOCMaker::Conf ], |
:yaml_classes => [ SOCMaker::CoreDef, |
SOCMaker::SOCDef, |
SOCMaker::IfcSpc, |
SOCMaker::LibInc, |
SOCMaker::Conf, |
SOCMaker::CoreInst ], |
|
# Regular expression, which is evaluatted to detect values like |
# eval function_name |
/core_inst.rb
31,20 → 31,18
# |
# |
############################################################### |
# |
# 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 |
|
###### |
# |
# This class represents a core instantiation within |
# a SOC. It contains a parameter-hash (@params), |
# which is used to define, 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. |
class CoreInst |
include ERR |
|
59,11 → 57,23
'params' => params ) |
|
end |
|
# |
# Encoder function (to yaml) |
# |
# +coder+:: An instance of the Psych::Coder to encode this class to a YAML file |
# |
def encode_with( coder ) |
%w[ type params ]. |
each { |v| coder[ v ] = instance_variable_get "@#{v}" } |
end |
|
# |
# Initialization function (from yaml) |
# |
# +coder+:: An instance of the Psych::Coder to init this class from a YAML file |
# |
# |
def init_with( coder ) |
|
serr_if( coder[ 'type' ] == nil, |
78,55 → 88,17
|
end |
|
def ports( *args ) |
if args.size == 0 |
@ports.each_with_index do |(name, port_def), i| |
yield( name.to_s, port_def[ :dir ], port_def[ :len ], port_def[ :default ], i==@ports.size-1 ) |
end |
elsif args.size == 1 |
@ifcs[ args.first.to_sym ].each do |name, port_def, i| |
yield( name.to_s, port_def[ :dir ], port_def[ :len ], port_def[ :default ], i==@ports.size-1 ) |
end |
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 |
|
|
|
|
|
|
# |
# Get a port, identified by the interface and port name |
# |
# +ifc_name+:: name of the interface |
# +port_spec_name+:: name of the port |
# |
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 |
|
|
# TODO do we need this? |
# Runs a consistency check and creates an internal |
# hash, which contains all evaluated ports. |
# Because the core-definition may contain variable port sizes, |
# which depend on the instance, these sizes need to be evaluated. |
# This is also done here and the result is stored in @_ifcs_evaluated. |
# |
# |
# def implements_port?( ifc_name, port_spec_name ) |
# @defn.implements_port?( ifc_name, port_spec_name ) |
# end |
|
|
def consistency_check |
|
@defn = SOCMaker::lib.get_core( @type ) |
146,58 → 118,10
@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 |
|
|
# |
# TODO merge these two loops and create one hash |
### |
# |
# create our own ports hash |
# |
@ports ||= {} |
@defn.ports do |port_name, port_dir, port_len, default, 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, default: default } |
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, default: default } |
end |
end |
|
|
@ifcs ||= {} |
@_ifcs_evaluated ||= {} |
@defn.interfaces.keys.each do |ifc_name| |
@ifcs[ ifc_name ] = {} |
@defn.ports( ifc_name ) do |port_name, port_dir, port_len, default, is_last | |
|
@_ifcs_evaluated[ ifc_name ] = {} |
@defn.ports( ifc_name.to_s ) do |port_name, port_dir, port_len, default, is_last | |
if port_len.is_a?( String ) |
param_match = SOCMaker::conf[ :length_regex ].match( port_len ) |
|
204,97 → 128,31
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 ) |
@ifcs[ ifc_name ][ port_name.to_sym ] = { len: tmp, dir: port_dir, default: default } |
@_ifcs_evaluated[ ifc_name ][ port_name.to_sym ] = { len: tmp, dir: port_dir, default: default } |
else |
SOCMaker::logger.error( "Failed to evaluate #{port_len} for port #{port_name}" ) |
end |
else |
@ifcs[ ifc_name ][ port_name.to_sym ] = { len: port_len, dir: port_dir, default: default } |
@_ifcs_evaluated[ ifc_name ][ port_name.to_sym ] = { len: port_len, dir: port_dir, default: default } |
end |
# |
#puts "#{port_def_ref}, #{port_name}, #{port_dir}, #{port_default}" |
end |
end |
|
# lerr_if( @defn == nil, 'Core not found in lib', |
# field: 'cores' ) |
|
|
|
@defn.consistency_check |
|
|
end |
|
|
|
# |
# Returns the length of a port within an interface. |
# If no instance is given, we know that it is |
# a toplevel interface. |
# Otherwise we check for this and we do a recursive call. |
# If this port is within a interface of a core, we |
# pass the call to the core-definition of this instance, which |
# knows all cores. |
# |
# +ifc_name+:: name of the interface |
# +port_spec_name+:: name of the port |
# +inst+:: name of the instance (optional), default is nil |
# |
def get_port_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 == @defn.name.to_sym |
return get_port_len( ifc_name, port_spec_name ) |
else |
return @defn.get_port_len( ifc_name, port_spec_name, inst ) |
end |
end |
end |
|
|
# |
# Returns the core definition for an instance (identified by its name) |
# |
# +inst+:: name of the instance |
# |
def get_core_def( inst ) |
if inst == @defn.name |
return @defn |
else |
tmp = @defn.get_core_def( inst ) |
perr_if( tmp == nil, "#Processing error: {inst} not found by get_core_def" ) |
return tmp |
end |
end |
|
|
# |
# Returns a core instance, identified by its name. |
# If it is not a sub-core, we return our self |
# |
# +inst+:: name of the instance |
# |
def get_core_inst( inst ) |
if @defn.cores[ inst ] != nil |
return @defn.cores[ inst ] |
else |
return self |
end |
end |
|
|
# |
# Generate toplevel hdl file for this instance. |
# This assumes, that this instance represents a SOC with |
# further instances. |
# |
# |
# +coder+:: A HDL coder, which is used to create the auto-generated HDL (optional). |
# If no coder is given, a VHDLCoder is used. |
# +coder+:: An instance of the SOCMaker::HDLCoder, which is used to |
# create the auto-generated HDL (optional). |
# If no coder is given, a SOCMaker::VHDLCoder is used. |
# |
# |
def gen_toplevel( coder = VHDLCoder.new ) |
345,7 → 203,6
end |
|
assign_unused_to_default( coder ) |
|
|
# |
# Write content to the file |
363,8 → 220,159
|
|
|
# |
# Iterate over all ports and call the block with |
# - port-name |
# - port length |
# - default value |
# - is-last value |
# |
# If no argument is given, all ports of this instance are processed. |
# If arguments are given, each argument is supposed to the name of |
# a interface. All specified interfaces with all ports are processed. |
# |
# +args+:: Optional list of interface names |
# |
# |
def ports( *args ) |
|
if args.size == 0 |
ifc_sel = @_ifcs_evaluated |
else |
ifc_sel = @_ifcs_evaluated.select{ |k,v| args.include?( k.to_s ) } |
end |
|
ifc_sel.each_with_index do |(ifc_name, ifc), i_ifc| |
ifc.each_with_index do |(port_name, port_def), i_port| |
yield( port_name.to_s, |
port_def[ :dir ], |
port_def[ :len ], |
port_def[ :default ], |
i_port==ifc.size-1 && i_ifc == ifc_sel.size-1 ) |
end |
end |
end |
|
# |
# Iterate over all generics and call the block with |
# - generic-name |
# - generic-type |
# - the value |
# - is-last information |
# |
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 |
|
|
|
|
|
|
|
# |
# Returns a port, identified by the interface and port name |
# |
# +ifc_name+:: name of the interface |
# +port_spec_name+:: name of the port |
# |
def 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, @_ifcs_evaluated[ ifc_name.to_sym ][ tmp.to_sym ] ] |
end |
|
# |
# Returns the length of a port within an interface. |
# If no instance is given, we know that it is |
# a toplevel interface. |
# Otherwise we check for this and we do a recursive call. |
# If this port is within a interface of a core, we |
# pass the call to the core-definition of this instance, which |
# knows all cores. |
# |
# +ifc_name+:: name of the interface |
# +port_spec_name+:: name of the port |
# +inst+:: name of the instance (optional), default is nil |
# |
def port_length( 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 : @_ifcs_evaluated[ ifc_name.to_sym ][ tmp.to_sym ][ :len ] |
else |
if inst == @defn.name.to_sym |
return port_length( ifc_name, port_spec_name ) |
else |
return @defn.port_length( ifc_name, port_spec_name, inst ) |
end |
end |
end |
|
# |
# Returns the core definition for an instance (identified by its name) |
# |
# +inst+:: name of the instance |
# |
def core_definition( inst ) |
if inst == @defn.name |
return @defn |
else |
tmp = @defn.core_definition( inst ) |
perr_if( tmp == nil, "#Processing error: {inst} not found by core_definition" ) |
return tmp |
end |
end |
|
# |
# Returns a core instance, identified by its name. |
# If it is not a sub-core, we return our self |
# |
# +inst+:: name of the instance |
# |
def core_instance( inst ) |
if @defn.cores[ inst ] != nil |
return @defn.cores[ inst ] |
else |
return self |
end |
end |
|
|
|
|
|
|
# |
# Returns a string describing this instance |
# |
def to_s |
"type: #{type}\n" + |
"params: #{params}\n" |
end |
|
# |
# Equality operator |
# |
def ==(o) |
o.class == self.class && |
o.type == self.type && |
o.params == self.params |
end |
|
|
|
|
|
|
# |
# Assign default values for unused interfaces. |
# This is just a helper function and is used by gen_toplevel |
# |
400,7 → 408,6
end |
|
|
|
# |
# This function is called during the toplevel generation |
# for each connection. |
421,8 → 428,8
# and searching for the core-definition. |
# |
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 ) |
core_definition( src.keys.first.to_s ).interfaces[ src.values.first ].name, |
core_definition( src.keys.first.to_s ).interfaces[ src.values.first ].version ) |
|
|
# |
438,10 → 445,10
ifc_spec.ports.keys.each do |_name| |
length_tmp[ _name ] = [] |
dst.each do |inst_name, ifc_name| |
length_tmp[ _name ] << get_port_len( ifc_name, _name, inst_name ) |
length_tmp[ _name ] << port_length( ifc_name, _name, inst_name ) |
end |
src.each do |inst_name, ifc_name| |
length_tmp[ _name ] << get_port_len( ifc_name, _name, inst_name ) |
length_tmp[ _name ] << port_length( ifc_name, _name, inst_name ) |
end |
end |
max_length = Hash[ length_tmp.map{ |key, arr| [ key, arr.max ] } ] |
453,10 → 460,10
# the value. |
# |
src.keys.each do |inst_name| |
src_inst[ inst_name ] = get_core_inst( inst_name ) |
src_inst[ inst_name ] = core_instance( inst_name ) |
end |
dst.keys.each do |inst_name| |
dst_inst[ inst_name ] = get_core_inst( inst_name ) |
dst_inst[ inst_name ] = core_instance( inst_name ) |
end |
|
# |
467,26 → 474,18
end |
|
|
# |
# Returns a string describing this instance |
# |
def to_s |
"type: #{type}\n" + |
"params: #{params}\n" |
end |
|
# |
# Equal operator |
# |
def ==(o) |
o.class == self.class && |
o.type == self.type && |
o.params == self.params |
end |
|
# TODO |
# private: assign_unused_to_default, :gen_toplevel_con |
|
|
|
|
|
|
private :assign_unused_to_default, :gen_toplevel_con |
|
|
|
end # CoreInst |
end # SOCMaker |
|
/component.rb
33,29 → 33,6
############################################################### |
# |
# Description: |
# This class represents an abstract component. |
# It is one of the central classes and holds data, |
# which is used to describe and instanciate a core or SOC. |
# |
# The following fields are defined and used |
# by CoreDef and SOCDef |
# - name : name of the core (mandatory) |
# - version : version of the core (mandatory) |
# - toplevel : toplevel name (mandatory) |
# - description : description of this core |
# - date : creation date |
# - license : license of this core |
# - licensefile : location of the license file |
# - author : author of this core |
# - authormail : author-mail of this core |
# - vccmd : a version control command, which is used |
# to download the files |
# - interfaces : interfaces which are implemented |
# see SOCMaker::IfcSpc |
# - inst_parameters : hash of instantiation parameters |
# see SOCMaker::Parameter |
# - static_parameters : hash of static parameters |
# see SOCMaker::SParameter |
######## |
# |
# TODO |
64,30 → 41,87
############################################################### |
|
|
|
module SOCMaker |
|
|
|
###### |
# |
# This class represents an abstract component. |
# It is one of the central classes and holds data, |
# which is used to describe a core or System-On-Chip (SOC). |
# |
# |
class Component |
include ERR |
include YAML_EXT |
|
|
# name of the core (mandatory) |
attr_accessor :name |
|
# version of the core (mandatory) |
attr_accessor :version |
|
# toplevel name (mandatory) |
attr_accessor :toplevel |
|
# description of this core |
attr_accessor :description |
|
# creation date |
attr_accessor :date |
|
# license of this core |
attr_accessor :license |
|
# location of the license file |
attr_accessor :licensefile |
|
# author of this core |
attr_accessor :author |
|
# author-mail of this core |
attr_accessor :authormail |
|
# a version control command, which is used to download the files |
attr_accessor :vccmd |
|
# interfaces which are implemented see SOCMaker::IfcSpc |
attr_accessor :interfaces |
|
attr_accessor :functions |
|
# hash of instantiation parameters see SOCMaker::Parameter |
attr_accessor :inst_parameters |
|
# hash of static parameters see SOCMaker::SParameter |
attr_accessor :static_parameters |
def initialize( name, version, toplevel, options = {} ) |
|
|
# |
# Constructor |
# The three attributes are required, and all other attributes |
# can be given as a optinal hash |
# |
# *name*:: Name of this component |
# *version*:: Version of this component |
# *toplevel*:: Toplevel name of this component |
# *optional*:: Non-mandatory values, which can be set during initialization. |
# |
# |
def initialize( name, version, toplevel, optional = {} ) |
init_with( { 'name' => name, |
'version' => version, |
'toplevel' => toplevel }.merge( options ) ) |
'toplevel' => toplevel }.merge( optional ) ) |
end |
|
# |
# Encoder function (to yaml) |
# |
# +coder+:: An instance of the Psych::Coder to encode this class to a YAML file |
# |
def encode_with( coder ) |
%w[ name version description date license licensefile |
author authormail vccmd toplevel interfaces |
94,6 → 128,13
functions inst_parameters static_parameters ]. |
each { |v| coder[ v ] = instance_variable_get "@#{v}" } |
end |
|
# |
# Initialization function (from yaml) |
# |
# +coder+:: An instance of the Psych::Coder to init this class from a YAML file |
# |
# |
def init_with( coder ) |
|
serr_if( coder[ 'name' ] == nil, |
218,6 → 259,13
end |
|
|
# |
# Runs a consistency check: |
# Iterate over all interfaces and check, if the interface is |
# in the SOCMaker::Lib. |
# The function also checks also, if the ports defined by this |
# core is also defined in the interface. |
# |
def consistency_check |
@interfaces.values.each_with_index do | ifc, i_ifc; ifc_def| |
|
236,7 → 284,10
end |
|
|
def get_files |
# |
# Runs the Version Control System command via system(....) |
# |
def update_vcs |
unless self.vccmd.nil? or @vccmd.size == 0 |
#puts"cd #{@dir} && #{@vccmd}" |
system( "cd #{@dir} && #{vccmd} " ) |
245,119 → 296,91
|
|
|
|
|
# Iterates over all generic values of this component |
# and yield the call block with |
# - generic name |
# - generic type |
# - generic default |
# - is-last value |
def generics |
@inst_parameters.each_with_index do |(name, val), i| |
yield( name.to_s, val.type, val.default, i == @inst_parameters.size-1 ) |
|
_generic_name = name.to_s |
_generic_type = val.type |
_generic_default = val.default |
_is_last = i == @inst_parameters.size-1 |
yield( _generic_name , |
_generic_type , |
_generic_default, |
_is_last ) |
|
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 |
|
# |
# Iterates over interface list. |
# Iterates over interface list (if no argument is given) |
# or all specified interfaces. |
# For each interface, all ports are processed. |
# For each port within each interface, we lookup the port defn |
# and yield the call block with |
# - port-name |
# - port-definition |
# - info if last |
# - port-name |
# - port length |
# - default value |
# - is-last value |
# as argument |
# |
# An xor mechanism between port_dir and ifc=>dir is used |
# to determine the direction of a port, for example: |
# If the interface is declared as input (1) and a port is declared as input (1) |
# the resulting direction will be an output 1^1 = 0. |
# But if the overall interface direction is an output (0) and a port is declared |
# as input, the resulting direction will an input 0^1 = 1. |
# If the interface is declared as input (1) and a port is declared as input (1) |
# the resulting direction will be an output 1^1 = 0. |
# But if the overall interface direction is an output (0) and a port is declared |
# as input, the resulting direction will an input 0^1 = 1. |
# This allows to define a port-direction in the interface definition, |
# and toggle the directions on core-definition level. |
# |
# |
# *args*:: An optional list of interface names |
def ports( *args ) |
|
if args.size == 0 |
@interfaces.values.each_with_index do | ifc, i_ifc; ifc_def| |
|
# get interface definition |
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version ) |
@ifc_sel = @interfaces |
else |
@ifc_sel = @interfaces.select{ |k,v| args.include?( k.to_s ) } |
end |
|
# loop over ports in this interface |
ifc.ports.each_with_index do |(port_name, port_def), i_port; port_dir| |
@ifc_sel.values.each_with_index do | ifc, i_ifc; ifc_def| |
|
# get interface definition |
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version ) |
|
# the reference to the port in the definition |
defn_ref = port_def.defn.to_sym |
perr_if( !ifc_def.ports.has_key?( defn_ref ), |
"Can't find #{port_def} in" + |
"interface definition #{ifc_def.name} " + |
"version #{ifc_def.version}" ) |
yield( port_name.to_s, |
ifc_def.ports[ defn_ref ][:dir] ^ ifc.dir, |
port_def.len, |
ifc_def.ports[ defn_ref ][ :default ], |
( (i_port == ifc.ports.size-1 ) and (i_ifc == @interfaces.size-1 ) ) ) |
end |
end |
# loop over ports in this interface |
ifc.ports.each_with_index do |(port_name, port_def), i_port | |
|
elsif args.size == 1 |
|
# get interface (input is the name as string ) |
ifc = @interfaces[ args.first.to_sym ] |
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version ) |
|
# loop over all ports of this interface |
ifc.ports.each_with_index do |(port_name, port_def),i_port; port_dir| |
# the reference to the port in the definition |
defn_ref = port_def.defn.to_sym |
perr_if( !ifc_def.ports.has_key?( defn_ref ), |
"Can't find #{defn_ref} in" + |
"Can't find #{port_def} in" + |
"interface definition #{ifc_def.name} " + |
"version #{ifc_def.version}" ) |
yield( port_name.to_s, |
ifc_def.ports[ defn_ref ][:dir] ^ ifc.dir, |
port_def.len, |
ifc_def.ports[ defn_ref ][ :default ], |
( (i_port == ifc.ports.size-1 ) ) |
) |
#yield( port_def.to_s, |
#port_name.to_s, |
#port_dir ^ ifc.dir, |
#port_default ) |
|
_port_name = port_name.to_s |
_port_dir = ifc_def.ports[ defn_ref ][:dir] ^ ifc.dir |
_port_length = port_def.len |
_port_default = ifc_def.ports[ defn_ref ][ :default ] |
_is_last = ( (i_port == ifc.ports.size-1 ) and (i_ifc == @ifc_sel.size-1 ) ) |
yield( _port_name, _port_dir, _port_length, _port_default, _is_last ) |
end |
|
else |
# TODO |
end |
|
end |
|
|
|
# def implements_port?( ifc_name, port_spec_name ) |
# tmp = @interfaces[ ifc_name.to_sym ]. |
# ports.select{ |key,hash| hash.defn == port_spec_name.to_s }.keys |
|
# perr_if( tmp.size > 1, |
# "The port #{port_spec_name} of interface #{ifc_name} is implemented |
# multiple times" ) |
|
# return tmp.size == 1 |
# end |
|
def param_ok?( param_name, param_value ) |
param = inst_parameters[ param_name.to_sym ] |
param = static_parameters[ param_name.to_sym ] if param == nil |
return false if param == nil |
end |
|
|
|
# |
# Equality operator |
# |
def ==(o) |
|
tmp = ( o.class == self.class ) |
372,6 → 395,9
return true |
end |
|
# |
# Returns a string describing this instance |
# |
def to_s |
"version: #{@version}\n" + |
"toplevel: #{@toplevel}\n" + |
389,6 → 415,35
end |
|
|
|
|
|
# |
# Creates a core directory, if it doesn't exist. |
# The path of the target directoy depends |
# on SOCMaker::conf[ :build_dir ] and |
# on SOCMaker::conf[ :hdl_dir ]. |
# The resulting path is |
# ./#{SOCMaker::conf[ :build_dir ]}/#{SOCMaker::conf[ :hdl_dir ]}/dir_name |
# |
# *dir_name*:: Name of the target directory |
# |
def self.get_and_ensure_dst_dir!( dir_name ) |
dst_dir = File.expand_path( |
File.join( |
SOCMaker::conf[ :build_dir ], |
SOCMaker::conf[ :hdl_dir ], |
dir_name ) ) |
FileUtils.mkdir_p dst_dir |
return dst_dir |
end |
|
|
|
|
|
|
|
end # class CoreDef |
end # module SOCMaker |
|
/soc_def.rb
51,11 → 51,11
attr_accessor :cores |
attr_accessor :cons |
attr_accessor :static |
def initialize( name, version, toplevel, options = {} ) |
def initialize( name, version, toplevel, optional = {} ) |
|
init_with( { 'name' => name, |
'version' => version, |
'toplevel' => toplevel }.merge( options ) ) |
'toplevel' => toplevel }.merge( optional ) ) |
|
end |
|
128,15 → 128,15
end |
|
|
def get_port_len( ifc_name, port_name, inst ) |
def port_length( ifc_name, port_name, inst ) |
if @cores[ inst.to_sym ] != nil |
return @cores[ inst ].get_port_len( ifc_name, port_name ) |
return @cores[ inst ].port_length( ifc_name, port_name ) |
else |
return nil |
end |
end |
|
def get_core_def( inst ) |
def core_definition( inst ) |
if @cores[ inst.to_sym ] != nil |
return @cores[ inst.to_sym ].defn |
elsif inst == @name |
173,8 → 173,8
end |
|
|
core_def_1 = get_core_def( inst1 ) |
core_def_2 = get_core_def( inst2 ) |
core_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}" ) |
283,7 → 283,7
core_def = SOCMaker::lib.get_core( core_inst.type ) |
|
# create destination directory name and ensure, that it is exist |
dst_dir = get_and_ensure_dst_dir!( core_def.name ) |
dst_dir = Component.get_and_ensure_dst_dir!( core_def.name ) |
|
# copy each file into destination dir |
core_def.hdlfiles.each do |file, val| |
329,7 → 329,7
|
# create file paths |
src_path = File.join( core_def.dir, sparam.path ) |
dst_dir = get_and_ensure_dst_dir!( core_def.name ) |
dst_dir = Component::get_and_ensure_dst_dir!( core_def.name ) |
dst_path = File.join( dst_dir, sparam.file_dst ) |
|
|
/sparameter.rb
60,9 → 60,9
attr_accessor :file_dst |
attr_accessor :parameters |
|
def initialize( path, file_dst, options = {} ) |
def initialize( path, file_dst, optional = {} ) |
init_with( { 'path' => path, |
'file_dst' => file_dst }.merge( options ) ) |
'file_dst' => file_dst }.merge( optional ) ) |
end |
def encode_with( coder ) |
%w[ path file_dst parameters ]. |
126,9 → 126,9
class SParameterEntry < Parameter |
attr_accessor :token |
|
def initialize( type, token, options = {} ) |
def initialize( type, token, optional = {} ) |
init_with( { 'type' => type, |
'token' => token }.merge( options ) ) |
'token' => token }.merge( optional ) ) |
|
end |
def encode_with( coder ) |
/core_def.rb
33,20 → 33,7
############################################################### |
# |
# Description: |
# This class represents a core definition. |
# It is one of the central classes and holds data, |
# which is used to describe and instanciate this core. |
# In general, instances of this class desribe a core, |
# it's interface and parameters as well as the files, |
# which are required for synthesis/simulation. |
# |
# In addition to this core, there exist CoreInst, |
# which represents a concret instanciation of a definition |
# (see core_inst.rb). |
# This class adds two fields to SOCMaker::Component: |
# - hdlfiles : hash of SOCMaker::HDLFile (mandatory, |
# at least one file) |
# |
######## |
# |
# TODO |
56,16 → 43,32
|
|
module SOCMaker |
|
|
######### |
# |
# This class represents a core definition. |
# It is one of the central classes and holds data, |
# which is used to describe and instanciate this core. |
# In general, instances of this class desribe a core, |
# it's interface and parameters as well as the files, |
# which are required for synthesis/simulation. |
# |
# In addition to this core, there exist SOCMaker::CoreInst, |
# which represents a concret instanciation of a definition. |
# |
class CoreDef < Component |
include ERR |
include YAML_EXT |
|
attr_accessor :hdlfiles |
def initialize( name, version, hdl_files, toplevel, options = {} ) |
|
|
def initialize( name, version, hdl_files, toplevel, optional = {} ) |
init_with( { 'name' => name, |
'version' => version, |
'hdlfiles' => hdl_files, |
'toplevel' => toplevel }.merge( options ) ) |
'toplevel' => toplevel }.merge( optional ) ) |
end |
def encode_with( coder ) |
super coder |
74,23 → 77,11
def init_with( coder ) |
super( coder ) |
|
# TODO: this was removed because we want to |
# support cores, which have a config-file only |
# (where config and implementation is in one file) |
|
# serr_if( coder[ 'hdlfiles' ] == nil, |
# 'No hdlfiles field found', |
# instance: @name, |
# fiel: 'hdlfiles' ) |
@hdlfiles = coder[ 'hdlfiles' ] || {} |
serr_if( !@hdlfiles.is_a?( Hash ), |
'HDL file def. != Hash', |
instance: @name, |
field: 'hdlfiles' ) |
# serr_if( @hdlfiles.size == 0, |
# 'No HDL files are given', |
# instance: @name, |
# field: 'hdlfiles' ) |
|
@hdlfiles.each do |file_name, defn | |
serr_if( defn == nil, |
115,89 → 106,7
end |
|
|
# |
# TODO this also exists in component.rb |
# might this be removed? |
# If yes, make sure, that the 'default' stuff |
# is also done in component.rb!!! |
# |
# Iterates over interface list. |
# For each interface, all ports are processed. |
# For each port within each interface, we lookup the port defn |
# and yield the call block with |
# - port-name |
# - port-definition |
# - info if last |
# as argument |
# |
# |
# |
#def ports( *args ) |
|
|
#if args.size == 0 |
#@interfaces.values.each_with_index do | ifc, i_ifc; ifc_def| |
|
## get interface definition |
#ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version ) |
|
## loop over ports in this interface |
#ifc.ports.each_with_index do |(port_name, port_def), i_port; port_dir| |
|
## the reference to the port in the definition |
#defn_ref = port_def.defn |
#port_dir = ifc_def.ports[ defn_ref.to_sym ][ :dir ] |
#port_default = ifc_def.ports[ defn_ref.to_sym ][ :default ] |
#perr_if( port_dir == nil, |
#"Can't find #{defn_ref} in interface " + |
#"definition #{ifc_def.name} version " + |
#ifc_def.version + "==>>" + ifc_def.to_yaml ) |
|
## An xor mechanism between port_dir and ifc=>dir is used |
## to determine the direction of a port, for example: |
## If the interface is declared as input (1) and a port is declared as input (1) |
## the resulting direction will be an output 1^1 = 0. |
## But if the overall interface direction is an output (0) and a port is declared |
## as input, the resulting direction will an input 0^1 = 1. |
## This allows to define a port-direction in the interface definition, |
## and toggle the directions on core-definition level. |
|
## (name, direction, length, is_last) |
#yield( port_name.to_s, |
#port_dir ^ ifc.dir, |
#port_def.len, |
#port_default, |
#( (i_port == ifc.ports.size-1 ) and (i_ifc == @interfaces.size-1 ) ) ) |
#end |
#end |
|
## elsif args.size == 1 |
|
## # get interface (input is the name as string ) |
## ifc = @interfaces[ args.first.to_sym ] |
|
## ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version ) |
## ifc.ports.each do |port_name, port_def; port_dir| |
## port_def = port_def.defn |
## port_dir = ifc_def.ports[ port_def.to_sym ] |
## if port_dir == nil |
## perr_if( port_dir==nil, |
## "Can't find #{port_def} in" + |
## "interface definition #{ifc_def.name} " + |
## "version #{ifc_def.version}" ) |
## end |
## yield( port_def.to_s, |
## port_name.to_s, |
## port_dir ^ ifc.dir ) |
## end |
|
#else |
|
#end |
|
#end |
|
|
# this is a core_def and doesn't have |
# sub-cores |
def get_core_def( inst ) |
/hdl_file.rb
62,8 → 62,8
attr_accessor :use_mod_sim |
attr_accessor :type |
|
def initialize( path, options = {} ) |
init_with( { 'path' => path }.merge( options ) ) |
def initialize( path, optional = {} ) |
init_with( { 'path' => path }.merge( optional ) ) |
end |
|
def encode_with( coder ) |
/ifc_spc.rb
47,9 → 47,9
attr_accessor :version |
attr_accessor :ports |
|
def initialize( name, version, options = {} ) |
def initialize( name, version, optional = {} ) |
init_with( { 'name' => name, |
'version' => version }.merge( options ) ) |
'version' => version }.merge( optional ) ) |
end |
def encode_with( coder ) |
%w[ name version ports ]. |