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 10

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 7 feddischso
  #
63
  #
64
 
65
  def filename( name )
66
    return name + ".v"
67
  end
68
 
69 3 feddischso
end
70
 
71
 
72
class VHDLCoder < HDLCoder
73
 
74
 
75
 
76
 
77
  #
78
  # Add a component declaration to the declaration-string @decl_part
79
  # This for example looks like
80
  # component <> is
81
  #  generic(
82
  #    g1 : ...
83
  #    g2 : ...
84
  #    ...
85
  #    );
86
  #  port(
87
  #    p1 : ...
88
  #    p2 : ...
89
  #    p3 : ...
90
  #    ...
91
  #    )
92
  #  end component <>;
93
  #
94
  # In addition, we add some VHDL comments (author, mail, license)
95
  #
96 7 feddischso
  def add_core_component( core_name, core_spec )
97 5 feddischso
 
98 3 feddischso
    @decl_part << "--\n"
99
    @decl_part << "-- core author: #{core_spec.author} - #{core_spec.authormail}\n"
100
    @decl_part << "-- license: #{core_spec.license}\n"
101
    @decl_part << "--\n"
102
    @decl_part << "component #{core_spec.toplevel} is\n"
103
    generic_str = entity_generic_str( core_spec );
104
    @decl_part << "generic ( #{ generic_str  });\n" if generic_str.size > 0
105
    @decl_part << "port( \n" << entity_port_str( core_spec ) <<" );\n"
106
    @decl_part << "end component #{core_spec.toplevel};\n"
107 7 feddischso
    #entity_generic_str( core_spec )
108 3 feddischso
  end
109
 
110 7 feddischso
  def filename( name )
111
    return name + ".vhd"
112
  end
113 3 feddischso
 
114
 
115
  def entity_generic_str( core )
116
 
117
    generic_str = ""
118
    core.generics do |gen_name, gen_type, gen_val, is_last|
119
      generic_str     << gen_name << " : " << gen_type << " := " << gen_val.to_s
120
      generic_str     << ";" unless is_last
121
      generic_str     << "\n"
122
    end
123
    return generic_str
124
  end
125
 
126
 
127
  #
128
  # Create a string, which lists all signals of 'core'
129
  # We iterate over all interface:
130
  # For each interface, we iterate over all ports:
131
  # For each port, we lookup the definition in the 'soc_lib' and
132
  # add the VHDL code according to the definition as string to
133
  # port_string
134
  #
135
  def entity_port_str( core )
136
    port_string = ""
137
 
138 8 feddischso
    core.ports do |port_name, port_dir, port_len, port_default, is_last |
139 3 feddischso
 
140
      # The string we are add in every iteration looks for example like
141
      #    myportname1 :  out std_logic_vector( 6-1 downto 0 )
142
      #    or
143
      #    myportname2 :  in  std_logic
144
      #
145
      port_string << port_name.to_s << " : "
146
 
147 7 feddischso
 
148
 
149 3 feddischso
      # port direction
150
      if    port_dir == 2
151
        port_string << " inout "
152
      elsif port_dir == 1
153
        port_string << " in "
154
      else
155
        port_string << " out "
156
      end
157
 
158
      # port type / length
159
      if(   port_len.is_a?( String ) ||
160
          ( port_len.is_a?( Fixnum ) && port_len > 1 )
161
        )
162
        port_string << " std_logic_vector( #{port_len}-1 downto 0 ) "
163
      elsif ( port_len.is_a?( Fixnum ) && port_len == 1 )
164
        port_string << " std_logic "
165
      else
166 7 feddischso
        puts "FAILED " + port_len.to_s #TODO
167 3 feddischso
      end
168
 
169
      # end of the line
170
      port_string << ";" unless is_last
171
      port_string << "\n"
172
    end
173
    return port_string
174
  end
175
 
176
 
177 7 feddischso
  def add_core_instance( inst_name, inst )
178 3 feddischso
 
179
    @inst_part << inst_name << " : " << inst.defn.toplevel << "\n"
180
    generic_str = ""
181
    inst.generics do |generic, type, value, is_last|
182
      generic_str << "#{generic} => #{value}"
183
      generic_str << "," unless is_last
184
      generic_str << "\n"
185
    end
186
    @inst_part << "generic map( \n#{generic_str} )\n" if generic_str.size > 0
187
    port_str = ""
188 8 feddischso
    inst.ports do |port_name, dir, length, default, is_last|
189 3 feddischso
      port_str << "#{port_name} => #{inst_name}_#{port_name}"
