soc_maker 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/History.txt +4 -0
  4. data/LICENSE +678 -0
  5. data/README.rdoc +228 -0
  6. data/Rakefile +46 -0
  7. data/bin/soc_maker_cli +80 -0
  8. data/bin/soc_maker_parser +85 -0
  9. data/core_lib/cores/adv_debug_sys/01_adv_debug_sys.yaml +245 -0
  10. data/core_lib/cores/or1200_rel2/01_or1200.yaml +208 -0
  11. data/core_lib/cores/or1200_rel2/02_or1200_files.yaml +421 -0
  12. data/core_lib/cores/or1200_rel2/03_or1200_sparam.yaml +188 -0
  13. data/core_lib/cores/or1200_rel2/or1200_defines.v.in +1799 -0
  14. data/core_lib/cores/ram_wb/ram_wb.yaml +102 -0
  15. data/core_lib/cores/ram_wb/ram_wb_b3.v.in +259 -0
  16. data/core_lib/cores/uart16550/01_uart16550.yaml +99 -0
  17. data/core_lib/cores/uart16550/02_uart16550_files.yaml +70 -0
  18. data/core_lib/cores/wb_connect/minsoc_tc_top.v +1802 -0
  19. data/core_lib/cores/wb_connect/wb_connect.yaml +733 -0
  20. data/core_lib/inc.yaml +13 -0
  21. data/core_lib/interfaces/clk_rst/clk.yaml +9 -0
  22. data/core_lib/interfaces/clk_rst/rst.yaml +9 -0
  23. data/core_lib/interfaces/clk_rst/single.yaml +7 -0
  24. data/core_lib/interfaces/debug/debug.yaml +32 -0
  25. data/core_lib/interfaces/jtag/jtag.yaml +13 -0
  26. data/core_lib/interfaces/jtag/jtag_tap.yaml +22 -0
  27. data/core_lib/interfaces/power/or_power.yaml +25 -0
  28. data/core_lib/interfaces/uart/uart.yaml +21 -0
  29. data/core_lib/interfaces/wishbone/wishbone_ma_b3.yaml +54 -0
  30. data/core_lib/interfaces/wishbone/wishbone_sl_b3.yaml +51 -0
  31. data/doc/class_arch.uml +5113 -0
  32. data/doc/fig/hierarchical.svg +273 -0
  33. data/examples/or1200_test/or1200_test.cmd +78 -0
  34. data/examples/or1200_test/or1200_test.rb +136 -0
  35. data/examples/or1200_test/rtl/or1200_test_top.vhd +274 -0
  36. data/examples/or1200_test/rtl/s3astarter.ucf +10 -0
  37. data/examples/or1200_test/rtl/xilinx_internal_jtag.v +438 -0
  38. data/examples/or1200_test/rtl/xilinx_internal_jtag_options.v +12 -0
  39. data/examples/or1200_test/sw/README.txt +35 -0
  40. data/examples/or1200_test/sw/bin2vmem.c +159 -0
  41. data/examples/or1200_test/sw/board.h +24 -0
  42. data/examples/or1200_test/sw/compile.sh +18 -0
  43. data/examples/or1200_test/sw/except.S +152 -0
  44. data/examples/or1200_test/sw/int.c +79 -0
  45. data/examples/or1200_test/sw/int.h +14 -0
  46. data/examples/or1200_test/sw/interconnect.h +17 -0
  47. data/examples/or1200_test/sw/interrupts.c +14 -0
  48. data/examples/or1200_test/sw/main.c +16 -0
  49. data/examples/or1200_test/sw/or1200.h +454 -0
  50. data/examples/or1200_test/sw/orp.ld +60 -0
  51. data/examples/or1200_test/sw/reset.S +112 -0
  52. data/examples/or1200_test/sw/support.c +123 -0
  53. data/examples/or1200_test/sw/support.h +33 -0
  54. data/examples/or1200_test/sw/tick.c +30 -0
  55. data/examples/or1200_test/sw/tick.h +2 -0
  56. data/examples/or1200_test/sw/uart.c +136 -0
  57. data/examples/or1200_test/sw/uart.h +126 -0
  58. data/lib/soc_maker.rb +324 -0
  59. data/lib/soc_maker/cli.rb +544 -0
  60. data/lib/soc_maker/conf.rb +310 -0
  61. data/lib/soc_maker/core_def.rb +579 -0
  62. data/lib/soc_maker/core_inst.rb +305 -0
  63. data/lib/soc_maker/err.rb +211 -0
  64. data/lib/soc_maker/hdl_coder.rb +500 -0
  65. data/lib/soc_maker/hdl_file.rb +166 -0
  66. data/lib/soc_maker/hdl_parser.rb +431 -0
  67. data/lib/soc_maker/ifc_def.rb +193 -0
  68. data/lib/soc_maker/ifc_port.rb +133 -0
  69. data/lib/soc_maker/ifc_spc.rb +180 -0
  70. data/lib/soc_maker/lib.rb +289 -0
  71. data/lib/soc_maker/lib_inc.rb +109 -0
  72. data/lib/soc_maker/parameter.rb +149 -0
  73. data/lib/soc_maker/soc_def.rb +847 -0
  74. data/lib/soc_maker/sparameter.rb +289 -0
  75. data/lib/soc_maker/version.rb +8 -0
  76. data/lib/soc_maker/ypp.rb +130 -0
  77. data/soc_maker.gemspec +28 -0
  78. data/spec/cli_cmds1.txt +39 -0
  79. data/spec/cli_spec.rb +49 -0
  80. data/spec/conf_spec.rb +44 -0
  81. data/spec/core_def_spec.rb +503 -0
  82. data/spec/core_inst_spec.rb +169 -0
  83. data/spec/hdl_file_spec.rb +154 -0
  84. data/spec/hdl_parser_spec.rb +201 -0
  85. data/spec/ifc_def_spec.rb +121 -0
  86. data/spec/ifc_port_spec.rb +92 -0
  87. data/spec/ifc_spc_spec.rb +196 -0
  88. data/spec/lib_inc_spec.rb +99 -0
  89. data/spec/lib_spec.rb +209 -0
  90. data/spec/parameter_spec.rb +86 -0
  91. data/spec/soc_def_spec.rb +611 -0
  92. data/spec/soc_maker_spec.rb +7 -0
  93. data/spec/sparameter_spec.rb +182 -0
  94. data/spec/spec_helper.rb +78 -0
  95. data/spec/test_soc.yaml +105 -0
  96. data/spec/test_soc2.yaml +60 -0
  97. data/spec/test_soc_lib/cores/core_A_rel1/00_core_a.yaml +75 -0
  98. data/spec/test_soc_lib/cores/core_A_rel1/01_core_a.yaml +57 -0
  99. data/spec/test_soc_lib/cores/core_A_rel1/core_a.vhd +29 -0
  100. data/spec/test_soc_lib/cores/core_A_rel1/core_a_pkg.vhd.src +3 -0
  101. data/spec/test_soc_lib/cores/core_A_rel1/core_a_pkg2.vhd.src +4 -0
  102. data/spec/test_soc_lib/cores/core_A_rel1/core_a_pkg3.v.src +6 -0
  103. data/spec/test_soc_lib/cores/core_B_rel1/core_b.vhd +25 -0
  104. data/spec/test_soc_lib/cores/core_B_rel1/core_b.yaml +36 -0
  105. data/spec/test_soc_lib/cores/core_C_v1/core_C.vhd +57 -0
  106. data/spec/test_soc_lib/cores/core_C_v1/core_c.yaml +42 -0
  107. data/spec/test_soc_lib/cores/soc_A/soc_A.yaml +12 -0
  108. data/spec/test_soc_lib/cores/soc_maker_include.yaml +6 -0
  109. data/spec/test_soc_lib/ifcs/core_AB_ifc/bidir_ifc.yaml +19 -0
  110. data/spec/test_soc_lib/ifcs/core_AB_ifc/core_AB_ifc.yaml +15 -0
  111. data/spec/test_soc_lib/ifcs/core_AB_ifc/top_ifc.yaml +9 -0
  112. data/spec/test_soc_lib/soc_maker_include.yaml +4 -0
  113. data/spec/yaml_examples.rb +367 -0
  114. data/spec/ypp_spec.rb +156 -0
  115. data/test/test_soc_maker.rb +0 -0
  116. metadata +255 -0
