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

Subversion Repositories soc_maker

[/] [soc_maker/] [trunk/] [lib/] [soc_maker/] [hdl_coder.rb] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 feddischso
###############################################################
2
#
3
#  File:      hdl_coder.rb
4
#
5
#  Author:    Christian Hättich
6
#
7
#  Project:   System-On-Chip Maker
8
#
9
#  Target:    Linux / Windows / Mac
10
#
11
#  Language:  ruby
12
#
13
#
14
###############################################################
15
#
16
#
17
#   Copyright (C) 2014  Christian Hättich  - feddischson [ at ] opencores.org
18
#
19
#   This program is free software: you can redistribute it and/or modify
20
#   it under the terms of the GNU General Public License as published by
21
#   the Free Software Foundation, either version 3 of the License, or
22
#   (at your option) any later version.
23
#
24
#   This program is distributed in the hope that it will be useful,
25
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
#   GNU General Public License for more details.
28
#
29
#   You should have received a copy of the GNU General Public License
30
#   along with this program.  If not, see .
31
#
32
#
33
###############################################################
34
#
35
#   Description:
36
#     This file contains two HDL-coders:
37
#      - VHDLCoder
38
#      - VerilogCoder (not implemented, yet)
39
#
40
#
41
#
42
###############################################################
43
 
44
module SOCMaker
45
class HDLCoder
46
 
47
  def initialize
48
    @decl_part  = "";   # declaration
49
    @asgn_part  = "";   # assignment
50
    @inst_part  = "";   # instantiation
51
 
52
 
53
 
54
  end
55
 
56
 
57
end
58
 
59
 
60
class VerilogCoder < HDLCoder
61
  #TODO
62
end
63
 
64
 
65
class VHDLCoder < HDLCoder
66
 
67
 
68
 
69
 
70
  #
71
  # Add a component declaration to the declaration-string @decl_part
72
  # This for example looks like
73
  # component <> is
74
  #  generic(
75
  #    g1 : ...
76
  #    g2 : ...
77
  #    ...
78
  #    );
79
  #  port(
80
  #    p1 : ...
81
  #    p2 : ...
82
  #    p3 : ...
83
  #    ...
84
  #    )
85
  #  end component <>;
86
  #
87
  # In addition, we add some VHDL comments (author, mail, license)
88
  #
89
  def add_core_declaration( core_name, core_spec )
90 5 feddischso
 
91 3 feddischso
    @decl_part << "--\n"
92
    @decl_part << "-- core author: #{core_spec.author} - #{core_spec.authormail}\n"
93
    @decl_part << "-- license: #{core_spec.license}\n"
94
    @decl_part << "--\n"
95
    @decl_part << "component #{core_spec.toplevel} is\n"
96
    generic_str = entity_generic_str( core_spec );
97
    @decl_part << "generic ( #{ generic_str  });\n" if generic_str.size > 0
98
    @decl_part << "port( \n" << entity_port_str( core_spec ) <<" );\n"
99
    @decl_part << "end component #{core_spec.toplevel};\n"
100
    entity_generic_str( core_spec )
101
  end
102
 
103
 
104
 
105
  def entity_generic_str( core )
106
 
107
    generic_str = ""
108
    core.generics do |gen_name, gen_type, gen_val, is_last|
109
      generic_str     << gen_name << " : " << gen_type << " := " << gen_val.to_s
110
      generic_str     << ";" unless is_last
111
      generic_str     << "\n"
112
    end
113
    return generic_str
114
  end
115
 
116
 
117
  #
118
  # Create a string, which lists all signals of 'core'
119
  # We iterate over all interface:
120
  # For each interface, we iterate over all ports:
121
  # For each port, we lookup the definition in the 'soc_lib' and
122
  # add the VHDL code according to the definition as string to
123
  # port_string
124
  #
125
  def entity_port_str( core )
126
    port_string = ""
127
 
128
    core.ports do |port_name, port_dir, port_len, is_last |
129
 
130
      # The string we are add in every iteration looks for example like
131
      #    myportname1 :  out std_logic_vector( 6-1 downto 0 )
132
      #    or
133
      #    myportname2 :  in  std_logic
134
      #
135
      port_string << port_name.to_s << " : "