190
      port_str << "," unless is_last
191
      port_str << "\n"
192
      if length > 1
193
        @decl_part << "signal #{inst_name}_#{port_name} : std_logic_vector( #{length}-1 downto 0 );\n"
194
      else
195
        @decl_part << "signal #{inst_name}_#{port_name} : std_logic;\n"
196
      end
197
    end
198
    @inst_part << "port map( \n#{port_str} );\n\n\n" if port_str.size > 0
199
 
200
  end
201
 
202 10 feddischso
  def add_ifc_default_assignment( inst, inst_name, ifc_name )
203 3 feddischso
 
204 8 feddischso
 
205
    tmp = ""
206 10 feddischso
    inst.ports( ifc_name.to_s ) do |port_name, dir, length, default_val, is_last|
207 8 feddischso
      if dir == 1 # assign default value only if it is an input
208
        if length > 1
209 10 feddischso
          tmp << "#{inst_name}_#{port_name} <= ( others => '#{default_val}' );\n"
210 8 feddischso
        else
211 10 feddischso
          tmp << "#{inst_name}_#{port_name} <= '#{default_val}';\n"
212 8 feddischso
        end
213
      end
214
    end
215
   @asgn_part << tmp
216
 
217
  end
218 3 feddischso
 
219 7 feddischso
  def add_ifc_connection( ifc_spec, ifc_name, length, src_inst, dst_inst, src_ifc, dst_ifc )
220 3 feddischso
 
221 7 feddischso
    ###
222
    #
223
    # declaration
224
    #
225
    #
226 3 feddischso
    ifc_spec.ports.each do |port_name, port|
227
      @decl_part << "signal #{ifc_name}_#{port_name.to_s} : "
228
      if length[ port_name ] > 1
229
        @decl_part << " std_logic_vector( #{length[ port_name ]}-1 downto 0 ) "
230
      else
231
        @decl_part << " std_logic "
232
      end
233
      # end of the line
234
      @decl_part << ";\n"
235
    end
236
 
237
 
238 7 feddischso
    ###
239
    #
240
    # assignment
241
    #
242
    #
243 8 feddischso
    ifc_spec.ports.each do |port_name, port_setup|
244
 
245
 
246
      if port_setup[ :dir ] == 0
247 3 feddischso
        src_inst_sel = src_inst
248
        dst_inst_sel = dst_inst
249
        src_ifc_sel  = src_ifc
250
        dst_ifc_sel  = dst_ifc
251
      else
252
        src_inst_sel = dst_inst
253
        dst_inst_sel = src_inst
254
        src_ifc_sel  = dst_ifc
255
        dst_ifc_sel  = src_ifc
256
      end
257
 
258
 
259 5 feddischso
      # length == 0 means, that no
260
      # signal is assigned to this connection
261
      if length[ port_name ] > 0
262 3 feddischso
 
263 5 feddischso
        port_tmp_name = "#{ifc_name}_#{port_name.to_s}"
264 3 feddischso
 
265 5 feddischso
 
266
        # combine all sources
267
        tmp = "#{port_tmp_name} <= "
268
        # loop over instances
269
        src_inst_sel.each_with_index do |(inst_name, inst), i|
270 9 feddischso
          ( tmp_name, port) = inst.port( src_ifc_sel[ inst_name ], port_name )
271 5 feddischso
          if port != nil
272 8 feddischso
            if port[ :len ] < length[ port_name ]
273
              tmp << "\"" + "0" * ( length[ port_name ] - port[ :len ] ) + "\" & "
274
            end
275 5 feddischso
            tmp << "#{inst_name}_#{tmp_name}"
276
            tmp << " and \n" unless i == src_inst_sel.size-1
277 8 feddischso
          else
278
            if length[ port_name ] > 1
279
              tmp << "( others => '0' )"
280
            else
281
              tmp << "'0'"
282
            end
283 5 feddischso
          end
284
        end
285 3 feddischso
        tmp << ";\n"
286 8 feddischso
        @asgn_part << tmp
287 5 feddischso
 
288 7 feddischso
        tmp = ""
289
        assigned = false
290 5 feddischso
        # assign to destination
291
        dst_inst_sel.each_with_index do |(inst_name, inst), i|
292 7 feddischso
          if not inst == nil  #TODO
293 9 feddischso
            ( tmp_name, port) = inst.port( dst_ifc_sel[ inst_name ], port_name )
294 7 feddischso
            if port != nil
295
              tmp << "#{inst_name}_#{tmp_name} <= #{port_tmp_name}"