@@ -0,0 +1,847 @@
1
+ ###############################################################
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 <http://www.gnu.org/licenses/>.
31
+ #
32
+ #
33
+ ###############################################################
34
+ module SOCMaker
35
+
36
+
37
+
38
+ #
39
+ # This class represents a System-on-chip and derives
40
+ # the functionallity from SOCMaker::CoreDef.
41
+ # The two important fields are
42
+ # - #cores: holds all core-instances
43
+ # - #cons: holds all connections
44
+ # In addition, the field @static is used to store
45
+ # static parameters, which are set for cores used in this SOC.
46
+ class SOCDef < CoreDef
47
+ include ERR
48
+ include YAML_EXT
49
+
50
+ #
51
+ # Hash of cores (core instances: SOCMaker::CoreInst)
52
+ #
53
+ attr_accessor :cores
54
+
55
+ #
56
+ # Hash of all connections.
57
+ # The structure is the following
58
+ #
59
+ # @cons = { :connection_name_1 => {
60
+ # :mapping => [
61
+ # { :instance_1 => :interface_of_instance_1, #\ dir=0
62
+ # :instance_2 => :interface_of_instance_2, #/
63
+ # ...},
64
+ # { :instance_3 => :interface_of_instance_3, #\ dir=1
65
+ # :instance_4 => :interface_of_instance_4, #/
66
+ # ...}
67
+ # ] },
68
+ #
69
+ # :connection_name_2 => {
70
+ # :mapping => [
71
+ # { :instance_a => :interface_of_instance_a, #\ dir=0
72
+ # :instance_b => :interface_of_instance_b, #/
73
+ # ...},
74
+ # { :instance_c => :interface_of_instance_c, #\ dir=1
75
+ # :instance_d => :interface_of_instance_d, #/
76
+ # ...}
77
+ # ] },
78
+ # ....
79
+ #
80
+ # }
81
+ # The important part is the mapping: it is a list with two entries. Ech
82
+ # entry is a Hash containing instance-interface assignments.
83
+ #
84
+ # <tt>TODO: this needs to be re-designed, because it allowes only
85
+ # one core to be used in one connection-direction.</tt>
86
+ #
87
+ #
88
+ #
89
+ #
90
+ attr_accessor :cons
91
+
92
+ #
93
+ # Hash of all static parameters defined within this SOC
94
+ #
95
+ attr_accessor :static
96
+
97
+ # This constructor expects the name, an id, the toplevel-name
98
+ # as mandatory arguments. All other attributes can be privided
99
+ # as optional argument
100
+ def initialize( name, id, toplevel, optional = {} )
101
+
102
+ init_with( { 'name' => name,
103
+ 'id' => id,
104
+ 'toplevel' => toplevel }.merge( optional ) )
105
+
106
+ end
107
+
108
+ #
109
+ # Encoder method (to yaml)
110
+ #
111
+ # +coder+:: An instance of the Psych::Coder to encode this class to a YAML file
112
+ #
113
+ def encode_with( coder )
114
+ init_error_if !coder.is_a?( Psych::Coder ),
115
+ 'coder is not given as Psych::Coder'
116
+ super coder
117
+ %w[ cores cons static ].
118
+ each { |v| coder[ v ] = instance_variable_get "@#{v}" }
119
+ end
120
+
121
+ #
122
+ # Initialization method (from yaml)
123
+ #
124
+ # +coder+:: An instance of the Psych::Coder to init this class from a YAML file
125
+ #
126
+ #
127
+ def init_with( coder )
128
+ init_error_if !( coder.is_a?( Hash ) || coder.is_a?( Psych::Coder ) ),
129
+ 'coder is not given as Hash neither as Psych::Coder'
130
+ super coder
131
+ @cores = coder[ 'cores' ] || {}
132
+ @static = coder[ 'static' ] || {}
133
+ @cons = coder[ 'cons' ] || {}
134
+ end
135
+
136
+
137
+ #
138
+ # Consistence check method:
139
+ # - ensures, that all cores are available and consistent
140
+ # - ensures, that all connections are possible
141
+ #
142
+ #
143
+ def consistence_check
144
+ super
145
+
146
+ @cores.values.each do |inst|
147
+ inst.consistence_check
148
+ end
149
+
150
+
151
+ @cons.each do |con_name, con_def|
152
+ con_def[ :mapping ].each_with_index do |mapping,dir|
153
+ mapping.each do |inst_name, ifc_name|
154
+ if !is_it_me?( inst_name )
155
+ consistence_error "#{inst_name} not does not exist in SOCDef #{@name}" if @cores[ inst_name ] == nil
156
+ end
157
+
158
+ core_def = core_definition( inst_name ) or
159
+ consistence_error "Can't find definition of core #{inst_name}"
160
+
161
+ consistence_error "Interface #{ifc_name} doesn exist in #{core_def.name}" if core_def.interfaces[ ifc_name ] == nil
162
+
163
+ consistence_error "Wrong connection definition of #{inst_name}:#{ifc_name}",
164
+ direction: core_def.interfaces[ ifc_name ].dir,
165
+ localtion: dir,
166
+ internal: is_it_me?( inst_name ) if !(
167
+ ( (core_def.interfaces[ ifc_name ].dir != dir) && is_it_me?( inst_name ) ) ||
168
+ ( (core_def.interfaces[ ifc_name ].dir == dir) && !is_it_me?( inst_name ) ) )
169
+
170
+ end
171
+ end
172
+ end
173
+
174
+
175
+
176
+ end
177
+
178
+
179
+ #
180
+ # Method to check, if inst_name means this SOC.
181
+ # For connecting cores, the instance name is used. But
182
+ # If a toplevel connection to a core needs to be done, the SOC
183
+ # is identified by @toplevel (even if this is not an instance)
184
+ #
185
+ # +inst_name+:: name of instance
186
+ # +return+:: true if inst_name == @toplevel.to_sym, otherwise false
187
+ #
188
+ def is_it_me?( inst_name )
189
+ # TODO: is there a better way to identify self via @toplevel?
190
+ inst_name == @toplevel.to_sym
191
+ end
192
+
193
+
194
+
195
+ #
196
+ # Check, if the instance name is already used within this SOC
197
+ #
198
+ def inst_in_use?( inst_name )
199
+ return ( @cores[ inst_name ] != nil or @cons[ inst_name ] != nil )
200
+ end
201
+
202
+ #
203
+ # Method to remove a instance
204
+ #
205
+ def rm( inst_name )
206
+
207
+ if @cores[ inst_name ] != nil
208
+ @cores.delete( inst_name )
209
+
210
+ # remove all connection entries of this core
211
+ @cons.each do |_con_name, con_def|
212
+ con_def[ :mapping ][ 0 ].delete( inst_name ) if con_def[ :mapping ][ 0 ].has_key?( inst_name )
213
+ con_def[ :mapping ][ 1 ].delete( inst_name ) if con_def[ :mapping ][ 1 ].has_key?( inst_name )
214
+ end
215
+
216
+ elsif @cons[ inst_name ] != nil
217
+ @cons.delete( inst_name )
218
+ else
219
+ consistence_error( "Can't remove instance #{inst_name}" )
220
+ end
221
+ end
222
+
223
+
224
+ #
225
+ # Add an instance to the SoC
226
+ #
227
+ # +id+:: the core ID, used to get the desired core from SOCMaker::Lib
228
+ # +inst_name+:: name of the instance
229
+ #
230
+ def add_core( id, inst_name )
231
+
232
+ consistence_error_if(
233
+ inst_in_use?( inst_name ),
234
+ "Instance name #{inst_name} is already in use" )
235
+
236
+ # check, if the core exits in our library
237
+ # if not: an error will be raised
238
+ SOCMaker::lib.get_core( id )
239
+
240
+ @cores[ inst_name ] = SOCMaker::CoreInst.new( id )
241
+ end
242
+
243
+
244
+ #
245
+ # Method to check, if the interface of an instance is already
246
+ # connected
247
+ #
248
+ # +inst_name+:: name of the instance
249
+ # +ifc_name+:: name of the interface
250
+ #
251
+ def ifc_in_use?( inst_name, ifc_name )
252
+
253
+ # go through all connections and check,
254
+ # that non of the interfaces we want to connect is used
255
+ @cons.each do |_con_name, con_def|
256
+ return true if con_def[ :mapping ][ 0 ][ inst_name] == ifc_name
257
+ return true if con_def[ :mapping ][ 1 ][ inst_name] == ifc_name
258
+ end
259
+ return false
260
+
261
+ end
262
+
263
+
264
+ #
265
+ # Method to get the port length. All arguments as symbol.
266
+ #
267
+ # +ifc_name+:: name of the interface
268
+ # +port_name+:: name of the port
269
+ # +inst+:: name of the instance
270
+ #
271
+ def port_length( ifc_name, port_name, inst )
272
+ if @cores[ inst ] != nil
273
+ return @cores[ inst ].port_length( ifc_name, port_name )
274
+ elsif is_it_me?( inst )
275
+ tmp = @interfaces[ ifc_name ].ports.select{ |k,v| v.spc_ref == port_name.to_s }
276
+ return tmp.values.first.len
277
+ else
278
+ return nil
279
+ end
280
+ end
281
+
282
+
283
+ #
284
+ # Method to get the core definition.
285
+ #
286
+ #
287
+ # +inst+:: instance name (as symbol)
288
+ # +return+:: nil, if there is no core with the
289
+ # name and if it is not this SOC
290
+ #
291
+ def core_definition( inst )
292
+ if @cores[ inst ] != nil
293
+ return @cores[ inst ].defn
294
+
295
+ elsif is_it_me?( inst )
296
+ return self
297
+ else
298
+ return nil
299
+ end
300
+ end
301
+
302
+
303
+
304
+
305
+
306
+ #
307
+ # Method add/modify a connection.
308
+ # The number of arguments are variable and multiple entries can be provided as once.
309
+ #
310
+ # +args+:: number of arguments must be >3 and odd. The first argument defines
311
+ # the connection name. The following arguments are treaded as pairs. Each
312
+ # pair consists of the instance name and the interface name.
313
+ #
314
+ #
315
+ #
316
+ def add_connection( *args )
317
+
318
+ if args.size < 3 || args.size % 2 != 1
319
+ processing_error "FATAL: wrong number of arguments: " +
320
+ "(#{args.size}) must be > = 3 and odd"
321
+ end
322
+
323
+ consistence_check
324
+
325
+
326
+ con_name = args[0]
327
+ args[ 1..-1].each_slice(2).to_a.each do |entry|
328
+ inst_name = entry[0]
329
+ ifc_name = entry[1]
330
+
331
+ # get the core definition
332
+ core_def = core_definition( inst_name ) or
333
+ consistence_error "Can't find definition of core #{inst_name}"
334
+
335
+
336
+ consistence_error_if ifc_in_use?( inst_name, ifc_name ),
337
+ "Interface #{ifc_name} of instance '#{inst_name}' is already in use "
338
+
339
+
340
+ consistence_error_if core_def.interfaces[ ifc_name ] == nil,
341
+ "Interface '#{ifc_name}' dosn't exist in core '#{inst_name}' \n" +
342
+ "The following interfaces do exist: '#{core_def.interfaces.keys}'"
343
+
344
+ # get the interface specification
345
+ ifc_spc = core_def.ifc_specification( ifc_name )
346
+
347
+ # get the directions
348
+ ifc_dir = core_def.interfaces[ ifc_name ].dir
349
+
350
+ ifc_dir = ( ifc_dir + 1 ) % 2 if is_it_me?( inst_name )
351
+
352
+
353
+ # create a new connection, if there is no one
354
+ if @cons[ con_name ] == nil
355
+ @cons[ con_name ] = { mapping: [ {},{} ] }
356
+ end
357
+
358
+ if ifc_spc.n_connections_ok?( ifc_dir, @cons[ con_name ][ :mapping ][ ifc_dir ].size+1 )
359
+ @cons[ con_name ][ :mapping ][ ifc_dir ][ inst_name ] = ifc_name
360
+ else
361
+ consistence_error "Only #{ ifc_spc.multiplicity[ ifc_dir ] } " +
362
+ "connections are allowed for direction #{ifc_dir}",
363
+ connection: con_name,
364
+ instance: inst_name,
365
+ interface: ifc_name
366
+
367
+ end
368
+
369
+ end
370
+
371
+
372
+ end
373
+
374
+
375
+ #
376
+ # Method to set an instance parameter
377
+ #
378
+ # +instance+:: name of the instance
379
+ # +param+:: name of the parameter
380
+ # +vlue+:: value, which is set
381
+ #
382
+ def set_param( instance, param, value )
383
+
384
+ # get instance
385
+ core_inst = @cores[ instance ]
386
+ consistence_error "Can't find '#{instance}' in SOC" if core_inst == nil
387
+
388
+ # get the core-definition
389
+ core_def = SOCMaker::lib.get_core( core_inst.type )
390
+
391
+ # check if parameter exist
392
+ if core_def.inst_parameters[ param ] != nil
393
+ core_inst.params[ param ] = value
394
+ else
395
+ consistence_error "Parameter '#{param}' not found in '#{core_def.name}'"
396
+ end
397
+
398
+ end
399
+
400
+ #
401
+ # Method to get an instance parameter
402
+ #
403
+ # +instance+:: name of the instance
404
+ # +param+:: name of the parameter
405
+ #
406
+ def get_param( instance, param )
407
+
408
+ # get instance
409
+ core_inst = @cores[ instance ]
410
+ consistence_error "Can't find '#{instance}' in SOC" if core_inst == nil
411
+ param_val = core_inst.params[ param ]
412
+ consistence_error "Can't find parameter '#{param}' in '#{instance}'" if param_val == nil
413
+ return param_val
414
+ end
415
+
416
+
417
+ #
418
+ # Method to set a static parameter
419
+ #
420
+ # +instance+:: name of the instance
421
+ # +param+:: name of the parameter
422
+ # +vlue+:: value, which is set
423
+ #
424
+ def set_sparam( core, param, value )
425
+
426
+ #get instance
427
+
428
+ # check, if we are instantiating this core
429
+ processing_error_if( @cores.select{ |name,inst| inst.type == core }.size == 0,
430
+ "Core '#{core}' is not instantiated in this SOC" )
431
+
432
+ # get the core-definition
433
+ core_def = SOCMaker::lib.get_core( core )
434
+
435
+ # check if parameter exist
436
+ processing_error_if( core_def.static_parameters.select{ |f,p| p.parameters[ param ] != nil }.size == 0,
437
+ "Parameter '#{param}' not found in '#{core_def.name}'" )
438
+
439
+ @static[ core ] ||= {}
440
+ @static[ core ][ param ] = value
441
+ end
442
+
443
+ #
444
+ # Method to get a static parameter
445
+ #
446
+ # +instance+:: name of the instance
447
+ # +param+:: name of the parameter
448
+ #
449
+ def get_sparam( core, param )
450
+ consistence_error "Core '#{core}' does not exist in this SOC" if @static[ core ] == nil
451
+
452
+ consistence_error "Parameter '#{param}' does not exist for core '#{core}'" if @static[ core ][ param ] == nil
453
+
454
+ return @static[ core ][ param ]
455
+ end
456
+
457
+
458
+
459
+ #
460
+ # Method, to deploy this SOC:
461
+ # It runs gen_toplevel and calls also super to
462
+ # copy files, which are added in addition to this SOC.
463
+ #
464
+ # +options+:: Common entries are coder and static:
465
+ # coder must be a SOCMaker::Coder and static must be a hash
466
+ # of static parameters.
467
+ #
468
+ def deploy( options = {} )
469
+ options = { coder: VHDLCoder.new }.merge( options )
470
+ gen_toplevel( options[ :coder ] )
471
+ super( options )
472
+ end
473
+
474
+
475
+ #
476
+ # Method to get all connections of an instance
477
+ # +inst_name+:: Instance name (as symbol)
478
+ # +return+:: A connection hash
479
+ #
480
+ #
481
+ def inst_connections( inst_name )
482
+ connections = {};
483
+ @cons.each do |con_name, con|
484
+ if con[ :mapping ][ 0 ].select{ |k,v| k == inst_name }.size > 0 ||
485
+ con[ :mapping ][ 1 ].select{ |k,v| k == inst_name }.size > 0
486
+ connections[ con_name ] = con
487
+ end
488
+ end
489
+ return connections
490
+ end
491
+
492
+
493
+ #
494
+ # Method to get all connections which connected to
495
+ # the top
496
+ # +inst_name+:: Instance name (as symbol)
497
+ # +return+:: A connection hash
498
+ #
499
+ def top_connections( inst_name )
500
+ inst = inst_connections( inst_name )
501
+ top = inst_connections( toplevel.to_sym )
502
+
503
+ tmp = inst.keys & top.keys
504
+ return inst.select{ |k,v| tmp.include?( k ) }
505
+ end
506
+
507
+
508
+
509
+
510
+ #
511
+ # Generate toplevel hdl file for this instance.
512
+ # This assumes, that this instance represents a SOC with
513
+ # further instances.
514
+ #
515
+ #
516
+ # +coder+:: An instance of the SOCMaker::HDLCoder, which is used to
517
+ # create the auto-generated HDL (optional).
518
+ # If no coder is given, a SOCMaker::VHDLCoder is used.
519
+ #
520
+ #
521
+ def gen_toplevel( coder = VHDLCoder.new )
522
+
523
+
524
+ #
525
+ # Get filename
526
+ #
527
+ file_name = coder.filename( dir_name )
528
+ dst_dir = CoreDef::get_and_ensure_dst_dir!( dir_name )
529
+
530
+ SOCMaker::logger.proc( "START of creating top-level '" + file_name + "'" )
531
+
532
+
533
+ #
534
+ # Create a unique list of cores and
535
+ # add for each core a component statement (vhdl only).
536
+ # Even if there are multiple instances of a core,
537
+ # we need to decalre it only once
538
+ #
539
+ @cores.values.uniq{|x| x.type }.each do |inst; spec|
540
+
541
+ spec = SOCMaker::lib.get_core( inst.type )
542
+ processing_error "Can't find #{ inst.type } in SOC library" if !spec
543
+
544
+ coder.add_core_component( inst.type, spec )
545
+ end
546
+
547
+
548
+ top_connections = {}
549
+
550
+ #
551
+ # Instanciate each core
552
+ #
553
+ @cores.each do |inst_name, inst|
554
+
555
+ # get all connections of this instance, which are connected
556
+ # to top and are single-entry connections
557
+ top_cons_tmp = top_connections( inst_name )
558
+ top_cons_tmp = top_cons_tmp.select{ |k,v| v[:mapping][0].size == 1 && v[:mapping][1].size == 1 }
559
+ top_cons_tmp.keys.each do |con_name|
560
+ @cons[ con_name ][ :top_assigned ] = true
561
+ end
562
+ coder.add_core_instance( inst_name.to_s, inst, top_cons_tmp, @interfaces, self )
563
+ top_connections.merge!( top_cons_tmp )
564
+ end
565
+
566
+
567
+ # create a list of all top-interfaces, which are directly connected
568
+ # to cores
569
+ top_connected_ifcs = []
570
+ top_connections.values.each do |con|
571
+ if con[ :mapping ][0].has_key?( @toplevel.to_sym )
572
+ top_connected_ifcs << con[ :mapping ][0][ @toplevel.to_sym ]
573
+ else
574
+ top_connected_ifcs << con[ :mapping ][1][ @toplevel.to_sym ]
575
+ end
576
+ end
577
+
578
+
579
+ # Iterate over all connections:
580
+ # - create signal instances
581
+ # - add assignments
582
+ #
583
+ @cons.each do |con_name, con_def|
584
+ if not con_def[ :top_assigned]
585
+ gen_toplevel_con( con_name.to_s,
586
+ con_def[ :mapping ][0],
587
+ con_def[ :mapping ][1],
588
+ coder )
589
+ end
590
+ end
591
+
592
+ assign_unused_to_default( coder )
593
+
594
+ coder.add_toplevel_sig( self, @toplevel, top_connected_ifcs )
595
+
596
+ #
597
+ # Write content to the file
598
+ #
599
+ SOCMaker::logger.proc( "writing top-level" )
600
+ File.open( File.join( dst_dir, file_name ), 'w' ) do |f|
601
+ f.write( coder.get_hdl_code( self, @toplevel ) )
602
+ end
603
+ SOCMaker::logger.proc( "END of creating top-level hdl code for #{@name}" )
604
+
605
+ @cons.values.each{ |v| v[ :top_assigned ] = false }
606
+
607
+
608
+ end
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+ #
617
+ # Assign default values for unused interfaces.
618
+ # This is just a helper function and is used by gen_toplevel
619
+ #
620
+ # +coder+:: A HDL coder, which is used to create the auto-generated HDL.
621
+ #
622
+ def assign_unused_to_default( coder )
623
+
624
+
625
+
626
+ # iterate over all instances
627
+ # and check all interfaces
628
+ @cores.each do |inst_name, inst|
629
+
630
+ inst.defn.interfaces.each do |ifc_name, ifc|
631
+
632
+ #
633
+ # Get the interface specification by using the 1st source entry
634
+ # and searching for the core-definition.
635
+ #
636
+ if !ifc_in_use?( inst_name, ifc_name )
637
+ coder.add_ifc_default_assignment( inst, inst_name, ifc_name )
638
+ end
639
+ end
640
+ end
641
+ end
642
+
643
+ #
644
+ # This function is called during the toplevel generation
645
+ # for each connection.
646
+ #
647
+ # +name+:: The name of the connection
648
+ # +src+:: Source hash with instance name as key and interface name as value
649
+ # +dst+:: Destination hash with instance name as key and interface name as value
650
+ # +coder+:: The HDL coder which is used
651
+ #
652
+ def gen_toplevel_con( name, src, dst, coder )
653
+
654
+ src_inst = {};
655
+ dst_inst = {};
656
+
657
+ #
658
+ # Get the interface specification by using the 1st source entry
659
+ # and searching for the core-definition.
660
+ #
661
+ ifc_spec = SOCMaker::lib.get_ifc(
662
+ core_definition( src.keys.first ).interfaces[ src.values.first ].id )
663
+
664
+
665
+ #
666
+ # For each signal in the interface specification,
667
+ # we create a list. The list has an entry for each source
668
+ # and destination signal, which defines the length.
669
+ #
670
+ # In the second step, we compare all values
671
+ #
672
+ length_tmp = Hash.new(0);
673
+ ifc_spec.ports.keys.each do |_name|
674
+ length_tmp[ _name ] = 0
675
+
676
+ ref_val = nil;
677
+ ref_inst_name = nil;
678
+ ref_ifc_name = nil;
679
+
680
+
681
+ [ dst, src].each do |con_hash|
682
+
683
+ con_hash.each_with_index do | (inst_name, ifc_name), i|
684
+
685
+ length = port_length( ifc_name, _name, inst_name )
686
+ if length.to_i > 0
687
+ if ref_val == nil
688
+ ref_val = port_length( ifc_name, _name, inst_name )
689
+ ref_inst_name = inst_name
690
+ ref_ifc_name = ifc_name
691
+ length_tmp[ _name ] = ref_val
692
+ end
693
+
694
+ consistence_error "Can't connect port #{_name}",
695
+ length_1: ref_val,
696
+ instance_1: ref_inst_name,
697
+ interface_1: ref_ifc_name,
698
+ length_2: length,
699
+ instance_2: inst_name,
700
+ interface_2: ifc_name if ref_val.to_i != length.to_i
701
+
702
+ length_tmp[ _name ] = length
703
+ end
704
+ end
705
+ end
706
+ end
707
+
708
+
709
+ #
710
+ # Prepare a hash for all sources and destinations, where
711
+ # the instance name is the key and the core-instance is
712
+ # the value.
713
+ #
714
+ src.keys.each do |inst_name|
715
+ src_inst[ inst_name ] = core_instance( inst_name )
716
+ end
717
+ dst.keys.each do |inst_name|
718
+ dst_inst[ inst_name ] = core_instance( inst_name )
719
+ end
720
+
721
+ #
722
+ # create the declaraion and assignments
723
+ #
724
+ coder.add_ifc_connection( ifc_spec, name, length_tmp, src_inst, dst_inst, src, dst )
725
+
726
+ end
727
+
728
+
729
+ #
730
+ # Returns a core instance, identified by its name.
731
+ # If it is not a sub-core, we return our self
732
+ #
733
+ # +inst+:: name of the instance
734
+ #
735
+ def core_instance( inst )
736
+ if @cores[ inst ] != nil
737
+ return @cores[ inst ]
738
+ else
739
+ return self
740
+ end
741
+ end
742
+
743
+ #
744
+ # Returns a port, identified by the interface and port name
745
+ # Note: this behaviour is exactly the same than of core_inst.port(...),
746
+ # but these ports are not evaluated.
747
+ #
748
+ # +ifc_name+:: name of the interface
749
+ # +port_ref+:: name of the port
750
+ #
751
+ def port( ifc_name, port_ref )
752
+
753
+ ifc = @interfaces[ ifc_name ]
754
+
755
+ # get interface specification
756
+ ifc_spc = SOCMaker::lib.get_ifc( ifc.id )
757
+
758
+ # get the port
759
+ port_tmp = ifc.ports.select{ |k,v| v.spc_ref.to_sym == port_ref }
760
+
761
+ # get the reference to the port definition
762
+ defn_ref = port_tmp.first[1].spc_ref.to_sym
763
+
764
+ _port_name = port_tmp.first[0].to_s
765
+
766
+ if ifc_spc.ports[ defn_ref ][ :dir ] == 2
767
+ _port_dir = 1 ^ ifc.dir
768
+ else
769
+ _port_dir = ifc_spc.ports[ defn_ref ][ :dir ] ^ ifc.dir
770
+ end
771
+
772
+ _port_default = ifc_spc.ports[ defn_ref ][ :default ]
773
+
774
+ _port_len = port_tmp.first[1].len
775
+
776
+ return [ _port_name, { len: _port_len, dir: _port_dir, default: _port_default, ref: port_tmp.first[1].spc_ref } ]
777
+ end
778
+
779
+
780
+ #
781
+ # Method to get all id's of all cores, sub-socs (recursively)
782
+ #
783
+ def all_core_id
784
+ @cores.values.map{ |c| c.defn.all_core_id }.flatten! << @id
785
+ end
786
+
787
+
788
+ #
789
+ # Method to get all static parameters of all cores, sub-socs (recursively)
790
+ #
791
+ def all_static_parameters
792
+ tmp = { @id => @static }
793
+ @cores.values.each { |v| tmp.merge!( v.defn.all_static_parameters ) }
794
+ return tmp
795
+ end
796
+
797
+
798
+ #
799
+ # Equality operator
800
+ #
801
+ def ==(o)
802
+ o.class == self.class &&
803
+ o.cores == self.cores &&
804
+ o.cons == self.cons &&
805
+ o.static == self.static &&
806
+ super( o )
807
+ end
808
+
809
+
810
+ #
811
+ # Returns a string describing this instance
812
+ #
813
+ def to_s
814
+
815
+ tmp = "_________ SOC #{@name}: _______\n" +
816
+ super +
817
+ "\n__connections__\n"
818
+
819
+ @cons.each do |_con_name, con_def|
820
+ tmp += "#{_con_name}: #{con_def}\n"
821
+ end
822
+
823
+ tmp += "\n__cores__\n"
824
+ @cores.each do |inst_name, inst|
825
+ tmp += "#{inst_name}:\n#{inst}\n"
826
+ end
827
+
828
+
829
+ tmp += "\n__interfaces__\n"
830
+ @interfaces.each do |ifc_name, ifc|
831
+ tmp += "#{ifc_name}:#{ifc.id}\n"
832
+ end
833
+
834
+ tmp += "'''''''''''''''''''''''''''''''''''\n"
835
+ return tmp
836
+ end
837
+
838
+ private :assign_unused_to_default,
839
+ :gen_toplevel_con,
840
+ :core_instance
841
+
842
+
843
+ end # class SOCSpec
844
+ end # module SOCMaker
845
+
846
+
847
+ # vim: noai:ts=2:sw=2