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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/History.txt +4 -0
- data/LICENSE +678 -0
- data/README.rdoc +228 -0
- data/Rakefile +46 -0
- data/bin/soc_maker_cli +80 -0
- data/bin/soc_maker_parser +85 -0
- data/core_lib/cores/adv_debug_sys/01_adv_debug_sys.yaml +245 -0
- data/core_lib/cores/or1200_rel2/01_or1200.yaml +208 -0
- data/core_lib/cores/or1200_rel2/02_or1200_files.yaml +421 -0
- data/core_lib/cores/or1200_rel2/03_or1200_sparam.yaml +188 -0
- data/core_lib/cores/or1200_rel2/or1200_defines.v.in +1799 -0
- data/core_lib/cores/ram_wb/ram_wb.yaml +102 -0
- data/core_lib/cores/ram_wb/ram_wb_b3.v.in +259 -0
- data/core_lib/cores/uart16550/01_uart16550.yaml +99 -0
- data/core_lib/cores/uart16550/02_uart16550_files.yaml +70 -0
- data/core_lib/cores/wb_connect/minsoc_tc_top.v +1802 -0
- data/core_lib/cores/wb_connect/wb_connect.yaml +733 -0
- data/core_lib/inc.yaml +13 -0
- data/core_lib/interfaces/clk_rst/clk.yaml +9 -0
- data/core_lib/interfaces/clk_rst/rst.yaml +9 -0
- data/core_lib/interfaces/clk_rst/single.yaml +7 -0
- data/core_lib/interfaces/debug/debug.yaml +32 -0
- data/core_lib/interfaces/jtag/jtag.yaml +13 -0
- data/core_lib/interfaces/jtag/jtag_tap.yaml +22 -0
- data/core_lib/interfaces/power/or_power.yaml +25 -0
- data/core_lib/interfaces/uart/uart.yaml +21 -0
- data/core_lib/interfaces/wishbone/wishbone_ma_b3.yaml +54 -0
- data/core_lib/interfaces/wishbone/wishbone_sl_b3.yaml +51 -0
- data/doc/class_arch.uml +5113 -0
- data/doc/fig/hierarchical.svg +273 -0
- data/examples/or1200_test/or1200_test.cmd +78 -0
- data/examples/or1200_test/or1200_test.rb +136 -0
- data/examples/or1200_test/rtl/or1200_test_top.vhd +274 -0
- data/examples/or1200_test/rtl/s3astarter.ucf +10 -0
- data/examples/or1200_test/rtl/xilinx_internal_jtag.v +438 -0
- data/examples/or1200_test/rtl/xilinx_internal_jtag_options.v +12 -0
- data/examples/or1200_test/sw/README.txt +35 -0
- data/examples/or1200_test/sw/bin2vmem.c +159 -0
- data/examples/or1200_test/sw/board.h +24 -0
- data/examples/or1200_test/sw/compile.sh +18 -0
- data/examples/or1200_test/sw/except.S +152 -0
- data/examples/or1200_test/sw/int.c +79 -0
- data/examples/or1200_test/sw/int.h +14 -0
- data/examples/or1200_test/sw/interconnect.h +17 -0
- data/examples/or1200_test/sw/interrupts.c +14 -0
- data/examples/or1200_test/sw/main.c +16 -0
- data/examples/or1200_test/sw/or1200.h +454 -0
- data/examples/or1200_test/sw/orp.ld +60 -0
- data/examples/or1200_test/sw/reset.S +112 -0
- data/examples/or1200_test/sw/support.c +123 -0
- data/examples/or1200_test/sw/support.h +33 -0
- data/examples/or1200_test/sw/tick.c +30 -0
- data/examples/or1200_test/sw/tick.h +2 -0
- data/examples/or1200_test/sw/uart.c +136 -0
- data/examples/or1200_test/sw/uart.h +126 -0
- data/lib/soc_maker.rb +324 -0
- data/lib/soc_maker/cli.rb +544 -0
- data/lib/soc_maker/conf.rb +310 -0
- data/lib/soc_maker/core_def.rb +579 -0
- data/lib/soc_maker/core_inst.rb +305 -0
- data/lib/soc_maker/err.rb +211 -0
- data/lib/soc_maker/hdl_coder.rb +500 -0
- data/lib/soc_maker/hdl_file.rb +166 -0
- data/lib/soc_maker/hdl_parser.rb +431 -0
- data/lib/soc_maker/ifc_def.rb +193 -0
- data/lib/soc_maker/ifc_port.rb +133 -0
- data/lib/soc_maker/ifc_spc.rb +180 -0
- data/lib/soc_maker/lib.rb +289 -0
- data/lib/soc_maker/lib_inc.rb +109 -0
- data/lib/soc_maker/parameter.rb +149 -0
- data/lib/soc_maker/soc_def.rb +847 -0
- data/lib/soc_maker/sparameter.rb +289 -0
- data/lib/soc_maker/version.rb +8 -0
- data/lib/soc_maker/ypp.rb +130 -0
- data/soc_maker.gemspec +28 -0
- data/spec/cli_cmds1.txt +39 -0
- data/spec/cli_spec.rb +49 -0
- data/spec/conf_spec.rb +44 -0
- data/spec/core_def_spec.rb +503 -0
- data/spec/core_inst_spec.rb +169 -0
- data/spec/hdl_file_spec.rb +154 -0
- data/spec/hdl_parser_spec.rb +201 -0
- data/spec/ifc_def_spec.rb +121 -0
- data/spec/ifc_port_spec.rb +92 -0
- data/spec/ifc_spc_spec.rb +196 -0
- data/spec/lib_inc_spec.rb +99 -0
- data/spec/lib_spec.rb +209 -0
- data/spec/parameter_spec.rb +86 -0
- data/spec/soc_def_spec.rb +611 -0
- data/spec/soc_maker_spec.rb +7 -0
- data/spec/sparameter_spec.rb +182 -0
- data/spec/spec_helper.rb +78 -0
- data/spec/test_soc.yaml +105 -0
- data/spec/test_soc2.yaml +60 -0
- data/spec/test_soc_lib/cores/core_A_rel1/00_core_a.yaml +75 -0
- data/spec/test_soc_lib/cores/core_A_rel1/01_core_a.yaml +57 -0
- data/spec/test_soc_lib/cores/core_A_rel1/core_a.vhd +29 -0
- data/spec/test_soc_lib/cores/core_A_rel1/core_a_pkg.vhd.src +3 -0
- data/spec/test_soc_lib/cores/core_A_rel1/core_a_pkg2.vhd.src +4 -0
- data/spec/test_soc_lib/cores/core_A_rel1/core_a_pkg3.v.src +6 -0
- data/spec/test_soc_lib/cores/core_B_rel1/core_b.vhd +25 -0
- data/spec/test_soc_lib/cores/core_B_rel1/core_b.yaml +36 -0
- data/spec/test_soc_lib/cores/core_C_v1/core_C.vhd +57 -0
- data/spec/test_soc_lib/cores/core_C_v1/core_c.yaml +42 -0
- data/spec/test_soc_lib/cores/soc_A/soc_A.yaml +12 -0
- data/spec/test_soc_lib/cores/soc_maker_include.yaml +6 -0
- data/spec/test_soc_lib/ifcs/core_AB_ifc/bidir_ifc.yaml +19 -0
- data/spec/test_soc_lib/ifcs/core_AB_ifc/core_AB_ifc.yaml +15 -0
- data/spec/test_soc_lib/ifcs/core_AB_ifc/top_ifc.yaml +9 -0
- data/spec/test_soc_lib/soc_maker_include.yaml +4 -0
- data/spec/yaml_examples.rb +367 -0
- data/spec/ypp_spec.rb +156 -0
- data/test/test_soc_maker.rb +0 -0
- 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
|