OpenCores
URL https://opencores.org/ocsvn/soc_maker/soc_maker/trunk

Subversion Repositories soc_maker

[/] [soc_maker/] [trunk/] [lib/] [soc_maker/] [soc_def.rb] - Blame information for rev 10

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 feddischso
###############################################################
2
#
3
#  File:      soc_def.rb
4
#
5
#  Author:    Christian Hättich
6
#
7
#  Project:   System-On-Chip Maker
8
#
9
#  Target:    Linux / Windows / Mac
10
#
11
#  Language:  ruby
12
#
13
#
14
###############################################################
15
#
16
#
17
#   Copyright (C) 2014  Christian Hättich  - feddischson [ at ] opencores.org
18
#
19
#   This program is free software: you can redistribute it and/or modify
20
#   it under the terms of the GNU General Public License as published by
21
#   the Free Software Foundation, either version 3 of the License, or
22
#   (at your option) any later version.
23
#
24
#   This program is distributed in the hope that it will be useful,
25
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
#   GNU General Public License for more details.
28
#
29
#   You should have received a copy of the GNU General Public License
30
#   along with this program.  If not, see .
31
#
32
#
33
###############################################################
34
#
35
#   Description:
36
#     This class represents a System-on-chip and derives
37
#     the functionallity from Component.
38
#     The two important fields are
39
#       - @cores: holds all core-instances
40
#       - cons:   holds all connections
41
#     In addition, the field @static is used to store
42
#     static parameters, which are set for cores used in this SOC.
43
#
44
###############################################################
45
 
46
module SOCMaker
47
class SOCDef < Component
48
  include ERR
49
  include YAML_EXT
50
 
51
  attr_accessor :cores
52
  attr_accessor :cons
53
  attr_accessor :static
54 10 feddischso
  def initialize( name, id, toplevel, optional = {} )
55 3 feddischso
 
56
    init_with( { 'name'     => name,
57 10 feddischso
                 'id'       => id,
58 9 feddischso
                 'toplevel' => toplevel }.merge( optional ) )
59 3 feddischso
 
60
  end
61
 
62
  def encode_with( coder )
63
    super coder
64
    %w[ cores cons static ].
65
      each { |v| coder[ v ] = instance_variable_get "@#{v}" }
66
  end
67
 
68
  def init_with( coder )
69
    super coder
70
    @cores  = coder[ 'cores'  ] || {}
71
    @static = coder[ 'static' ] || {}
72
    @cons   = coder[ 'cons'   ] || {}
73
  end
74
 
75
 
76 7 feddischso
  def consistency_check
77
    super
78
    @cores.values.each do |inst|
79
      inst.consistency_check
80 3 feddischso
    end
81
  end
82
 
83
 
84
 
85
 
86
  # SOCMaker::logger.error( "instantiation #{inst_name} is already in use" )
87
  def inst_in_use?( inst_name )
88
       @cores[ inst_name.to_sym ] != nil or
89
       @cons[ inst_name.to_sym ]  != nil
90
  end
91
 
92
  def rm( inst_name )
93
 
94
    if @cores[ inst_name.to_sym ] != nil
95
      # TODO: remove also all related connections
96
      @cores.delete( inst_name.to_sym )
97
    elsif @cons[ inst_name.to_sym ]  != nil
98
      @cons.delete( inst_name.to_sym )
99
    else
100
      return false
101
    end
102
    return true
103
  end
104
 
105
 
106 10 feddischso
  def add_core( id, inst_name )
107 3 feddischso
 
108
    return false if inst_in_use?( inst_name )
109
 
110
    # check, if the core exits in our library
111
    #  if not: an error will be raised
112 10 feddischso
    SOCMaker::lib.get_core( id )
113 3 feddischso
 
114 10 feddischso
    @cores[ inst_name.to_sym ] = SOCMaker::CoreInst.new( id )
115 3 feddischso
  end
116
 
117
 
118
  def ifc_in_use?( inst_name, ifc_name )
119
 
120
    # go through all connections and check,
121
    # that non of the interfaces we want to connect is used
122
    @cons.each do |_con_name, con_def|