136
 
137
      # port direction
138
      if    port_dir == 2
139
        port_string << " inout "
140
      elsif port_dir == 1
141
        port_string << " in "
142
      else
143
        port_string << " out "
144
      end
145
 
146
      # port type / length
147
      if(   port_len.is_a?( String ) ||
148
          ( port_len.is_a?( Fixnum ) && port_len > 1 )
149
        )
150
        port_string << " std_logic_vector( #{port_len}-1 downto 0 ) "
151
      elsif ( port_len.is_a?( Fixnum ) && port_len == 1 )
152
        port_string << " std_logic "
153
      else
154
        puts "FAILED " + port_len
155
      end
156
 
157
      # end of the line
158
      port_string << ";" unless is_last
159
      port_string << "\n"
160
    end
161
    return port_string
162
  end
163
 
164
 
165
  def add_core_inst( inst_name, inst )
166
 
167
    @inst_part << inst_name << " : " << inst.defn.toplevel << "\n"
168
    generic_str = ""
169
    inst.generics do |generic, type, value, is_last|
170
      generic_str << "#{generic} => #{value}"
171
      generic_str << "," unless is_last
172
      generic_str << "\n"
173
    end
174
    @inst_part << "generic map( \n#{generic_str} )\n" if generic_str.size > 0
175
    port_str = ""
176
    inst.ports do |port_name, length, dir, is_last|
177
      port_str << "#{port_name} => #{inst_name}_#{port_name}"
178
      port_str << "," unless is_last
179
      port_str << "\n"
180
      if length > 1
181
        @decl_part << "signal #{inst_name}_#{port_name} : std_logic_vector( #{length}-1 downto 0 );\n"
182
      else
183
        @decl_part << "signal #{inst_name}_#{port_name} : std_logic;\n"
184
      end
185
    end
186
    @inst_part << "port map( \n#{port_str} );\n\n\n" if port_str.size > 0
187
 
188
  end
189
 
190
 
191
 
192 5 feddischso
 
193
 
194
 
195 3 feddischso
 
196
  def ifc_declaration( ifc_spec, ifc_name, length )
197
 
198
    ifc_spec.ports.each do |port_name, port|
199
 
200
      @decl_part << "signal #{ifc_name}_#{port_name.to_s} : "
201
      if length[ port_name ] > 1
202
        @decl_part << " std_logic_vector( #{length[ port_name ]}-1 downto 0 ) "
203
      else
204
        @decl_part << " std_logic "
205
      end
206
      # end of the line
207
      @decl_part << ";\n"
208
    end
209
 
210
  end
211
 
212
  def ifc_assignment( ifc_spec, ifc_name, length, src_inst, dst_inst, src_ifc, dst_ifc )
213
 
214
    ifc_spec.ports.each do |port_name, port_dir|
215
      if port_dir == 0
216
        src_inst_sel = src_inst
217
        dst_inst_sel = dst_inst
218
        src_ifc_sel  = src_ifc
219
        dst_ifc_sel  = dst_ifc
220
      else
221
        src_inst_sel = dst_inst
222
        dst_inst_sel = src_inst
223
        src_ifc_sel  = dst_ifc
224
        dst_ifc_sel  = src_ifc
225
      end
226
 
227
 
228 5 feddischso
      # length == 0 means, that no
229
      # signal is assigned to this connection
230
      if length[ port_name ] > 0
231 3 feddischso
 
232 5 feddischso
        port_tmp_name = "#{ifc_name}_#{port_name.to_s}"
233 3 feddischso
 
234 5 feddischso
 
235
        # combine all sources
236
        tmp = "#{port_tmp_name} <= "
237
        # loop over instances
238
        src_inst_sel.each_with_index do |(inst_name, inst), i|
239
          ( tmp_name, port) = inst.get_port( src_ifc_sel[ inst_name ], port_name )
240
          if port != nil
241
            tmp << "\"" + "0" * ( length[ port_name ] - port[ :len ] ) + "\" & "  if port[ :len ] < length[ port_name ]
242
            tmp << "#{inst_name}_#{tmp_name}"
243
            tmp << " and \n" unless i == src_inst_sel.size-1
244
          end
245
 
