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,166 @@
|
|
1
|
+
###############################################################
|
2
|
+
#
|
3
|
+
# File: hdl_file.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
|
+
# Description:
|
36
|
+
#
|
37
|
+
#
|
38
|
+
#
|
39
|
+
#
|
40
|
+
###############################################################
|
41
|
+
|
42
|
+
module SOCMaker
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
# A small classes, used to group information
|
48
|
+
# and to verify, auto-correct and auto-complete
|
49
|
+
# this information:
|
50
|
+
# The class represents an high-level-description (HDL) file.
|
51
|
+
# The two supported file-types are *.vhdl and *.v, whose information
|
52
|
+
# is stored in #type ('verilog' or 'vhdl').
|
53
|
+
# A #path is mandatory and defines, where the file is located.
|
54
|
+
# In addition, is is used for auto-detecting the file-type (if not given).
|
55
|
+
# There are three flags:
|
56
|
+
# - #use_syn (use in synthesis)
|
57
|
+
# - #use_sys_sim (use in system simulation)
|
58
|
+
# - #use_mod_sim (use in module simulation)
|
59
|
+
# These flags are not used at the moment and reserved for
|
60
|
+
# future implementation.
|
61
|
+
class HDLFile
|
62
|
+
include ERR
|
63
|
+
|
64
|
+
# file path of the HDL file
|
65
|
+
attr_accessor :path
|
66
|
+
|
67
|
+
# synthesis flag
|
68
|
+
attr_accessor :use_syn
|
69
|
+
|
70
|
+
# system simulation flag (reserved and not used)
|
71
|
+
attr_accessor :use_sys_sim
|
72
|
+
|
73
|
+
# modul simulation flag (reserved and not used)
|
74
|
+
attr_accessor :use_mod_sim
|
75
|
+
|
76
|
+
# type of this hdl file: 'vhdl' or 'verilog'
|
77
|
+
attr_accessor :type
|
78
|
+
|
79
|
+
# The constructor gets the path as mandatory argument.
|
80
|
+
# Everything else can be passed with optional arguments
|
81
|
+
def initialize( path, optional = {} )
|
82
|
+
init_with( { 'path' => path }.merge( optional ) )
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Encoder method (to yaml)
|
87
|
+
#
|
88
|
+
# +coder+:: An instance of the Psych::Coder to encode this class to a YAML file
|
89
|
+
#
|
90
|
+
def encode_with( coder )
|
91
|
+
init_error_if !coder.is_a?( Psych::Coder ),
|
92
|
+
'coder is not given as Psych::Coder'
|
93
|
+
%w[ path use_syn use_sys_sim use_mod_sim type ].
|
94
|
+
each { |v| coder[ v ] = instance_variable_get "@#{v}" }
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Initialization method (from yaml)
|
99
|
+
#
|
100
|
+
# +coder+:: An instance of the Psych::Coder to init this class from a YAML file
|
101
|
+
#
|
102
|
+
#
|
103
|
+
def init_with( coder )
|
104
|
+
|
105
|
+
init_error_if !( coder.is_a?( Hash ) || coder.is_a?( Psych::Coder ) ),
|
106
|
+
'coder is not given as Hash neither as Psych::Coder'
|
107
|
+
|
108
|
+
# check path
|
109
|
+
init_error 'no filepath specified' if coder[ 'path' ] == nil
|
110
|
+
@path = coder[ 'path' ]
|
111
|
+
init_error 'path must be of type string' if !@path.is_a?( String )
|
112
|
+
|
113
|
+
# auto-complete to 'true'
|
114
|
+
@use_syn = coder[ 'use_syn' ] || true
|
115
|
+
@use_sys_sim = coder[ 'use_sys_sim' ] || true
|
116
|
+
@use_mod_sim = coder[ 'use_mod_sim' ] || true
|
117
|
+
|
118
|
+
# ensure, that the thee use... fields are boolean
|
119
|
+
init_error 'use_syn field must be true of false' if !!@use_syn != @use_syn
|
120
|
+
init_error 'use_sys_sim field must be true of false' if !!@use_sys_sim != @use_sys_sim
|
121
|
+
init_error 'use_mod_sim field must be true of false' if !!@use_mod_sim != @use_mod_sim
|
122
|
+
|
123
|
+
# if the file-type is not given, we try to auto-detect it
|
124
|
+
# *.vhd -> vhdl
|
125
|
+
# *.v -> verilog
|
126
|
+
# (see conf[ :vhdl_file_regex ] and
|
127
|
+
# conf[ :verilog_file_regex ] )
|
128
|
+
if coder[ 'type' ] == nil
|
129
|
+
if @path =~ SOCMaker::conf[ :vhdl_file_regex ]
|
130
|
+
SOCMaker::logger.warn "Auto-detected vhdl file type for #{ @path }"
|
131
|
+
@type = 'vhdl'
|
132
|
+
elsif @path =~ SOCMaker::conf[ :verilog_file_regex ]
|
133
|
+
SOCMaker::logger.warn "Auto-detected verilog file type for #{ @path }"
|
134
|
+
@type = 'verilog'
|
135
|
+
else
|
136
|
+
init_error "Cant auto-detect file type for #{path}"
|
137
|
+
end
|
138
|
+
else
|
139
|
+
# if the file-type is given, ensure, that it is either 'vhdl' or 'verilog'
|
140
|
+
init_error "The type must be 'vhdl' or 'verilog'",
|
141
|
+
instance: @path,
|
142
|
+
field: 'type' if !SOCMaker::conf[ :hdl_type_regex ].match( coder[ 'type' ] )
|
143
|
+
@type = coder[ 'type' ]
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
#
|
151
|
+
# Equality operator
|
152
|
+
#
|
153
|
+
def ==(o)
|
154
|
+
o.class == self.class &&
|
155
|
+
o.path == self.path &&
|
156
|
+
o.use_syn == self.use_syn &&
|
157
|
+
o.use_sys_sim == self.use_sys_sim &&
|
158
|
+
o.use_mod_sim == self.use_mod_sim &&
|
159
|
+
o.type == self.type
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# vim: noai:ts=2:sw=2
|
166
|
+
|
@@ -0,0 +1,431 @@
|
|
1
|
+
###############################################################
|
2
|
+
#
|
3
|
+
# File: hdl_parser.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) 2015 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
|
+
# Description:
|
36
|
+
#
|
37
|
+
#
|
38
|
+
#
|
39
|
+
###############################################################
|
40
|
+
|
41
|
+
|
42
|
+
require 'singleton'
|
43
|
+
require 'pathname'
|
44
|
+
|
45
|
+
module SOCMaker
|
46
|
+
|
47
|
+
class HDLParser
|
48
|
+
|
49
|
+
|
50
|
+
include ERR
|
51
|
+
|
52
|
+
# to organize it as singleton
|
53
|
+
#
|
54
|
+
include Singleton
|
55
|
+
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def get_content( file )
|
63
|
+
return File.open( file, "r"){ |f| f.read }
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def get_extension( file )
|
68
|
+
return File.extname( file )
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_all_hdl_files( files )
|
72
|
+
hdl_files = []
|
73
|
+
files.each { |f| hdl_files += Dir[f] }
|
74
|
+
return hdl_files
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
def parse_core( top_file, files, package_file = nil )
|
81
|
+
|
82
|
+
files = [ files ] if not files.kind_of?( Array )
|
83
|
+
|
84
|
+
#
|
85
|
+
# read and parse toplevel file
|
86
|
+
#
|
87
|
+
content = get_content( top_file )
|
88
|
+
if get_extension( top_file ) == ".v"
|
89
|
+
toplevel = VerilogParser.instance.parse_toplevel( content )
|
90
|
+
toplevel = VerilogParser.instance.extract_length( toplevel )
|
91
|
+
elsif get_extension( top_file ) == ".vhd"
|
92
|
+
toplevel = VHDLParser.instance.parse_toplevel( content )
|
93
|
+
toplevel = VHDLParser.instance.extract_length( toplevel )
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# read and parse package file
|
98
|
+
#
|
99
|
+
# -> not yet supported
|
100
|
+
#
|
101
|
+
if package_file != nil
|
102
|
+
content = get_content( package_file )
|
103
|
+
if get_extension( package_file ) == ".v"
|
104
|
+
package = VerilogParser.instance.parse_package( content )
|
105
|
+
elsif get_extension( top_file ) == ".vhd"
|
106
|
+
package = VerilogParser.instance.parse_package( content )
|
107
|
+
end
|
108
|
+
else
|
109
|
+
package = {}
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
#
|
114
|
+
# get all HDL files
|
115
|
+
#
|
116
|
+
hdl_files = get_all_hdl_files( files )
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
#
|
121
|
+
# Prepare options and ports hashes
|
122
|
+
#
|
123
|
+
options = { 'inst_parameters' => {},
|
124
|
+
'hdlfiles' => {},
|
125
|
+
'interfaces' => {} }
|
126
|
+
|
127
|
+
if toplevel.has_key?( :generic )
|
128
|
+
toplevel[ :generic ].values.each do | v |
|
129
|
+
options[ 'inst_parameters' ][ v[:name] ] = Parameter.new( v[ :type ], default: v[ :default ] )
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
ports = {}
|
134
|
+
if toplevel.has_key?( :port )
|
135
|
+
toplevel[ :port ].values.each do | v |
|
136
|
+
ports[ v[ :name ] ] = IfcPort.new( v[:name], v[:length] )
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
ifc_name = toplevel[:name].to_s + '_ifc'
|
141
|
+
ifc_id = ifc_name + ",v1"
|
142
|
+
options[ 'interfaces'][ ifc_name ] = IfcDef.new( ifc_name, ifc_id, 0, ports )
|
143
|
+
|
144
|
+
hdl_files.each do | f |
|
145
|
+
f_opts = {}
|
146
|
+
name = Pathname.new( f ).basename( ".*" ).to_s
|
147
|
+
if name.include? "sim"
|
148
|
+
f_opts[ 'use_syn' => false ]
|
149
|
+
f_opts[ 'use_mod_sim' => true ]
|
150
|
+
else
|
151
|
+
f_opts[ 'use_syn' => true ]
|
152
|
+
f_opts[ 'use_mod_sim' => false ]
|
153
|
+
end
|
154
|
+
options[ 'hdlfiles' ][ name ] = HDLFile.new( f, f_opts )
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# create new core
|
159
|
+
#
|
160
|
+
d = CoreDef.new( toplevel[ :name ],
|
161
|
+
toplevel[ :name ]+",v1",
|
162
|
+
toplevel[ :name ], options)
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
# dump the result
|
167
|
+
return SOCMaker::to_yaml_s( d )
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
class VerilogParser < HDLParser
|
176
|
+
|
177
|
+
include ERR
|
178
|
+
|
179
|
+
# to organize it as singleton
|
180
|
+
#
|
181
|
+
include Singleton
|
182
|
+
|
183
|
+
|
184
|
+
def initialize
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
def parse_toplevel( data )
|
189
|
+
# remove all newlines
|
190
|
+
data = data.gsub( "\n", " " )
|
191
|
+
|
192
|
+
# empty result hash
|
193
|
+
result = {}
|
194
|
+
|
195
|
+
module_regex = /\s*module\s+(\w+)*\s*\(.*?\);/
|
196
|
+
port_regex = /(input|output)\s*(\[([\d\w\-\:\s]*)\s*\])?\s*(\w*);/
|
197
|
+
parameter_regex = /parameter\s*(\w*)\s*=\s(.*?);/
|
198
|
+
|
199
|
+
|
200
|
+
# extract module name
|
201
|
+
if m = module_regex.match( data )
|
202
|
+
result[ :name ] = m[1]
|
203
|
+
else
|
204
|
+
result[ :name ] = "unknown"
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# extract parameteters
|
209
|
+
#
|
210
|
+
parameters = data.scan( parameter_regex )
|
211
|
+
result[ :generic ] = {}
|
212
|
+
parameters.each do |port|
|
213
|
+
|
214
|
+
result[ :generic ][ port[0] ] = { name: port[0], default: port[1], type: "integer" }
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
#
|
219
|
+
# extract ports
|
220
|
+
#
|
221
|
+
ports = data.scan( port_regex )
|
222
|
+
result[ :port ] = {}
|
223
|
+
ports.each do |port|
|
224
|
+
result[ :port ][ port[3] ] = { name: port[3] }
|
225
|
+
|
226
|
+
|
227
|
+
if port[0]
|
228
|
+
if port[0] == "input"
|
229
|
+
result[ :port ][ port[3] ][ :dir ] = "in"
|
230
|
+
elsif port[0] == "output"
|
231
|
+
result[ :port ][ port[3] ][ :dir ] = "out"
|
232
|
+
else
|
233
|
+
result[ :port ][ port[3] ][ :dir ] = "in"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
if port[ 2 ]
|
239
|
+
result[ :port ][ port[ 3 ] ][ :range ] = port[ 2 ]
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
return result
|
245
|
+
end
|
246
|
+
|
247
|
+
def extract_length( content )
|
248
|
+
|
249
|
+
numeric_regex = /^\s*([0-9+\-\s]+):([0-9+\-\s]+)/
|
250
|
+
parameter_regex = /^\s*(\D[\D\d]+)\s*-\s*1\s*:\s*0/
|
251
|
+
|
252
|
+
|
253
|
+
content[ :port ].values.each do |port|
|
254
|
+
if port[ :range ]
|
255
|
+
if m = numeric_regex.match( port[ :range ] )
|
256
|
+
tmp = " ( #{ m[1] } ) - ( #{ m[ 2 ] } ) + 1 "
|
257
|
+
begin
|
258
|
+
port[ :length ] = eval( tmp )
|
259
|
+
rescue Exception
|
260
|
+
port[:length] = 'UNKNOWN'
|
261
|
+
end
|
262
|
+
|
263
|
+
elsif m = parameter_regex.match( port[ :range ] )
|
264
|
+
port[:length] = m[1]
|
265
|
+
end
|
266
|
+
else
|
267
|
+
port[ :length ] = 1
|
268
|
+
end
|
269
|
+
end
|
270
|
+
return content
|
271
|
+
end
|
272
|
+
|
273
|
+
def parse_package( data )
|
274
|
+
result = {}
|
275
|
+
#data.split("\n").each do |line|
|
276
|
+
#end
|
277
|
+
return result
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
end
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
class VHDLParser < HDLParser
|
286
|
+
|
287
|
+
include ERR
|
288
|
+
|
289
|
+
# to organize it as singleton
|
290
|
+
#
|
291
|
+
include Singleton
|
292
|
+
|
293
|
+
def initialize
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
def parse_toplevel( data )
|
300
|
+
|
301
|
+
# remove all newlines
|
302
|
+
data = data.gsub( "\n", " " )
|
303
|
+
|
304
|
+
# empty result hash
|
305
|
+
result = {}
|
306
|
+
|
307
|
+
# thee expressions to parse the entity header
|
308
|
+
entity_regex = /
|
309
|
+
entity\s+(\S+)\s+is\s+ # entity <name> is
|
310
|
+
(generic\s*\(\s*(.*?)\s*\)\s*;)?\s* # generic ( <generic-infos> ) ; --> optional
|
311
|
+
(port\s*\(\s*(.*?)\s*\)\s*;)?\s* # port ( <port-info> ) ; --> optional
|
312
|
+
end\s*(entity)?\s*(\S*)\s*; # end <entity-name --> optional> ;
|
313
|
+
/x
|
314
|
+
|
315
|
+
generic_regex = /\s*(\S+)\s*:\s*(\w+)\s*(\((.*?)\))?\s*(:\s*=\s([\d\w]+))?/
|
316
|
+
port_regex = /\s*(\S+)\s*:\s*(in|out)?\s*(\w+)\s*(\((.*?)\))?\s*/
|
317
|
+
|
318
|
+
|
319
|
+
|
320
|
+
# match the whole entity header,
|
321
|
+
# -> extract name
|
322
|
+
# -> extract generics
|
323
|
+
# -> extract ports
|
324
|
+
if m = entity_regex.match( data )
|
325
|
+
|
326
|
+
|
327
|
+
result[ :name ] = m[1]
|
328
|
+
|
329
|
+
|
330
|
+
# if there are generics:
|
331
|
+
# -> process each
|
332
|
+
if m[3]
|
333
|
+
result[ :generic ] = {}
|
334
|
+
|
335
|
+
m[3].split(";").each do |x|
|
336
|
+
if match = generic_regex.match( x )
|
337
|
+
|
338
|
+
result[ :generic ][ match[1] ] = {
|
339
|
+
type: match[2],
|
340
|
+
name: match[1]
|
341
|
+
}
|
342
|
+
if( match[3])
|
343
|
+
result[ :generic ][ match[1] ][ :range ] = match[4]
|
344
|
+
end
|
345
|
+
if( match[5])
|
346
|
+
result[ :generic ][ match[1] ][ :default ] = match[6]
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# if there are ports
|
353
|
+
# -> process each
|
354
|
+
#
|
355
|
+
if m[5]
|
356
|
+
result[ :port ] = {}
|
357
|
+
m[5].split(";").each do |x|
|
358
|
+
if port_match = port_regex.match( x )
|
359
|
+
result[ :port ][ port_match[ 1 ] ] = {
|
360
|
+
name: port_match[1],
|
361
|
+
type: port_match[3]
|
362
|
+
}
|
363
|
+
if( port_match[2])
|
364
|
+
result[ :port ][ port_match[1] ][ :direction] = port_match[2]
|
365
|
+
else
|
366
|
+
result[ :port ][ port_match[1] ][ :direction] = "in"
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
if( port_match[ 4 ])
|
371
|
+
result[ :port ][ port_match[1] ][ :range] = port_match[5]
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
return result;
|
379
|
+
end
|
380
|
+
|
381
|
+
def extract_length( content )
|
382
|
+
|
383
|
+
content[ :port ].values.each do |v|
|
384
|
+
|
385
|
+
v[:length ] = 'UNKNOWN'
|
386
|
+
|
387
|
+
if v[:range]
|
388
|
+
|
389
|
+
numeric_regex = /^\s*([0-9+\-\s]+)(to|downto+)([0-9+\-\s]+)/i
|
390
|
+
parameter_regex = /^\s*(\D[\D\d]+)\s*-\s*1\s*(to|downto+)\s+0/i
|
391
|
+
|
392
|
+
if m = numeric_regex.match( v[:range] )
|
393
|
+
|
394
|
+
if( m[2].downcase == "downto")
|
395
|
+
tmp = "(" + m[1] + ") - ( " + m[3] + ") + 1"
|
396
|
+
else
|
397
|
+
tmp = "(" + m[3] + ") - ( " + m[1] + ") + 1"
|
398
|
+
end
|
399
|
+
begin
|
400
|
+
v[ :length ] = eval( tmp )
|
401
|
+
rescue Exception
|
402
|
+
v[:length] = 'UNKNOWN'
|
403
|
+
end
|
404
|
+
|
405
|
+
elsif m = parameter_regex.match( v[ :range ] )
|
406
|
+
v[:length] = m[1]
|
407
|
+
end
|
408
|
+
else
|
409
|
+
v[ :length ] = 1
|
410
|
+
end
|
411
|
+
end
|
412
|
+
return content
|
413
|
+
end
|
414
|
+
|
415
|
+
|
416
|
+
def parse_package( data )
|
417
|
+
result = {}
|
418
|
+
#const_regex = /^\s*constant\s*(\S+)\s*:\s*(\w+)\s*(\(.*?\))?\s*:\s*=\s*"?([\d\w]+)"?/i
|
419
|
+
#data.split("\n").each do |line|
|
420
|
+
#end
|
421
|
+
return result
|
422
|
+
end
|
423
|
+
|
424
|
+
end
|
425
|
+
|
426
|
+
|
427
|
+
|
428
|
+
end
|
429
|
+
|
430
|
+
|
431
|
+
|