123
      return true if con_def[ :mapping ][ 0 ][ inst_name.to_sym] == ifc_name.to_sym
124
      return true if con_def[ :mapping ][ 1 ][ inst_name.to_sym] == ifc_name.to_sym
125
    end
126
    return false
127
 
128
  end
129
 
130
 
131 9 feddischso
  def port_length( ifc_name, port_name, inst )
132 6 feddischso
    if @cores[ inst.to_sym ] != nil
133 9 feddischso
      return @cores[ inst ].port_length( ifc_name, port_name )
134 6 feddischso
    else
135
      return nil
136
    end
137
  end
138 5 feddischso
 
139 9 feddischso
  def core_definition( inst )
140 5 feddischso
      if @cores[ inst.to_sym ] != nil
141
        return @cores[ inst.to_sym ].defn
142 10 feddischso
      elsif inst == @toplevel
143 5 feddischso
        return self
144
      else
145 6 feddischso
        return nil
146 5 feddischso
      end
147
  end
148
 
149 7 feddischso
 
150 5 feddischso
 
151
 
152 10 feddischso
  #def add_to_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )
153
  def add_to_connection( *args )
154
 
155
    if args.size == 4
156
      inst1     = @toplevel
157
      ifc1_name = args[ 0 ]
158
      inst2     = args[ 1 ]
159
      ifc2_name = args[ 2 ]
160
      con_name  = args[ 3 ]
161
    elsif args.size == 5
162
      inst1     = args[ 0 ]
163
      ifc1_name = args[ 1 ]
164
      inst2     = args[ 2 ]
165
      ifc2_name = args[ 3 ]
166
      con_name  = args[ 4 ]
167
    else
168
      perr_if( true, "FATAL: wrong number of arguments (#{args.size}) for add_to_connection (3 or 4)" )
169
    end
170
 
171
 
172 7 feddischso
    perr_if( @cons[ con_name.to_sym ]  == nil, "Connection instance #{con_name} not found" )
173
    @cons[ con_name.to_sym ][:mapping][0][ inst1.to_sym ] = ifc1_name.to_sym
174
    @cons[ con_name.to_sym ][:mapping][1][ inst2.to_sym ] = ifc2_name.to_sym
175
  end
176
 
177
 
178
 
179 10 feddischso
  #def add_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )
180
  def add_connection( *args )
181 3 feddischso
 
182 10 feddischso
    if args.size == 4
183
      inst1     = @toplevel
184
      ifc1_name = args[ 0 ]
185
      inst2     = args[ 1 ]
186
      ifc2_name = args[ 2 ]
187
      con_name  = args[ 3 ]
188
    elsif args.size == 5
189
      inst1     = args[ 0 ]
190
      ifc1_name = args[ 1 ]
191
      inst2     = args[ 2 ]
192
      ifc2_name = args[ 3 ]
193
      con_name  = args[ 4 ]
194
    else
195
      perr_if( true, "FATAL: wrong number of arguments (#{args.size}) for add_connection (3 or 4)" )
196
    end
197
 
198 7 feddischso
    if @cores[ con_name.to_sym ] != nil
199
      return nil
200
    elsif @cons[ con_name.to_sym ]  != nil
201
      return add_to_connection( inst1, ifc1_name, inst2, ifc2_name, con_name )
202
    end
203 3 feddischso
 
204
 
205 7 feddischso
    [ [ inst1, ifc1_name ],
206
      [ inst2, ifc2_name ] ].each do |sub_arr|
207
       perr_if( ifc_in_use?( sub_arr[ 0 ], sub_arr[ 1 ] ),
208
           "Interface #{sub_arr[ 1 ]} of instance '#{sub_arr[ 0 ]}' is already in use " )
209 3 feddischso
    end
210
 
211
 
212 9 feddischso
    core_def_1 = core_definition( inst1 )
213
    core_def_2 = core_definition( inst2 )
214 7 feddischso
 
215
    perr_if( !core_def_1, "Can't find core #{inst1}" )
216
    perr_if( !core_def_2, "Can't find core #{inst2}" )
217 3 feddischso
 
218 5 feddischso
 
219 7 feddischso
    [ [ core_def_1, ifc1_name ],
220
      [ core_def_2, ifc2_name ] ].each do |sub_arr|
