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,310 @@
1
+ ###############################################################
2
+ #
3
+ # File: conf.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
+
35
+ module SOCMaker
36
+
37
+ ###
38
+ #
39
+ # This class holds all the configuration and is
40
+ # realized as singleton.
41
+ # The instance can be accessed via Conf.instance
42
+ # The configuration is splitted into two parts:
43
+ # - @data -> user-configurable
44
+ # - @data_ro -> read-only
45
+ #
46
+ # Examples:
47
+ # c = Conf.instance
48
+ # c[ :app_nam ] # SOC-Maker
49
+ # c[ :build_dir ] # build
50
+ #
51
+ #
52
+ #
53
+ class Conf
54
+ include YAML_EXT
55
+ include ERR
56
+
57
+ #
58
+ # Config file path. This is fixed and can't be modified.
59
+ #
60
+ @@conf_file_path = 'socm_conf.yaml'
61
+
62
+
63
+
64
+ #
65
+ # new is private to ensure singleton behaviour
66
+ #
67
+ private_class_method :new
68
+
69
+ #
70
+ # Method to access the singleton instance:
71
+ # Within the first call, this method tries to load the config from
72
+ # the file. If the file doesn exist, a new instance is created.
73
+ #
74
+ # *return*:: the config instance
75
+ #
76
+ def Conf.instance
77
+ if @@inst == nil
78
+ if File.file?( @@conf_file_path )
79
+ @@inst = YAML::load_file( @@conf_file_path )
80
+ else
81
+ @@inst = new
82
+ end
83
+ end
84
+ return @@inst
85
+ end
86
+
87
+ #
88
+ # Method to write the config to the file system
89
+ #
90
+ def Conf.write
91
+ File.open( 'socm_conf.yaml', 'w' ) { |f| f.write( @@inst.to_yaml ) }
92
+ end
93
+
94
+ #
95
+ # Private constructor: it initializes all data
96
+ #
97
+ def initialize( )
98
+
99
+
100
+ init_with( { 'data' => {
101
+
102
+ # array of core search paths
103
+ :cores_search_path => [ './' ],
104
+
105
+ # VHDL include directive
106
+ :vhdl_include => "library ieee;\nuse ieee.std_logic_1164.ALL;",
107
+
108
+ # build directory, where the whole synthese and build process
109
+ # happens
110
+ :build_dir => 'build',
111
+
112
+ # the folder inside build_dir, where all the vhdl source is placed
113
+ :hdl_dir => 'hdl',
114
+
115
+ # synthesis directory inside build_dir
116
+ :syn_dir => 'syn',
117
+
118
+ # simulation directory inside build_dir
119
+ :sim_dir => 'sim'
120
+
121
+ } } )
122
+ end
123
+
124
+ #
125
+ # Encoder function (to yaml)
126
+ #
127
+ # +coder+:: An instance of the Psych::Coder to encode this class to a YAML file
128
+ #
129
+ def encode_with( coder )
130
+ puts "ENCODE_WITH CALLED"
131
+ init_error_if !coder.is_a?( Psych::Coder ),
132
+ 'coder is not given as Psych::Coder'
133
+ coder[ 'data' ] = @data
134
+ end
135
+
136
+ #
137
+ # Initialization function (from yaml)
138
+ #
139
+ # +coder+:: An instance of the Psych::Coder to init this class from a YAML file
140
+ #
141
+ #
142
+ def init_with( coder )
143
+
144
+ init_error_if !( coder.is_a?( Hash ) || coder.is_a?( Psych::Coder ) ),
145
+ 'coder is not given as Hash neither as Psych::Coder'
146
+
147
+ init_error "No configuration data provided",
148
+ field: 'data' if coder[ 'data' ] == nil
149
+
150
+ @data = coder[ 'data' ]
151
+
152
+ %w[ vhdl_include
153
+ build_dir hdl_dir
154
+ syn_dir sim_dir ].each do |d|
155
+ raise InitError.new(
156
+ "Data field '#{d}' is not provided",
157
+ field: 'data' ) if @data[ d.to_sym ] == nil
158
+
159
+ raise InitError.new(
160
+ "Data field '#{d}' is not of type String",
161
+ field: 'data' ) if !@data[ d.to_sym ].is_a?( String )
162
+
163
+ raise InitError.new(
164
+ "Data field '#{d}' is not of type String",
165
+ field: 'data' ) if @data[ d.to_sym ].size == 0
166
+ end
167
+
168
+
169
+ @data_ro = {
170
+
171
+ # the name of this application/tool
172
+ :app_name => 'SOC-Maker',
173
+
174
+ # the name of the tool's commandline interface
175
+ :app_cli_name => 'SOC-Maker CLI',
176
+
177
+
178
+ # All classes, which can be loaded by this software
179
+ :yaml_classes => [ SOCMaker::CoreDef,
180
+ SOCMaker::SOCDef,
181
+ SOCMaker::IfcSpc,
182
+ SOCMaker::LibInc,
183
+ SOCMaker::Conf,
184
+ SOCMaker::CoreInst ],
185
+
186
+ # Regular expression, which is evaluatted to detect values like
187
+ # eval function_name
188
+ # The function_name is used for further processing
189
+ :eval_regex => /eval +([a-zA-Z_1-9]+)/,
190
+
191
+ # Regular expression to check, if it is VHDL or verilog
192
+ :hdl_type_regex => /(\bvhdl\b)|(\bverilog\b)/,
193
+
194
+ #
195
+ # Regular expression for vhdl file detection
196
+ #
197
+ :vhdl_file_regex => /\A\S+\.vhd\Z/,
198
+
199
+ #
200
+ # Regular expression for verilog file detection
201
+ #
202
+ :verilog_file_regex => /\A\S+\.v\Z/,
203
+
204
+
205
+ #
206
+ # Regular expression to match names starting with non-number
207
+ #
208
+ :length_regex => /\A[^0-9]+.*\Z/,
209
+
210
+ #
211
+ # Regular expression to match a component's name (core-name or SOC-name)
212
+ # (Obsolete)
213
+ #
214
+ :name_regex => /^[a-zA-Z]+[a-zA-Z0-9_\-]*$/,
215
+
216
+
217
+ :YPP_LUT => {
218
+ /\bSOCM_CONF\b/ => '--- !ruby/object:SOCMaker::Conf',
219
+ /\bSOCM_CORE\b/ => '--- !ruby/object:SOCMaker::CoreDef',
220
+ /\bSOCM_SOC\b/ => '--- !ruby/object:SOCMaker::SOCDef',
221
+ /\bSOCM_IFC_SPC\b/ => '--- !ruby/object:SOCMaker::IfcSpc',
222
+ /\bSOCM_INCLUDE\b/ => '--- !ruby/object:SOCMaker::LibInc',
223
+ /\bSOCM_INST\b/ => '!ruby/object:SOCMaker::CoreInst',
224
+ /\bSOCM_IFC\b/ => '!ruby/object:SOCMaker::IfcDef',
225
+ /\bSOCM_PORT\b/ => '!ruby/object:SOCMaker::IfcPort',
226
+ /\bSOCM_HDL_FILE\b/ => '!ruby/object:SOCMaker::HDLFile',
227
+ /\bSOCM_PARAM\b/ => '!ruby/object:SOCMaker::Parameter',
228
+ /\bSOCM_SPARAM\b/ => '!ruby/object:SOCMaker::SParameter',
229
+ /\bSOCM_SENTRY\b/ => '!ruby/object:SOCMaker::SParameterEntry'
230
+ },
231
+ #
232
+ # $1 provides the white spaces
233
+ # $2 the name
234
+ #
235
+ :YPP_INV_REGEX => /(\s)*-{0,3}\s*!ruby\/object:SOCMaker::([a-zA-Z]+)/,
236
+
237
+ :YPP_INV_LUT => {
238
+ 'Conf' => 'SOCM_CONF',
239
+ 'CoreDef' => 'SOCM_CORE',
240
+ 'SOCDef' => 'SOCM_SOC',
241
+ 'CoreInst' => 'SOCM_INST',
242
+ 'IfcSpc' => 'SOCM_IFC_SPC',
243
+ 'IfcDef' => 'SOCM_IFC',
244
+ 'IfcPort' => 'SOCM_PORT',
245
+ 'HDLFile' => 'SOCM_HDL_FILE',
246
+ 'Parameter' => 'SOCM_PARAM',
247
+ 'SParameter' => 'SOCM_SPARAM',
248
+ 'SParameterEntry' => 'SOCM_SENTRY',
249
+ 'LibInc' => 'SOCM_INCLUDE'
250
+ },
251
+
252
+ # used to split yaml files
253
+ #
254
+ :YPP_SPLIT_REGEX => /^\s*---\s*!ruby\/(object|object):SOCMaker/,
255
+
256
+
257
+ :COMMENT_REGEX => /([^#]*)(#.*)?/,
258
+
259
+ :EMPTY_CMD_REGEX => /(\s*)(.*)/,
260
+
261
+ :LIC =>
262
+ """
263
+ Copyright (C) 2014 Christian Haettich - feddischson [ at ] opencores.org
264
+
265
+ This program is free software: you can redistribute it and/or modify
266
+ it under the terms of the GNU General Public License as published by
267
+ the Free Software Foundation, either version 3 of the License, or
268
+ (at your option) any later version.
269
+
270
+ This program is distributed in the hope that it will be useful,
271
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
272
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
273
+ GNU General Public License for more details.
274
+
275
+ You should have received a copy of the GNU General Public License
276
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
277
+ """
278
+
279
+
280
+ }
281
+ end
282
+
283
+ #
284
+ # Read access via array operator:
285
+ # config from @data and @data_ro can be accessed.
286
+ #
287
+ def [](y)
288
+ @data.merge( @data_ro )[y]
289
+ end
290
+
291
+ #
292
+ # Write access via array operator:
293
+ # config from @data can be accessed, @data_ro not.
294
+ #
295
+ def []=(y, value)
296
+ @data[y] = value if @data.has_key?( y )
297
+ end
298
+
299
+ #
300
+ # The singleton instance. It is initialized by the first
301
+ # Conf::instance mehtod call.
302
+ #
303
+ @@inst = nil
304
+
305
+ end
306
+
307
+ end
308
+
309
+
310
+ # vim: noai:ts=2:sw=2
@@ -0,0 +1,579 @@
1
+ ###############################################################
2
+ #
3
+ # File: core_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
+ #
40
+ # This class represents a core definition.
41
+ # It is one of the central classes and holds data,
42
+ # which is used to describe and instanciate a IP core.
43
+ # In general, instances of this class desribe a core,
44
+ # it's interface and parameters as well as the files,
45
+ # which are required for synthesis/simulation.
46
+ #
47
+ # In addition to this core, there exist SOCMaker::CoreInst,
48
+ # which represents a concret instanciation of a definition.
49
+ #
50
+ class CoreDef
51
+ include ERR
52
+ include YAML_EXT
53
+
54
+
55
+ # name of the core (mandatory)
56
+ attr_accessor :name
57
+
58
+ # ID of the core (mandatory, stored as hash key)
59
+ attr_accessor :id
60
+
61
+ # toplevel name (mandatory)
62
+ attr_accessor :toplevel
63
+
64
+ # description of this core
65
+ attr_accessor :description
66
+
67
+ # creation date
68
+ attr_accessor :date
69
+
70
+ # license of this core
71
+ attr_accessor :license
72
+
73
+ # location of the license file
74
+ attr_accessor :licensefile
75
+
76
+ # author of this core
77
+ attr_accessor :author
78
+
79
+ # author-mail of this core
80
+ attr_accessor :authormail
81
+
82
+ # a version control command, which is used to download the files
83
+ attr_accessor :vccmd
84
+
85
+ # interfaces which are implemented see SOCMaker::IfcSpc
86
+ attr_accessor :interfaces
87
+
88
+ # reserved and not implemented
89
+ attr_accessor :functions
90
+
91
+ # hash of instantiation parameters see SOCMaker::Parameter
92
+ attr_accessor :inst_parameters
93
+
94
+ # hash of static parameters see SOCMaker::SParameter
95
+ attr_accessor :static_parameters
96
+
97
+ # the ID, but withou commata and as string, can be used
98
+ # for creating paths and so on
99
+ attr_accessor :id_clean
100
+
101
+ # Hash of SOCMaker::HDLFile
102
+ attr_accessor :hdlfiles
103
+
104
+
105
+ #
106
+ # Constructor:
107
+ # the three attributes name, id and toplevel are required. All other attributes
108
+ # can be given as a optinal hash.
109
+ #
110
+ # +name+:: Name of this core (string)
111
+ # +id+:: Id of this core (string)
112
+ # +toplevel+:: Toplevel name of this core (string)
113
+ # +optional+:: Non-mandatory values, which can be set during initialization.
114
+ #
115
+ #
116
+ def initialize( name, id, toplevel, optional = {} )
117
+ init_with( { 'name' => name,
118
+ 'id' => id,
119
+ 'toplevel' => toplevel }.merge( optional ) )
120
+ end
121
+
122
+ #
123
+ # Encoder method (to yaml)
124
+ #
125
+ # +coder+:: An instance of the Psych::Coder to encode this class to a YAML file
126
+ #
127
+ def encode_with( coder )
128
+ init_error_if !coder.is_a?( Psych::Coder ),
129
+ 'coder is not given as Psych::Coder'
130
+ %w[ name description date license licensefile
131
+ author authormail vccmd toplevel interfaces
132
+ functions inst_parameters static_parameters hdlfiles ].
133
+ each { |v| coder[ v ] = instance_variable_get "@#{v}" }
134
+
135
+ coder[ "id" ] = @id.to_s
136
+ end
137
+
138
+ #
139
+ # Initialization method (from yaml)
140
+ #
141
+ # +coder+:: An instance of the Psych::Coder to init this class from a YAML file
142
+ #
143
+ #
144
+ def init_with( coder )
145
+ init_error_if !( coder.is_a?( Hash ) || coder.is_a?( Psych::Coder ) ),
146
+ 'coder is not given as Hash neither as Psych::Coder'
147
+
148
+ @name = coder[ 'name' ]
149
+ @toplevel = coder[ 'toplevel' ]
150
+
151
+ # check name
152
+ init_error 'Name must be of type string', field: 'name' if !@name.is_a?( String )
153
+ init_error 'Name is not defined (size == 0)', field: 'name' if @name.size == 0
154
+
155
+ # check id
156
+ init_error 'Id must be of type string',
157
+ field: 'id' if !coder[ 'id' ].is_a?( String )
158
+
159
+ @id = coder[ 'id' ].to_sym
160
+
161
+ init_error 'Id not defined (size == 0)',
162
+ instance: @name,
163
+ field: 'id' if @id.size == 0
164
+ @id_clean = coder[ 'id' ].split(',').join("_")
165
+
166
+
167
+
168
+
169
+
170
+ init_error "toplevel must be of type string",
171
+ instance: @name,
172
+ field: "toplevel" if !@toplevel.is_a?( String )
173
+
174
+ init_error 'Toplevel not defined (size == 0 )',
175
+ instance: @name,
176
+ field: 'toplevel' if @toplevel.size == 0
177
+
178
+
179
+
180
+
181
+ # set non-nil values
182
+ # -> we don't need to check for nil in the rest of the
183
+ # processing
184
+ @description = coder[ 'description' ] || ""
185
+ @date = coder[ 'date' ] || ""
186
+ @license = coder[ 'license' ] || ""
187
+ @licensefile = coder[ 'licensefile' ] || ""
188
+ @author = coder[ 'author' ] || ""
189
+ @authormail = coder[ 'authormail' ] || ""
190
+ @vccmd = coder[ 'vccmd' ] || ""
191
+ @interfaces = coder[ 'interfaces' ] || {}
192
+ @functions = coder[ 'functions' ] || {}
193
+ @inst_parameters = coder[ 'inst_parameters' ] || {}
194
+ @static_parameters = coder[ 'static_parameters' ] || {}
195
+ @hdlfiles = coder[ 'hdlfiles' ] || {}
196
+
197
+
198
+ # ensure, that these fields are of type String
199
+ %w[ description date license licensefile
200
+ author authormail vccmd ].each do |n|
201
+
202
+ init_error "#{n} must be of type String",
203
+ instance: @name,
204
+ field: n if !instance_variable_get( '@'+n ).is_a?( String )
205
+ end
206
+
207
+ # ensure, that these fields are of type Hash
208
+ %w[ interfaces inst_parameters
209
+ functions static_parameters ].each do |n|
210
+ init_error "#{n} must be of type Hash",
211
+ instance: @name,
212
+ field: n if !instance_variable_get( '@'+n ).is_a?( Hash )
213
+
214
+ end
215
+
216
+
217
+
218
+ # check interfaces
219
+ @interfaces.each do |ifc_name, ifc|
220
+ init_error 'Interface not defined',
221
+ instance: @name,
222
+ interface: ifc_name if ifc == nil
223
+
224
+ init_error 'Interface definition is not SOCMaker::IfcDef (please use SOCM_IFC)',
225
+ instance: @name,
226
+ interface: ifc_name if !ifc.is_a?( SOCMaker::IfcDef )
227
+ end
228
+
229
+ # check instance parameters
230
+ @inst_parameters.each do |name, param |
231
+
232
+ init_error 'Instance parameter not SOCMaker::Parameter (please use SOCM_PARAM)',
233
+ instance: @name,
234
+ parameter: name if !param.is_a?( SOCMaker::Parameter )
235
+ end
236
+
237
+ # check instance parameters
238
+ @static_parameters.each do |name, sparam |
239
+
240
+ init_error 'Static parameter not SOCMaker::Parameter (please use SOCM_SPARAM)',
241
+ instance: @name,
242
+ parameter: name if !sparam.is_a?( SOCMaker::SParameter )
243
+ end
244
+
245
+
246
+ init_error 'HDL files argument is not of type Hash',
247
+ instance: @name,
248
+ field: 'hdlfiles' if !@hdlfiles.is_a?( Hash )
249
+
250
+
251
+ # check hdl files
252
+ @hdlfiles.each do |file_name, file_info |
253
+
254
+ init_error 'HDL file not defined',
255
+ instance: @name,
256
+ filename: file_name if file_info == nil
257
+
258
+ init_error 'HDL file is not of type SOCMaker::HDLFile (use SOCM_HDL_FILE)',
259
+ instance: @name,
260
+ filename: file_name if !file_info.is_a?( SOCMaker::HDLFile )
261
+ end
262
+
263
+ end
264
+
265
+ #
266
+ # The directory name of this core (returns @id_clean)
267
+ #
268
+ def dir_name
269
+ @id_clean
270
+ end
271
+
272
+
273
+ #
274
+ # Method to get an interface specification, used
275
+ # by this core. The interface is identified by it's
276
+ # name (within this core)
277
+ #
278
+ # +ifc_name+:: Interface name (within this core, not the ID)
279
+ #
280
+ def ifc_specification( ifc_name )
281
+ SOCMaker::lib.get_ifc( @interfaces[ ifc_name ].id )
282
+ end
283
+
284
+
285
+ #
286
+ # Runs the Version Control System command via system(....)
287
+ #
288
+ def update_vcs
289
+ unless self.vccmd.nil? or @vccmd.size == 0
290
+ #puts"cd #{@dir} && #{@vccmd}"
291
+ system( "cd #{@src_dir} && #{vccmd}" )
292
+ end
293
+ end
294
+
295
+
296
+
297
+
298
+
299
+
300
+ #
301
+ # Runs a consistence check:
302
+ # Iterate over all interfaces and check, if the interface is
303
+ # in the SOCMaker::Lib.
304
+ # The method also checks also, if the ports defined by this
305
+ # core is also defined in the interface.
306
+ #
307
+ def consistence_check
308
+ @interfaces.values.each_with_index do | ifc, i_ifc; ifc_spc|
309
+
310
+ # get interface definition
311
+ ifc_spc = SOCMaker::lib.get_ifc( ifc.id )
312
+
313
+
314
+
315
+ # check if all refereces (to the ports) exist
316
+ ifc.ports.each_with_index do |(port_name, port_def), i_port |
317
+ spc_ref = port_def.spc_ref.to_sym
318
+ consistence_error_if(
319
+ !ifc_spc.ports.has_key?( spc_ref ),
320
+ "Can't find #{port_def} in" +
321
+ "interface definition #{ifc_spc.name} ",
322
+ id: ifc_spc.id,
323
+ portname: port_name )
324
+ end
325
+
326
+
327
+ # check, if all mandatory ports are implemented by this interface
328
+ ifc_spc.ports.each do | port_name, port |
329
+ consistence_error_if(
330
+ port[ :mandatory ] == true &&
331
+ ifc.ports.select{ |key,port_def| port_def.spc_ref.to_sym == port_name }.size == 0,
332
+ "Mandatory port #{port_name} is not implemented in interface #{ifc.name}",
333
+ port: port_name,
334
+ interface: ifc.name )
335
+ end
336
+
337
+ end
338
+
339
+ end
340
+
341
+
342
+
343
+
344
+
345
+ #
346
+ # Iterates over all generic values of this core
347
+ # and yield the call block with
348
+ # - generic name
349
+ # - generic type
350
+ # - generic default
351
+ # - is-last value
352
+ def generics
353
+ @inst_parameters.each_with_index do |(name, val), i|
354
+
355
+ _generic_name = name.to_s
356
+ _generic_type = val.type
357
+ _generic_default = val.default
358
+ _is_last = i == @inst_parameters.size-1
359
+ yield( _generic_name ,
360
+ _generic_type ,
361
+ _generic_default,
362
+ _is_last )
363
+
364
+ end
365
+ end
366
+
367
+
368
+
369
+ #
370
+ # Iterates over interface list (if no argument is given)
371
+ # or all specified interfaces.
372
+ # For each interface, all ports are processed.
373
+ # For each port within each interface, we lookup the port spc_ref
374
+ # and yield the call block with
375
+ # - port-name
376
+ # - port length
377
+ # - default value
378
+ # - the spec-reference
379
+ # - is-last value
380
+ # as argument
381
+ #
382
+ # An xor mechanism between port_dir and ifc=>dir is used
383
+ # to determine the direction of a port, for example:
384
+ # If the interface is declared as input (1) and a port is declared as input (1)
385
+ # the resulting direction will be an output 1^1 = 0.
386
+ # But if the overall interface direction is an output (0) and a port is declared
387
+ # as input, the resulting direction will an input 0^1 = 1.
388
+ # This allows to define a port-direction in the interface definition,
389
+ # and toggle the directions on core-definition level.
390
+ #
391
+ #
392
+ # +args+:: An optional list of interface names
393
+ def ports( *args )
394
+
395
+ if args.size == 0
396
+ ifc_sel = @interfaces
397
+ else
398
+ ifc_sel = @interfaces.select{ |k,v| args.include?( k.to_s ) }
399
+ end
400
+
401
+
402
+
403
+ ifc_sel.values.each_with_index do | ifc, i_ifc; ifc_spc|
404
+
405
+ # get interface specification
406
+ ifc_spc = SOCMaker::lib.get_ifc( ifc.id )
407
+
408
+ # loop over ports in this interface
409
+ ifc.ports.each_with_index do |(port_name, port_def), i_port |
410
+
411
+ # the reference to the port in the definition
412
+ spc_ref = port_def.spc_ref.to_sym
413
+
414
+ _port_name = port_name.to_s
415
+ if ifc_spc.ports[ spc_ref ][:dir] != 2
416
+ _port_dir = ifc_spc.ports[ spc_ref ][:dir] ^ ifc.dir
417
+ else
418
+ _port_dir = 2
419
+ end
420
+ _port_length = port_def.len
421
+ _port_default = ifc_spc.ports[ spc_ref ][ :default ]
422
+ _is_last = ( (i_port == ifc.ports.size-1 ) and (i_ifc == ifc_sel.size-1 ) )
423
+ yield( _port_name, _port_dir, _port_length, _port_default, port_def.spc_ref, _is_last )
424
+ end
425
+ end
426
+ end
427
+
428
+ def add_interface( ifc_name, ifc_id, dir, ports )
429
+ processing_error_if( @interfaces.has_key?( ifc_name.to_sym ),
430
+ "Interface name #{ifc_name} already exist",
431
+ name: ifc_name,
432
+ id_to_add: ifc_id )
433
+ @interfaces[ ifc_name.to_sym ] = SOCMaker::IfcDef.new( ifc_name, ifc_id, dir, ports );
434
+
435
+ end
436
+
437
+
438
+ def core_definition( inst )
439
+ return nil;
440
+ end
441
+
442
+
443
+ #
444
+ # Equality operator
445
+ #
446
+ def ==(o)
447
+
448
+ tmp = ( o.class == self.class )
449
+ return tmp if !tmp
450
+
451
+ %w[ name id description date license licensefile
452
+ author authormail vccmd toplevel interfaces
453
+ functions inst_parameters static_parameters hdlfiles ].
454
+ each do |v|
455
+ return false if instance_variable_get( "@#{v}" ) != o.instance_variable_get( "@#{v}" )
456
+ end
457
+ return true
458
+ end
459
+
460
+ #
461
+ # Returns a string describing this instance
462
+ #
463
+ def to_s
464
+ "id: #{@id}\n" +
465
+ "toplevel: #{@toplevel}\n" +
466
+ "description: #{@description}\n" +
467
+ "date: #{@date}\n" +
468
+ "license: #{@license}\n" +
469
+ "licensefile: #{@licensefile}\n" +
470
+ "author: #{@author}\n" +
471
+ "authormail: #{@authormail}\n" +
472
+ "vccmd: #{@vccmd}\n" +
473
+ "interfaces: #{@interfaces}\n" +
474
+ "functions: #{@functions}\n" +
475
+ "inst_parameters: #{@inst_parameters}\n" +
476
+ "static_parameters: #{@static_parameters}\n"
477
+ end
478
+
479
+
480
+
481
+ #
482
+ # Method, which counts the core occurence:
483
+ #
484
+ # +core_id_array+:: An array with id's, for example [ 'id1', 'id1', 'id2', 'id3' ]
485
+ # +return+:: A Hash with id => #ofOccurence mapping, for example { 'id1' => 2, 'id2' => 1, 'id3' => 1 }
486
+ #
487
+ def self.core_cnt( core_id_array )
488
+ cnt_hash = Hash.new( 0 )
489
+ core_id_array.each do |v|
490
+ cnt_hash[v] += 1
491
+ end
492
+ return cnt_hash
493
+ end
494
+
495
+
496
+
497
+ #
498
+ # Creates a core directory, if it doesn't exist.
499
+ # The path of the target directoy depends
500
+ # on SOCMaker::conf[ :build_dir ] and
501
+ # on SOCMaker::conf[ :hdl_dir ].
502
+ # The resulting path is
503
+ # ./build_dir/hdl_dir/dir_name
504
+ #
505
+ # +dir_name+:: Name of the target directory
506
+ #
507
+ def self.get_and_ensure_dst_dir!( dir_name )
508
+ dst_dir = File.expand_path(
509
+ File.join(
510
+ SOCMaker::conf[ :build_dir ],
511
+ SOCMaker::conf[ :hdl_dir ],
512
+ dir_name ) )
513
+ FileUtils.mkdir_p dst_dir
514
+ return dst_dir
515
+ end
516
+
517
+
518
+
519
+
520
+ #
521
+ # This method is required to allow recursive static parameter
522
+ # collection. Because this is a sigle core and doesn't have sub-cores
523
+ # (which might have some static parameters), an empty hash is returned.
524
+ #
525
+ def all_static_parameters
526
+ Hash.new()
527
+ end
528
+
529
+
530
+
531
+ #
532
+ # Method to deploy this core: all files are copied and deployed:
533
+ # - all hdl-files
534
+ # - all files with static-parameters
535
+ #
536
+ # +options+:: Optinal arguments: usually the static parameters are passed via
537
+ # options[ :static ]
538
+ #
539
+ def deploy( options={} )
540
+ options = { static: {} }.merge( options )
541
+
542
+ # create destination directory name and ensure, that it is exist
543
+ dst_dir = CoreDef::get_and_ensure_dst_dir!( dir_name )
544
+
545
+
546
+
547
+ # copy each file into destination dir
548
+ @hdlfiles.each do |file, val|
549
+ file_path = File.join( @src_dir, val.path )
550
+ dst_path = File.join( dst_dir, val.path )
551
+ SOCMaker::logger.proc( "copy #{file_path} to #{ dst_path} " )
552
+ FileUtils.mkdir_p(File.dirname(dst_path))
553
+ FileUtils.cp( file_path, dst_path )
554
+ end
555
+
556
+ # deploy all static-parameter files
557
+ @static_parameters.each do |file, sparam|
558
+ sparam.deploy( options[ :static ][ @id ], @src_dir, dst_dir )
559
+ end
560
+
561
+ end
562
+
563
+
564
+ #
565
+ # This method is required to allow recursive search of all IDs
566
+ # and returns only it's ID (because there are no sub-cores).
567
+ #
568
+ def all_core_id
569
+ [ @id ]
570
+ end
571
+
572
+
573
+
574
+ end # class CoreDef
575
+ end # module SOCMaker
576
+
577
+
578
+
579
+ # vim: noai:ts=2:sw=2