296
              tmp << "( #{port[ :len ]}-1 downto 0 )" if port[ :len ] > 1
297
              tmp << ";\n"
298
              assigned = true
299
            end
300 5 feddischso
          end
301
        end
302 7 feddischso
        @asgn_part << tmp if assigned
303 8 feddischso
        puts "NOT ASSIGNED DST" if not assigned
304
      else
305
      #  puts "ifc #{ifc_name} port #{port_name.to_s} is not assigned"
306
      #  p src_ifc
307
      #  p dst_ifc
308
      #  tmp = ""
309
      #  dst_inst_sel.each_with_index do |(inst_name, inst), i|
310
      #    p inst_name
311
      #    p port_name
312 9 feddischso
      #    ( tmp_name, port) = inst.port( dst_ifc_sel[ inst_name ], port_name )
313 8 feddischso
      #    tmp << "#{inst_name}_#{tmp_name} <= ( others => 'X' );\n"
314
      #  end
315
      #  @asgn_part << tmp;
316 3 feddischso
      end
317
 
318
    end
319
  end
320
 
321
 
322
 
323 7 feddischso
  def get_hdl_code( soc, entity_name )
324 5 feddischso
    add_toplevel_sig( soc, entity_name )
325
    entity_str = SOCMaker::conf[ :LIC ].split(/\n/).map{ |s| "-- "+s }.join("\n") + "\n"
326 3 feddischso
    entity_str << "-- Auto-Generated by #{SOCMaker::conf[ :app_name ]} \n"
327
    entity_str << "-- Date: #{Time.now}\n"
328
    entity_str << SOCMaker::conf[ :vhdl_include ] + "\n"
329
    entity_str << "entity #{entity_name} is \n"
330
    tmp = entity_port_str( soc )
331
    entity_str << "port( \n" << tmp << " );\n" if tmp.size > 0
332
    entity_str << "end entity #{entity_name};\n\n\n"
333
    entity_str << "ARCHITECTURE IMPL of #{entity_name} is \n"
334
    entity_str << @decl_part
335
    entity_str << "\n\n"
336
    entity_str << "begin"
337
    entity_str << "\n\n"
338
    entity_str << "--"
339
    entity_str << "-- assignments "
340
    entity_str << "--"
341
    entity_str << "\n\n"
342
    entity_str << @asgn_part
343
    entity_str << "\n\n"
344
    entity_str << "--"
345
    entity_str << "-- instances "
346
    entity_str << "--"
347
    entity_str << "\n\n"
348
    entity_str << @inst_part
349
    entity_str << "end ARCHITECTURE IMPL;"
350
    return entity_str
351
  end
352
 
353 5 feddischso
  def add_toplevel_sig( soc, entity_name )
354 7 feddischso
    soc.ports do |port_name, dir, length, is_last|
355
      if dir == 0
356
        @asgn_part << "#{port_name} <= #{entity_name}_#{port_name}"
357
      else
358
        @asgn_part << "#{entity_name}_#{port_name} <= #{port_name} "
359
      end
360
      @asgn_part << ";\n"
361 5 feddischso
      if length > 1
362
        @decl_part << "signal #{entity_name}_#{port_name} : std_logic_vector( #{length}-1 downto 0 );\n"
363
      else
364
        @decl_part << "signal #{entity_name}_#{port_name} : std_logic;\n"
365
      end
366
    end
367
  end
368 3 feddischso
 
369
 
370
 
371
  def asgn_str( ifc_spec, con,  ifc_name, core1, core1_name, core2, core2_name )
372
    port_string = ""
373
 
374
    { core1 => [ con[ :ifc1 ], :src1 ],
375
      core2 => [ con[ :ifc2 ], :src2 ] }.each do| core, tmp |
376
 
377
      core.ports( tmp[0] ) do | port_spec_name, port_name, port_dir |
378
 
379
        if port_dir  == 0
380
          port_string << "#{ifc_name}_#{port_spec_name}"
381
          port_string << " <= "
382
          port_string << "#{con[ tmp[1] ]}_#{port_name}"
383
          port_string << ";\n"
384
        else
385
          port_string << "#{con[ tmp[1] ]}_#{port_name}"
386
          port_string << " <= "
387
          port_string << "#{ifc_name}_#{port_spec_name }"
388
          port_string << ";\n"
389
        end
390
      end
391
 
392
    end
393
 
394
    return port_string
395
  end
396
 
397
 
398
 
399
 
400
 
401
end
402
end
403
 
404
# 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.