221 3 feddischso
        perr_if( sub_arr[ 0 ].interfaces[ sub_arr[ 1 ].to_sym ] == nil,
222 7 feddischso
          "Interface '#{sub_arr[ 1 ]}' dosn't exist in core '#{sub_arr[0].name}' \n" +
223
          "The following interfaces do exist:  '#{sub_arr[0].interfaces.keys}'"  )
224 3 feddischso
    end
225
 
226 10 feddischso
    # check id of the ifcs which will be connected
227
    perr_if( core_def_1.interfaces[ ifc1_name.to_sym ].id !=
228
             core_def_2.interfaces[ ifc2_name.to_sym ].id,
229 3 feddischso
          "Can't connect #{
230 10 feddischso
             core_def_1.interfaces[ ifc1_name.to_sym ].id} with #{
231
             core_def_2.interfaces[ ifc2_name.to_sym ].id} " )
232 3 feddischso
 
233
    @cons[ con_name.to_sym ] = {
234
          :rule    => "or",
235
          :mapping => [ { inst1.to_sym => ifc1_name.to_sym },
236
                        { inst2.to_sym => ifc2_name.to_sym } ] }
237 5 feddischso
    return false
238 3 feddischso
  end
239
 
240
  def set_param( instance, param, value )
241
 
242
    # get instance
243
    core_inst = @cores[ instance.to_sym ]
244
    perr_if( core_inst == nil,
245
      "Can't find '#{instance}' in SOC" )
246
 
247
    # get the core-definition
248
    core_def = SOCMaker::lib.get_core( core_inst.type  )
249
 
250
    # check if parameter exist
251
    if core_def.inst_parameters[ param.to_sym ] != nil
252
      core_inst.params[ param.to_sym ] = value
253
    else
254
      perr_if( true,
255
        "Parameter '#{param}' not found in '#{core_def.name}'" )
256
    end
257
 
258
  end
259
 
260
  def get_param( instance, param )
261
 
262
    # get instance
263
    core_inst = @cores[ instance.to_sym ]
264
    perr_if( core_inst == nil,
265
      "Can't find '#{instance}' in SOC" )
266
    param_val = core_inst.params[ param.to_sym ]
267
    perr_if( param_val == nil,
268
      "Can't find parameter '#{param}' in '#{instance}'" )
269
    return param_val
270
  end
271
 
272
 
273
  def set_sparam( core, param, value )
274
 
275
    #get instance
276
 
277
    # check, if we are instantiating this core
278
    perr_if( @cores.select{ |name,inst| inst.type == core }.size == 0,
279
      "Core '#{core}' is not instantiated in this SOC" )
280
 
281
    # get the core-definition
282
    core_def = SOCMaker::lib.get_core( core )
283
 
284
    # check if parameter exist
285
    perr_if( core_def.static_parameters.select{ |f,p| p.parameters[ param.to_sym ] != nil }.size == 0,
286
        "Parameter '#{param}' not found in '#{core_def.name}'" )
287
 
288
    @static[ core.to_sym ] ||= {}
289
    @static[ core.to_sym ][ param.to_sym ] = value
290
  end
291
 
292
  def get_sparam( core, param )
293
    perr_if( @static[ core.to_sym ] == nil,
294
      "Core '#{core}' does not exist in this SOC" )
295
 
296
    perr_if( @static[ core.to_sym ][ param.to_sym ] == nil,
297
      "Parameter '#{param}' does not exist for core '#{core}'" )
298
 
299
    return @static[ core.to_sym ][ param.to_sym ]
300
  end
301
 
302
 
303
  def copy_files
304
 
305
    SOCMaker::logger.proc( "START of copying all HDL files" )
306
 
307 8 feddischso
 
308 3 feddischso
    #
309
    # Create a unique list of cores and
310
    # for every core, create a directory and copy files
311
    #
312
    @cores.values.uniq{|x| x.type }.each do |core_inst; core_def, dst_dir|
313
 
314
      core_def = SOCMaker::lib.get_core( core_inst.type )
315
 
316
      # create destination directory name and ensure, that it is exist