246
        end
247 3 feddischso
        tmp << ";\n"
248 5 feddischso
        @asgn_part << tmp
249
 
250
        # assign to destination
251
        tmp = ""
252
        dst_inst_sel.each_with_index do |(inst_name, inst), i|
253
          ( tmp_name, port) = inst.get_port( dst_ifc_sel[ inst_name ], port_name )
254
          if port != nil
255
            tmp << "#{inst_name}_#{tmp_name} <= #{port_tmp_name}"
256
            tmp << "( #{port[ :len ]}-1 downto 0 )" if port[ :len ] > 1
257
            tmp << ";\n"
258
          end
259
        end
260
        @asgn_part << tmp
261 3 feddischso
      end
262
 
263
    end
264
 
265
 
266
 
267
  end
268
 
269
 
270
 
271
  # TODO: add sig list as argument (or interface list) for entity description
272
  def get_entity( soc, entity_name )
273 5 feddischso
    add_toplevel_sig( soc, entity_name )
274
    entity_str = SOCMaker::conf[ :LIC ].split(/\n/).map{ |s| "-- "+s }.join("\n") + "\n"
275 3 feddischso
    entity_str << "-- Auto-Generated by #{SOCMaker::conf[ :app_name ]} \n"
276
    entity_str << "-- Date: #{Time.now}\n"
277
    entity_str << SOCMaker::conf[ :vhdl_include ] + "\n"
278
    entity_str << "entity #{entity_name} is \n"
279
    tmp = entity_port_str( soc )
280
    entity_str << "port( \n" << tmp << " );\n" if tmp.size > 0
281
    entity_str << "end entity #{entity_name};\n\n\n"
282
    entity_str << "ARCHITECTURE IMPL of #{entity_name} is \n"
283
    entity_str << @decl_part
284
    entity_str << "\n\n"
285
    entity_str << "begin"
286
    entity_str << "\n\n"
287
    entity_str << "--"
288
    entity_str << "-- assignments "
289
    entity_str << "--"
290
    entity_str << "\n\n"
291
    entity_str << @asgn_part
292
    entity_str << "\n\n"
293
    entity_str << "--"
294
    entity_str << "-- instances "
295
    entity_str << "--"
296
    entity_str << "\n\n"
297
    entity_str << @inst_part
298
    entity_str << "end ARCHITECTURE IMPL;"
299
    return entity_str
300
  end
301
 
302 5 feddischso
  def add_toplevel_sig( soc, entity_name )
303
    soc.ports do |port_name, length, dir, is_last|
304
      @asgn_part << "#{port_name} <= #{entity_name}_#{port_name}"
305
      @asgn_part << "," unless is_last
306
      @asgn_part << "\n"
307
      if length > 1
308
        @decl_part << "signal #{entity_name}_#{port_name} : std_logic_vector( #{length}-1 downto 0 );\n"
309
      else
310
        @decl_part << "signal #{entity_name}_#{port_name} : std_logic;\n"
311
      end
312
    end
313
  end
314 3 feddischso
 
315
 
316
 
317
  def asgn_str( ifc_spec, con,  ifc_name, core1, core1_name, core2, core2_name )
318
    port_string = ""
319
 
320
    { core1 => [ con[ :ifc1 ], :src1 ],
321
      core2 => [ con[ :ifc2 ], :src2 ] }.each do| core, tmp |
322
 
323
      core.ports( tmp[0] ) do | port_spec_name, port_name, port_dir |
324
 
325
        if port_dir  == 0
326
          port_string << "#{ifc_name}_#{port_spec_name}"
327
          port_string << " <= "
328
          port_string << "#{con[ tmp[1] ]}_#{port_name}"
329
          port_string << ";\n"
330
        else
331
          port_string << "#{con[ tmp[1] ]}_#{port_name}"
332
          port_string << " <= "
333
          port_string << "#{ifc_name}_#{port_spec_name }"
334
          port_string << ";\n"
335
        end
336
      end
337
 
338
    end
339
 
340
    return port_string
341
  end
342
 
343
 
344
 
345
 
346
 
347
end
348
end
349
 
350
# vim: noai:ts=2:sw=2

powered by: WebSVN 2.1.0

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