317 10 feddischso
      dst_dir  = Component.get_and_ensure_dst_dir!( core_def.dir_name )
318 3 feddischso
 
319
      # copy each file into destination dir
320
      core_def.hdlfiles.each do |file, val|
321
        file_path = File.join( core_def.dir, val.path )
322 5 feddischso
        dst_path = File.join( dst_dir, val.path )
323 3 feddischso
        SOCMaker::logger.proc( "copy #{file_path} to #{ dst_path} " )
324 5 feddischso
        FileUtils.mkdir_p(File.dirname(dst_path))
325 3 feddischso
        FileUtils.cp( file_path, dst_path )
326
      end
327
 
328
 
329
      #
330
      # handle the static parameters
331
      #   (search and replace in pakckage/include files)
332 8 feddischso
      core_def.static_parameters.each do |file, sparam|
333 3 feddischso
 
334
        token_val_map = {}
335 8 feddischso
        sparam.parameters.each do |n,sparam_entry|
336 3 feddischso
 
337
          if  @static[ core_inst.type.to_sym ]      != nil and
338
              @static[ core_inst.type.to_sym ][ n ] != nil
339
            # use value defined in soc-spec
340 8 feddischso
            tmp = @static[ core_inst.type.to_sym ][ n ]
341 3 feddischso
          else
342
            # use default value from core-spec
343 8 feddischso
            tmp =  sparam_entry.default
344 3 feddischso
          end
345
 
346 8 feddischso
          if sparam_entry.type == "enum"
347
            token_val_map[ sparam_entry.token ] = sparam_entry.choice[ tmp ]
348
          elsif sparam_entry.type == "bool"
349
            if tmp == true
350
              token_val_map[ sparam_entry.token ] = sparam_entry.choice
351
            else
352
              token_val_map[ sparam_entry.token ] = ""
353
            end
354
          else
355
            token_val_map[ sparam_entry.token ] = tmp
356
          end
357
 
358
 
359 3 feddischso
        end
360 8 feddischso
 
361 3 feddischso
        # create file paths
362 8 feddischso
        src_path = File.join( core_def.dir, sparam.path )
363 10 feddischso
        dst_dir  = Component::get_and_ensure_dst_dir!( core_def.dir_name )
364 8 feddischso
        dst_path = File.join( dst_dir, sparam.file_dst )
365 3 feddischso
 
366
 
367
        # process each line of input file
368
        # and replace tokens by value via
369
        # regular expression
370
        File.open( dst_path, 'w' ) do |dst_f|
371
          File.open( src_path ) do |src_f|
372
            SOCMaker::logger.proc( "create #{dst_path} from #{ src_path} " )
373
            while line = src_f.gets
374 8 feddischso
              token_val_map.each { |token, val| line = line.sub( Regexp.new( '\b' + token.to_s + '\b' ), val.to_s ) }
375 3 feddischso
              dst_f.puts line
376
            end
377
          end
378
        end
379
 
380
 
381
 
382
      end
383
 
384
    end
385
 
386
 
387
    SOCMaker::logger.proc( "END of copying all HDL files" )
388
  end
389
 
390
 
391 6 feddischso
 
392 3 feddischso
  def ==(o)
393
    o.class   == self.class   &&
394
    o.cores   == self.cores   &&
395
    o.cons    == self.cons    &&
396
    o.static  == self.static  &&
397
    super( o )
398
  end
399
 
400
 
401 5 feddischso
  def to_s
402
 
403
    tmp = "_________ SOC #{@name}: _______\n"     +
404
          super                                   +
405
          "\n__connections__\n"
406
 
407
    @cons.each do |_con_name, con_def|
408
      tmp += "#{_con_name}: #{con_def}\n"
409
    end
410
 
411
    tmp += "\n__cores__\n"
412
    @cores.each do |inst_name, inst|
413
      tmp += "#{inst_name}:\n#{inst}\n"
414
    end
415
    tmp += "'''''''''''''''''''''''''''''''''''\n"
416
    return tmp
417
  end
418
 
419
 
420 3 feddischso
end # class SOCSpec
421
end # module SOCMaker
422
 
423
 
424
# vim: noai:ts=2:sw=2

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.