HDLRuby 3.3.4 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1153 @@
1
+ require "HDLRuby/verilog_parser"
2
+
3
+ # Generate HDLRuby code from a Verilog HDL AST (produced from
4
+ # verilog_parser.rb)
5
+
6
+ module VerilogTools
7
+
8
+ # The possible levels in HDLRuby generation.
9
+ HDLRubyLevels = [ :top, :system, :hdef, :<=, :seq, :par, :timed, :expr ]
10
+ NoEventLevels = [ :hdef, :<=, :seq, :par, :timed ]
11
+ NoTimeLevels = [ :hdef, :<=, :seq, :par ]
12
+
13
+ # HDLRuby generation state.
14
+ class HDLRubyState
15
+ # String to add at new line for indent.
16
+ attr_reader :indent
17
+
18
+ # The current level in HDLRuby generation.
19
+ attr_reader :level
20
+
21
+ # The names of the ports of the current module.
22
+ attr_reader :port_names
23
+
24
+ # The default state.
25
+ DEFAULT = HDLRubyState.new
26
+
27
+ # Create a new state.
28
+ def initialize
29
+ @indent = "" # String to add at new line for indent.
30
+ @level = :top # Current level in HDLRuby generation.
31
+ @port_names = [] # The names of the ports of the current module.
32
+ end
33
+
34
+ # Set the indent string.
35
+ def indent=(str)
36
+ @indent = str.to_s
37
+ end
38
+
39
+ # Set the level in HDLRuby generation
40
+ def level=(level)
41
+ unless HDLRubyLevels.include?(level)
42
+ raise "Internal error, unknown generation level #{level}"
43
+ end
44
+ @level = level
45
+ end
46
+
47
+ # Sets the port names.
48
+ def port_names=(port_names)
49
+ @port_names = port_names.to_a
50
+ end
51
+ end
52
+
53
+
54
+ # Tool for gathering the names of ports.
55
+ def self.get_port_names(ports)
56
+ return [] unless ports
57
+ return [] if ports.is_a?(AST) and ports.type == :property
58
+ if ports.respond_to?(:map) then
59
+ return ports.map {|p| VerilogTools.get_port_names(p) }.flatten
60
+ else
61
+ if ports.is_a?(String) then
62
+ return [ ports ]
63
+ else
64
+ return []
65
+ end
66
+ end
67
+ end
68
+
69
+
70
+ # Tool for checking if a statement is to be seq or par in HDLRuby
71
+ def self.get_seq_par(statement)
72
+ case statement.type
73
+ when :blocking_asignment
74
+ return :seq
75
+ when :non_blocking_assignment
76
+ return :par
77
+ when :statement
78
+ statement.each do |child|
79
+ next unless child.is_a?(AST)
80
+ seq_par = VerilogTools.get_seq_par(child)
81
+ return seq_par if seq_par
82
+ end
83
+ return nil
84
+ else
85
+ return nil
86
+ end
87
+ end
88
+
89
+ # Tool for getting the name of a statement if any.
90
+ def self.get_name(statement)
91
+ case statement.type
92
+ when :seq_block, :par_block
93
+ name = statement[0]
94
+ name_txt = name ? name.to_HDLRuby(HDLRubyState::DEFAULT) : ""
95
+ return name_txt
96
+ when :statement
97
+ statement.each do |child|
98
+ next unless child.is_a?(AST)
99
+ seq_par = VerilogTools.get_name(child)
100
+ return seq_par if seq_par
101
+ end
102
+ else
103
+ return ""
104
+ end
105
+ end
106
+
107
+
108
+ # Converts a Verilog HDL name to a HDLRuby one.
109
+ def self.name_to_HDLRuby(name)
110
+ if name[0] =~ /[_$A-Z]/ then
111
+ # HDLRuby names cannot start with a $ or a capital letter.
112
+ # To fix that add an "_", but then to avoid confusion, also
113
+ # convert starting "_" to "__" if any.
114
+ return "_" + name
115
+ else
116
+ return name
117
+ end
118
+ end
119
+
120
+ # Converts a Verilog HDL system task to a HDLRuby one.
121
+ def self.system_to_HDLRuby(name,args)
122
+ case name
123
+ when "$signed"
124
+ return "(#{args}).as(signed[(#{args}).type.width])"
125
+ when "$display"
126
+ return "hprint(#{args})"
127
+ when "$finish"
128
+ return "terminate"
129
+ else
130
+ raise "Internal error: unsupported system task #{name} yet."
131
+ end
132
+ end
133
+
134
+
135
+ # Converts a Verilog HDL operator to a HDLRuby one.
136
+ def self.operator_to_HDLRuby(op)
137
+ case op
138
+ when "!"
139
+ return "~"
140
+ when "&&"
141
+ return "&"
142
+ when "||"
143
+ return "|"
144
+ when "~&"
145
+ return ".send(:~) | ~"
146
+ when "~|"
147
+ return ".send(:~) & ~"
148
+ when "~^"
149
+ return "^~"
150
+ when "^|"
151
+ return "^"
152
+ else
153
+ return op
154
+ end
155
+ end
156
+
157
+
158
+ # The class describing generation errors.
159
+ class GenerateError < StandardError
160
+
161
+ # Create a new parse error with message +msg+, faulty line number
162
+ # +lpos+, and possibly file name +filename+.
163
+ def initialize(msg,lpos,filename)
164
+ @msg = msg.to_s
165
+ @lpos = lpos.to_i
166
+ @filename = filename.to_s if filename
167
+ super(self.make_message)
168
+ end
169
+
170
+ # Generate the error message.
171
+ # NOTE: if you want to translate the error message, please
172
+ # redefine the function.
173
+ def make_message
174
+ if @filename then
175
+ head = "Generation error for file '#{@filename}' "
176
+ else
177
+ head = "Generation error "
178
+ end
179
+ return head + "line #{@lpos}: " + @msg + "."
180
+ end
181
+ end
182
+
183
+
184
+ class AST
185
+
186
+ # Generate HDLRuby text from the current AST node.
187
+ # +state+ is the HDLRuby generation state.
188
+ def to_HDLRuby(state = HDLRubyState.new)
189
+ # Execute the generation procedure corresponding to the type.
190
+ return TO_HDLRuby[self.type].(self,state)
191
+ end
192
+
193
+
194
+ # Generate a generation error with message indicated by +msg+.
195
+ def generate_error(msg)
196
+ property = self[-1]
197
+ lpos = property[:lpos]
198
+ filename = property[:filename]
199
+ # Raise an exception containing an error message made of msg,
200
+ # the adjusted line number, its number, and the column where error
201
+ # happended.
202
+ raise GenerateError.new(msg,lpos,filename)
203
+ end
204
+
205
+
206
+ # The types of ports declaration in module ports and items.
207
+ PORT_DECLS = [ :input_declaration, :output_declaration,
208
+ :inout_declaration ]
209
+
210
+ # The generation procedures.
211
+ TO_HDLRuby = Hash.new( lambda do |ast,state|
212
+ # By default, recurse on the children.
213
+ return ast.map do |child|
214
+ if child.is_a?(Array) then
215
+ child.map do |sub|
216
+ sub.is_a?(AST) ? sub.to_HDLRuby(state) : sub.to_s
217
+ end.join
218
+ elsif child.is_a?(AST) then
219
+ child.to_HDLRuby(state)
220
+ else
221
+ child
222
+ end
223
+ end.join
224
+ end)
225
+
226
+
227
+ # Properties should not produce anything.
228
+ TO_HDLRuby[:property] = lambda { |ast, state| return "" }
229
+
230
+
231
+ TO_HDLRuby[:module] = lambda do |ast,state|
232
+ # Save and update the state.
233
+ indent = state.indent
234
+ level = state.level
235
+ state.indent += " "
236
+ state.level = :system
237
+ # Generate the name.
238
+ name = ast[0].to_HDLRuby
239
+ # Generate the generic parameters if any.
240
+ parameters = ast[1]
241
+ parameters = parameters ? parameters.to_HDLRuby(state) : ""
242
+ # Generate the ports.
243
+ # From the port declaration.
244
+ ports = ast[2]
245
+ ports = ports ? ports[0].map {|p| p.to_HDLRuby(state) } : []
246
+ # Remove the empty ports.
247
+ ports.select! {|p| !p.empty? }
248
+ # From the items, for that separate port declarations from others.
249
+ pitems, items = ast[3].partition {|i| PORT_DECLS.include?(i.type) }
250
+ ports += pitems.map {|p| p.to_HDLRuby(state) }
251
+ # Gather the port names to skip the redeclarations.
252
+ state.port_names = VerilogTools.get_port_names(pitems)
253
+ # Generate the items.
254
+ items = items.map do |i|
255
+ res = i.to_HDLRuby(state)
256
+ res
257
+ end
258
+ # Generate the module text.
259
+ res = indent + "system :" + name + " do " + parameters + "\n" +
260
+ ports.join + items.join + indent + "end\n"
261
+ # Restores the state.
262
+ state.indent = indent
263
+ state.level = level
264
+ state.port_names = []
265
+ # Returns the resulting string.
266
+ return res
267
+ end
268
+
269
+
270
+ TO_HDLRuby[:pre_parameter_declaration] = lambda do |ast,state|
271
+ return "|" + ast[0].to_HDLRuby(state) + "|"
272
+ end
273
+
274
+
275
+ TO_HDLRuby[:list_of_param_assignments] = lambda do |ast,state|
276
+ return ast[0].map {|p| p.to_HDLRuby(state) }.join(", ")
277
+ end
278
+
279
+
280
+ TO_HDLRuby[:param_assignment] = lambda do |ast,state|
281
+ return ast[0].to_HDLRuby(state) + "=" + ast[1].to_HDLRuby(state)
282
+ end
283
+
284
+
285
+ TO_HDLRuby[:list_of_ports] = lambda do |ast,state|
286
+ return ast.map { |p| p.to_HDLRuby(state) }.join("\n")
287
+ end
288
+
289
+
290
+ TO_HDLRuby[:port] = lambda do |ast,state|
291
+ p = ast[0]
292
+ return "" unless p
293
+ if p.type == :port_expression then
294
+ return p.to_HDLRuby(state)
295
+ else
296
+ v = ast[1]
297
+ return p.to_HDLRuby(state) + ": " + v ? v.to_HDLRuby(state) : ""
298
+ end
299
+ end
300
+
301
+
302
+ TO_HDLRuby[:port_expression] = lambda do |ast,state|
303
+ port = ast[0]
304
+ if port.is_a?(Array) then
305
+ return port.map {|p| p.to_HDLRuby(state) }.join("\n")
306
+ else
307
+ return port.to_HDLRuby(state)
308
+ end
309
+ end
310
+
311
+
312
+ TO_HDLRuby[:input_port_declaration] = lambda do |ast,state|
313
+ # Ignore the INPUTTYPE not used in HDLRuby
314
+ # Get the sign if any.
315
+ sign = ast[1]
316
+ sign = "" unless sign
317
+ # Get the range.
318
+ range = ast[2]
319
+ range = range ? range.to_HDLRuby(state) + "." : ""
320
+ # Get the name.
321
+ name = ast[3].to_HDLRuby(state)
322
+ # Genereate the resulting declaration.
323
+ return state.indent + sign + range +"input :" + name + "\n"
324
+ end
325
+
326
+
327
+ TO_HDLRuby[:output_port_declaration] = lambda do |ast,state|
328
+ # Ignore the OUTPUTTYPE not used in HDLRuby
329
+ # Get the sign if any.
330
+ sign = ast[1]
331
+ sign = "" unless sign
332
+ # Get the range.
333
+ range = ast[2]
334
+ range = range ? range.to_HDLRuby(state) + "." : ""
335
+ # Get the name.
336
+ name = ast[3].to_HDLRuby(state)
337
+ # Genereate the resulting declaration.
338
+ return state.indent + sign + range +"output :" + name + "\n"
339
+ end
340
+
341
+
342
+ TO_HDLRuby[:inout_port_declaration] = lambda do |ast,state|
343
+ # Ignore the INOUTTYPE not used in HDLRuby
344
+ # Get the sign if any.
345
+ sign = ast[1]
346
+ sign = "" unless sign
347
+ # Get the range.
348
+ range = ast[2]
349
+ range = range ? range.to_HDLRuby(state) + "." : ""
350
+ # Get the name.
351
+ name = ast[3].to_HDLRuby(state)
352
+ # Genereate the resulting declaration.
353
+ return state.indent + sign + range +"inout :" + name + "\n"
354
+ end
355
+
356
+
357
+ TO_HDLRuby[:port_reference] = lambda do |ast,state|
358
+ # Port reference are actually ignored since they are redeclared
359
+ # afterward (or are they?).
360
+ return ""
361
+ end
362
+
363
+
364
+ TO_HDLRuby[:task] = lambda do |ast,state|
365
+ # Save and update the state.
366
+ indent = state.indent
367
+ level = state.level
368
+ state.indent += " "
369
+ state.level = :hdef
370
+ # Generate the task text (function defintion in HDLRuby).
371
+ res = indent + "hdef :" + ast[0].to_HDLRuby +
372
+ " do |" + ast[1].to_HDLRuby + "|\n" +
373
+ state.indent + ast[2].to_HDLRuby(state.indent) + indent + "end\n"
374
+ # Restores the state.
375
+ state.indent = indent
376
+ state.level = level
377
+ # Returns the resulting string.
378
+ return res
379
+ end
380
+
381
+
382
+ TO_HDLRuby[:function] = lambda do |ast,state|
383
+ # Save and update the state.
384
+ indent = state.indent
385
+ level = state.level
386
+ state.indent += " "
387
+ state.level = :hdef
388
+ # Generate the function text.
389
+ # The return type is ignored for HDLRuby.
390
+ res = indent + "hdef :" + ast[1].to_HDLRuby(state) +
391
+ " do |" + ast[2].map{|p| p.to_HDLRuby(state)}.join(",") + "|\n" +
392
+ state.indent + ast[3].to_HDLRuby(state) + indent + "end\n"
393
+ # Restores the state.
394
+ state.indent = indent
395
+ state.level = level
396
+ # Returns the resulting string.
397
+ return res
398
+ end
399
+
400
+
401
+ TO_HDLRuby[:list_of_param_assignments] = lambda do |ast,state|
402
+ return ast[0].map {|p| p.to_HDLRuby(state) }.join
403
+ end
404
+
405
+
406
+ TO_HDLRuby[:param_assignment] = lambda do |ast,state|
407
+ return state.indent + ast[0].to_HDLRuby(state) + " = " +
408
+ ast[1].to_HDLRuby(state) + "\n"
409
+ end
410
+
411
+
412
+ TO_HDLRuby[:input_declaration] = lambda do |ast,state|
413
+ # Ignore the INPUTTYPE not used in HDLRuby
414
+ # Get the sign if any.
415
+ sign = ast[1]
416
+ sign = "" unless sign
417
+ # Get the range.
418
+ range = ast[2]
419
+ range = range ? range.to_HDLRuby(state) + "." : ""
420
+ # Get the names.
421
+ names = ast[3].to_HDLRuby(state)
422
+ # Genereate the resulting declaration.
423
+ if state.level == :hdef then
424
+ # Specific case of function argument: ignore the types, and
425
+ # do not add new line no indent.
426
+ return names.gsub(":","")
427
+ else
428
+ # General case
429
+ return state.indent + sign + range +"input " + names + "\n"
430
+ end
431
+ end
432
+
433
+
434
+ TO_HDLRuby[:output_declaration] = lambda do |ast,state|
435
+ # Ignore the OUTPUTTYPE not used in HDLRuby
436
+ # Get the sign if any.
437
+ sign = ast[1]
438
+ sign = "" unless sign
439
+ # Get the range.
440
+ range = ast[2]
441
+ range = range ? range.to_HDLRuby(state) + "." : ""
442
+ # Get the names.
443
+ names = ast[3].to_HDLRuby(state)
444
+ # Genereate the resulting declaration.
445
+ return state.indent + sign + range +"output " + names + "\n"
446
+ end
447
+
448
+
449
+ TO_HDLRuby[:inout_declaration] = lambda do |ast,state|
450
+ # Ignore the INOUTTYPE not used in HDLRuby
451
+ # Get the sign if any.
452
+ sign = ast[1]
453
+ sign = "" unless sign
454
+ # Get the range.
455
+ range = ast[2]
456
+ range = range ? range.to_HDLRuby(state) + "." : ""
457
+ # Get the names.
458
+ names = ast[3].to_HDLRuby(state)
459
+ # Generate the resulting declaration.
460
+ return state.indent + sign + range + "inout " + names + "\n"
461
+ end
462
+
463
+
464
+ TO_HDLRuby[:net_declaration] = lambda do |ast,state|
465
+ # Ignore the NETTYPE which is not required in HDLRuby.
466
+ # Get the sign if any.
467
+ sign = ast[1]
468
+ sign = "" unless sign
469
+ # Get the expandrange if any.
470
+ expandrange = ast[2]
471
+ expandrange = expandrange ? expandrange.to_HDLRuby(state) + "." : ""
472
+ # Get the delay.
473
+ delay = delay ? ast[3].to_HDLRuby(state) : ""
474
+ if delay[0] then
475
+ raise "Internal error: delay in wire declaration not supported yet."
476
+ end
477
+ # Get the names.
478
+ names = ast[4].to_HDLRuby(state)
479
+ if names.empty? then
480
+ # There is actually no new inner.
481
+ return ""
482
+ end
483
+ # Generate the resulting declaration.
484
+ return state.indent + sign + expandrange + "inner " + names + "\n"
485
+ end
486
+
487
+
488
+ TO_HDLRuby[:reg_declaration] = lambda do |ast,state|
489
+ # Get the sign if any.
490
+ sign = ast[0]
491
+ sign = "" unless sign
492
+ # Get the range.
493
+ range = ast[1]
494
+ range = range ? range.to_HDLRuby(state) + "." : ""
495
+ # # Get the name.
496
+ # names = ast[2].to_HDLRuby(state)
497
+ # if names.empty? then
498
+ # # There is actually no new inner.
499
+ # return ""
500
+ # end
501
+ # Registers can also be memory, so treat each name independantly.
502
+ # # Genereate the resulting declaration.
503
+ # return state.indent + sign + range +"inner " + names + "\n"
504
+ res_txt = ""
505
+ ast[2][0].each do |reg|
506
+ if reg[0].type == :name_of_memory then
507
+ # It is a memory, it must be declared.
508
+ sign = "bit" if sign.empty?
509
+ res_txt += state.indent + sign + range[0..-2] +
510
+ "[" + reg[1].to_HDLRuby(state) + ".." +
511
+ reg[2].to_HDLRuby(state) + "].inner :" +
512
+ reg[0].to_HDLRuby(state) + "\n"
513
+ else
514
+ # It is a standard register, it may override a previous
515
+ # declaration and in such case can be omitted in HDLRuby.
516
+ n = reg[0].to_HDLRuby(state)
517
+ unless state.port_names.include?(n) then
518
+ res_txt += state.indent + sign + range + "inner :" + n + "\n"
519
+ end
520
+ end
521
+ end
522
+ return res_txt
523
+ end
524
+
525
+
526
+ TO_HDLRuby[:continuous_assignment] = lambda do |ast,state|
527
+ if ast[0] != "assign" then
528
+ raise "Internal error: unsupported continous assignment: #{ast[0]}"
529
+ end
530
+ if ast[1] then
531
+ raise "Internal error: drive strength not support yet #{ast[1]}"
532
+ end
533
+ if ast[2] then
534
+ raise "Internal error: expandrange in continous assignment not support yet #{ast[2]}"
535
+ end
536
+ if ast[3] then
537
+ raise "Internal error: delay in continous assignment not support yet #{ast[3]}"
538
+ end
539
+ return ast[4].to_HDLRuby(state)
540
+ end
541
+
542
+
543
+ # TO_HDLRuby[:list_of_variables] = lambda do |ast,state|
544
+ # return ast[0].map {|n| ":#{n.to_HDLRuby(state)}" }.join(", ")
545
+ # end
546
+
547
+
548
+ TO_HDLRuby[:list_of_variables] = lambda do |ast,state|
549
+ # Auth: variables that have already been declared are ignored
550
+ # since in HDLRuby all variables are identical.
551
+ return ast[0].map do |n|
552
+ n = n.to_HDLRuby(state)
553
+ if state.port_names.include?(n) then
554
+ nil
555
+ else
556
+ ":#{n}"
557
+ end
558
+ end.compact.join(", ")
559
+ end
560
+
561
+
562
+ TO_HDLRuby[:list_of_register_variables] = TO_HDLRuby[:list_of_variables]
563
+
564
+
565
+ TO_HDLRuby[:initial_statement] = lambda do |ast,state|
566
+ # Translated to a timed block.
567
+ head_txt = state.indent + "timed do\n"
568
+ # Save and update the state.
569
+ indent = state.indent
570
+ level = state.level
571
+ state.indent += " "
572
+ state.level = :timed
573
+ # Generate the content.
574
+ content_txt = ast[0].to_HDLRuby(state)
575
+ # Restore the state and generate the final result.
576
+ state.indent = indent
577
+ state.level = level
578
+ return head_txt + content_txt + state.indent + "end\n"
579
+ end
580
+
581
+
582
+ TO_HDLRuby[:always_statement] = lambda do |ast,state|
583
+ # Get the head statement.
584
+ head = ast[0]
585
+ head = head[0] while head[0].is_a?(AST) and head[0].type == :statement
586
+ # Get its synchronization if any.
587
+ event_txt = ""
588
+ delay_txt = ""
589
+ # Check if there is a delay or an event control,
590
+ # and generate the corresponding text if possible in the
591
+ # current generation state.
592
+ if head[0].type == :delay_or_event_control then
593
+ delay_or_event_control = head[0]
594
+ # There is a delay or an event, process it, and
595
+ # update the current statement (i.e. ast) to its second child.
596
+ delay_or_event_control = delay_or_event_control[0]
597
+ # For event.
598
+ if delay_or_event_control.type == :event_control then
599
+ if NoEventLevels.include?(state.level) then
600
+ ast.generate_error("there should not be an event here")
601
+ end
602
+ # Support, generate the event control text.
603
+ event_txt = delay_or_event_control.to_HDLRuby(state)
604
+ # For delay.
605
+ elsif delay_or_event_control.type == :delay_control then
606
+ # if NoTimeLevels.include?(state.level) then
607
+ # ast.generate_error("there should not be a delay here")
608
+ # end
609
+ # Supported, generate the delay control text.
610
+ delay_txt = delay_or_event_control.to_HDLRuby(state)
611
+ end
612
+ # Update the head statement.
613
+ head = head[1]
614
+ end
615
+ # Get the name if any.
616
+ name_txt = VerilogTools.get_name(head)
617
+ if delay_txt[0] then
618
+ # It will become a timed process with an infinite loop.
619
+ decl_txt = state.indent + "timed do\n" +
620
+ state.indent + " repeat(-1) do\n" +
621
+ " " + delay_txt
622
+ end_txt = state.indent + " end\n" + state.indent + "end\n"
623
+ # Now going to generate the content of the process.
624
+ # For that, save and update the state.
625
+ indent = state.indent
626
+ level = state.level
627
+ state.indent += " "
628
+ state.level = :timed
629
+ # Now generate the content.
630
+ content_txt = head.to_HDLRuby(state)
631
+ # Restore the state and generate the result.
632
+ state.indent = indent
633
+ state.level = level
634
+ return decl_txt + content_txt + end_txt
635
+ else
636
+ # It is a normal process.
637
+ # Generate the declaration of the process.
638
+ decl_txt = ""
639
+ unless delay_txt.empty? then
640
+ raise "Process with delay is not supported yet."
641
+ end
642
+ unless event_txt.empty? and name_txt.empty? then
643
+ # There are arguments to the process.
644
+ decl_txt += "(" + event_txt
645
+ decl_txt += ", " if event_txt[0] and name_txt[0]
646
+ decl_txt += "name: #{name_txt}" if name_txt[0]
647
+ decl_txt +=")"
648
+ end
649
+ decl_txt += " do\n"
650
+ # Generate its content.
651
+ # First check if it is a seq or par process at first.
652
+ seq_par = VerilogTools.get_seq_par(head)
653
+ seq_par = :par unless seq_par
654
+ # Now going to generate the content of the process.
655
+ # For that, save and update the state.
656
+ indent = state.indent
657
+ level = state.level
658
+ state.indent += " "
659
+ state.level = seq_par
660
+ # Now generate the content.
661
+ content_txt = head.to_HDLRuby(state)
662
+ # Restore the state and generate the result.
663
+ state.indent = indent
664
+ state.level = level
665
+ res = indent + seq_par.to_s + decl_txt
666
+ res += content_txt + indent + "end\n"
667
+ return res
668
+ end
669
+ end
670
+
671
+ TO_HDLRuby[:expandrange] = lambda do |ast,state|
672
+ # Auth: for now the type of expand range is ignored, maybe it
673
+ # is not necessary in HDLRuby.
674
+ return ast[1].to_HDLRuby(state)
675
+ end
676
+
677
+
678
+ TO_HDLRuby[:range] = lambda do |ast,state|
679
+ return "[" + ast[0].to_HDLRuby(state) + ".." +
680
+ ast[1].to_HDLRuby(state) + "]"
681
+ end
682
+
683
+
684
+ TO_HDLRuby[:module_instantiation] = lambda do |ast,state|
685
+ # Generate each element.
686
+ module_txt = ast[0].to_HDLRuby(state)
687
+ parameters_txt = ast[1] ? "(" + ast[1].to_HDLRuby(state) + ")." : ""
688
+ instance_txts = ast[2].map {|i| i.to_HDLRuby(state) }
689
+ # Generate the final state.
690
+ # Auth: in HDLRuby there is one such statement per module instance.
691
+ return instance_txts.map do |i|
692
+ state.indent + module_txt + parameters_txt + i + "\n"
693
+ end.join
694
+ end
695
+
696
+
697
+ TO_HDLRuby[:parameter_value_assignment] = lambda do |ast,state|
698
+ return ast[0].map {|p| p.to_HDLRuby(state) }.join(",")
699
+ end
700
+
701
+
702
+ TO_HDLRuby[:module_instance] = lambda do |ast,state|
703
+ instance_txt = "(:" + ast[0].to_HDLRuby(state) + ")"
704
+ if ast[1] then
705
+ return instance_txt + ".(" + ast[1].to_HDLRuby(state) + ")"
706
+ else
707
+ return instance_txt
708
+ end
709
+ end
710
+
711
+
712
+ TO_HDLRuby[:name_of_instance] = lambda do |ast,state|
713
+ name_txt = ast[0].to_HDLRuby(state)
714
+ range_txt = ast[1] ? ast[1].to_HDLRuby(state) : ""
715
+ if range_txt[0] then
716
+ # Auth: I do not know what to do with range here.
717
+ raise "Internal error: range in module instance name not supported yet."
718
+ end
719
+ return name_txt
720
+ end
721
+
722
+
723
+ TO_HDLRuby[:list_of_module_connections] = lambda do |ast,state|
724
+ return ast[0].map { |c| c.to_HDLRuby(state) }.join(",")
725
+ end
726
+
727
+
728
+ TO_HDLRuby[:module_port_connection] = lambda do |ast,state|
729
+ return ast[0].to_HDLRuby(state)
730
+ end
731
+
732
+
733
+ TO_HDLRuby[:named_port_connection] = lambda do |ast,state|
734
+ return ast[0].to_HDLRuby(state) + ":" + ast[1].to_HDLRuby(state)
735
+ end
736
+
737
+
738
+ TO_HDLRuby[:statement_or_null] = lambda do |ast,state|
739
+ if ast[0] then
740
+ return ast[0].to_HDLRuby(state)
741
+ else
742
+ return ""
743
+ end
744
+ end
745
+
746
+
747
+ TO_HDLRuby[:statement] = lambda do |ast,state|
748
+ # Check if it is a block, and generate the corresponding code.
749
+ block_txt = ""
750
+ type = ast[0].is_a?(AST) ? ast[0].type : ast[0].to_sym
751
+ case type
752
+ when :seq_block
753
+ seq_block = ast[0]
754
+ # Get the name if any.
755
+ # Auth: in this case, what to do with the name?
756
+ name_txt = VerilogTools.get_name(seq_block)
757
+ # Generate the declarations if any.
758
+ decls = seq_block[1]
759
+ decls_txt = decls ? decls.map {|d| d.to_HDLRuby(state)}.join : ""
760
+ # Saves the state.
761
+ indent = state.indent
762
+ level = state.level
763
+ # Generate the content.
764
+ seq_par_txt = [ [state.level, ""] ] # The list of seq and par block contents.
765
+ content = seq_block[2]
766
+ content_txt = ""
767
+ content.each do |statement|
768
+ seq_par = VerilogTools.get_seq_par(statement)
769
+ # Check if the blocking/non blocking mode changed.
770
+ if seq_par != seq_par_txt[-1][0] then
771
+ if !content_txt.empty? then
772
+ # There is a content, add it to the list.
773
+ seq_par_txt[-1][1] = content_txt
774
+ content_txt == ""
775
+ end
776
+ # Add a new block.
777
+ seq_par_txt << [seq_par, ""]
778
+ end
779
+ # Update the content.
780
+ state.level = seq_par if seq_par
781
+ content_txt += statement.to_HDLRuby(state)
782
+ end
783
+ # Update the final seq_par_txt block.
784
+ seq_par_txt[-1][1] = content_txt
785
+ # Restores the state and generate the final text.
786
+ state.indent = indent
787
+ state.level = level
788
+ # Get the base seq or par state of the process
789
+ base = seq_par_txt[0][0]
790
+ # Generate the body text.
791
+ body_txt = decls_txt.empty? ? "" : decls_txt + "\n"
792
+ seq_par_txt.each do |seq_par, txt|
793
+ if seq_par and seq_par != base then
794
+ body_txt += state.indent + " " + seq_par.to_s + " do\n" +
795
+ txt + state.indent + " " + "end\n"
796
+ else
797
+ body_txt += txt
798
+ end
799
+ end
800
+ # Return the result.
801
+ return body_txt
802
+ when :system_task_enable
803
+ sys = ast[0]
804
+ name_txt = sys[0].to_HDLRuby(state)
805
+ arg_txt = sys[1] ? sys[1].map{|a|a.to_HDLRuby(state)}.join(",") : ""
806
+ return state.indent +
807
+ VerilogTools.system_to_HDLRuby(name_txt,arg_txt) + "\n"
808
+ when :if
809
+ # Saves the state.
810
+ indent = state.indent
811
+ level = state.level
812
+ # Generate the hif.
813
+ state.indent += " "
814
+ if_txt = indent + "hif(" + ast[1].to_HDLRuby(state) + ") do\n"
815
+ if_txt += ast[2].to_HDLRuby(state) + indent + "end\n"
816
+ if ast[3] then
817
+ if_txt += indent + "helse do\n"
818
+ if_txt += ast[3].to_HDLRuby(state) + indent + "end\n"
819
+ end
820
+ # Restore the state and return the result.
821
+ state.indent = indent
822
+ state.level = level
823
+ return if_txt
824
+ when :case
825
+ # Saves the state.
826
+ indent = state.indent
827
+ level = state.level
828
+ # Generate the hcase.
829
+ state.indent += " "
830
+ case_txt = indent + "hcase(" + ast[1].to_HDLRuby(state) + ")\n"
831
+ # Generate the case items.
832
+ case_txt += ast[2].map do |item|
833
+ res_txt = ""
834
+ if item[0] then
835
+ # hwhen case.
836
+ res_txt += indent + "hwhen("
837
+ res_txt += item[0].map {|e| e.to_HDLRuby(state) }.join(",")
838
+ res_txt += ") do\n"
839
+ res_txt += item[1].to_HDLRuby(state)
840
+ res_txt += indent + "end\n"
841
+ else
842
+ # helse case.
843
+ res_txt += indent + "helse do\n"
844
+ res_txt += item[1].to_HDLRuby(state) + indent + "end\n"
845
+ end
846
+ res_txt
847
+ end.join
848
+ # Restore the state and return the result.
849
+ state.indent = indent
850
+ state.level = level
851
+ return case_txt
852
+ when :blocking_assignment, :non_blocking_assignment
853
+ return ast[0].to_HDLRuby(state)
854
+ when :statement
855
+ # Simply recurse, but first restores the indent.
856
+ state.indent = indent
857
+ return ast[0].to_HDLRuby(state)
858
+ when :delay_or_event_control
859
+ delay = ast[0][0]
860
+ if delay.type != :delay_control then
861
+ raise "Event not supported within statements yet."
862
+ end
863
+ return delay.to_HDLRuby(state) + ast[1].to_HDLRuby(state)
864
+ else
865
+ raise "Unsupported statement type: #{type}"
866
+ end
867
+ end
868
+
869
+
870
+ TO_HDLRuby[:assignment] = lambda do |ast,state|
871
+ return state.indent + ast[0].to_HDLRuby(state) + " <= " +
872
+ ast[1].to_HDLRuby(state) + "\n"
873
+ end
874
+
875
+
876
+ # Blocking and non blocking assignments have the same resulting
877
+ # code in HDLruby, however they are included in different kind of
878
+ # blocks, but this is processed elsewhere.
879
+ TO_HDLRuby[:blocking_assignment] = lambda do |ast,state|
880
+ if ast[1] then
881
+ raise "Internal error: unsupported delay or event in assingment yet."
882
+ end
883
+ return state.indent + ast[0].to_HDLRuby(state) + " <= " +
884
+ ast[2].to_HDLRuby(state) + "\n"
885
+ end
886
+
887
+ TO_HDLRuby[:non_blocking_assignment] = TO_HDLRuby[:blocking_assignment]
888
+
889
+
890
+ TO_HDLRuby[:lvalue] = lambda do |ast, state|
891
+ # Get the base of the primary: number or identifier.
892
+ base = ast[0]
893
+ base_txt = base.to_HDLRuby(state)
894
+ expr1 = ast[1]
895
+ expr2 = ast[2]
896
+ if expr1 then
897
+ # Array access type.
898
+ if expr2 then
899
+ # Range access.
900
+ return base_txt + "[" +
901
+ expr1.to_HDLRuby(state) + ".." + expr2.to_HDLRuby(state) +
902
+ "]"
903
+ else
904
+ # Index access.
905
+ return base_txt + "[" + expr1.to_HDLRuby(state) + "]"
906
+ end
907
+ else
908
+ # Default access.
909
+ return base_txt
910
+ end
911
+ end
912
+
913
+
914
+ TO_HDLRuby[:expression] = lambda do |ast,state|
915
+ # Depending on the child.
916
+ child = ast[0]
917
+ # Is it a conditional expression?
918
+ if child.is_a?(Array) then
919
+ # Go inside an expression so save and update the state.
920
+ level = state.level
921
+ state.level = :expr
922
+ # Yes, generate the conditional.
923
+ res_txt = ""
924
+ depth = 0
925
+ elems = child.reverse
926
+ while elems.any? do
927
+ expr_txt = elems.pop.to_HDLRuby(state)
928
+ case(elems.pop)
929
+ when "?"
930
+ res_txt += "mux(~" + expr_txt + ","
931
+ depth += 1
932
+ when ":" then
933
+ res_txt += expr_txt + ","
934
+ when nil then
935
+ res_txt += expr_txt + ")" * depth
936
+ depth = 0
937
+ end
938
+ end
939
+ # Restores the state and return the result.
940
+ state.level = level
941
+ else
942
+ # No, just return the generation result for the child
943
+ res_txt = child.to_HDLRuby(state)
944
+ end
945
+ return res_txt
946
+ end
947
+
948
+ # All the expression AST have the same structure until the primary.
949
+
950
+ TO_HDLRuby[:condition_term] = lambda do |ast,state|
951
+ # Save the state (may change after).
952
+ level = state.level
953
+ if ast[0].size > 1 then
954
+ # Go inside the expression, so update the level.
955
+ state.level = :expr
956
+ end
957
+ res_txt = ast[0].map do |elem|
958
+ elem.is_a?(String) ? VerilogTools.operator_to_HDLRuby(elem) :
959
+ elem.to_HDLRuby(state)
960
+ end.join
961
+ # Restores the state.
962
+ state.level = level
963
+ if state.level != :expr or ast[0].size < 3 then
964
+ # Single node, unary or not within expression cases:
965
+ # no parenthesis required.
966
+ return res_txt
967
+ else
968
+ # Otherwise they are required to avoid priority problems.
969
+ return "(" + res_txt + ")"
970
+ end
971
+ end
972
+
973
+ TO_HDLRuby[:logic_or_term] = TO_HDLRuby[:condition_term]
974
+
975
+ TO_HDLRuby[:logic_and_term] = TO_HDLRuby[:condition_term]
976
+
977
+ TO_HDLRuby[:bit_or_term] = TO_HDLRuby[:condition_term]
978
+
979
+ TO_HDLRuby[:bit_xor_term] = TO_HDLRuby[:condition_term]
980
+
981
+ TO_HDLRuby[:bit_and_term] = TO_HDLRuby[:condition_term]
982
+
983
+ TO_HDLRuby[:equal_term] = TO_HDLRuby[:condition_term]
984
+
985
+ TO_HDLRuby[:comparison_term] = TO_HDLRuby[:condition_term]
986
+
987
+ TO_HDLRuby[:shift_term] = TO_HDLRuby[:condition_term]
988
+
989
+ TO_HDLRuby[:add_term] = TO_HDLRuby[:condition_term]
990
+
991
+ TO_HDLRuby[:mul_term] = lambda do |ast,state|
992
+ primary_txt = ast[0][-1].to_HDLRuby(state)
993
+ if ast[0].size == 1 then
994
+ # There is no operator, just return the priary text.
995
+ return primary_txt
996
+ else
997
+ # There is an operator, depending on it.
998
+ op = ast[0][0]
999
+ case(op)
1000
+ when "+", "-", "~", "!"
1001
+ return VerilogTools.operator_to_HDLRuby(op) + primary_txt
1002
+ when "&", "|", "^", "^|"
1003
+ return primary_txt +
1004
+ ".each.reduce(:" + VerilogTools.operator_to_HDLRuby(op) + ")"
1005
+ when "~&", "~|", "~^"
1006
+ return "~" + primary_txt +
1007
+ ".each.reduce(:" + VerilogTools.operator_to_HDLRuby(op[1]) +")"
1008
+ else
1009
+ raise "Internal error: unknown unary operator #{op}"
1010
+ end
1011
+ end
1012
+ end
1013
+
1014
+
1015
+ TO_HDLRuby[:primary] = lambda do |ast,state|
1016
+ # Get the base of the primary: number or identifier.
1017
+ base = ast[0]
1018
+ base_txt = base.to_HDLRuby(state)
1019
+ # Depending on the base.
1020
+ if base.type == :mintypmax_expression then
1021
+ # Parenthesis case.
1022
+ # Auth: but can be ommitted since automatically
1023
+ # set for ensuring order of operations.
1024
+ # return "(" + base_txt + ")"
1025
+ return base_txt
1026
+ else
1027
+ expr1 = ast[1]
1028
+ expr2 = ast[2]
1029
+ if expr1 then
1030
+ # Array access type.
1031
+ if expr2 then
1032
+ # Range access.
1033
+ return base_txt + "[" +
1034
+ expr1.to_HDLRuby(state) + ".." + expr2.to_HDLRuby(state) +
1035
+ "]"
1036
+ else
1037
+ # Index access.
1038
+ return base_txt + "[" + expr1.to_HDLRuby(state) + "]"
1039
+ end
1040
+ else
1041
+ # Default access.
1042
+ return base_txt
1043
+ end
1044
+ end
1045
+ end
1046
+
1047
+
1048
+ TO_HDLRuby[:number] = lambda do |ast,state|
1049
+ # Get the first number if any.
1050
+ number0 = ast[0] ? ast[0].to_HDLRuby(state) : ""
1051
+ # Get the base if any.
1052
+ base = ast[1] ? ast[1].to_HDLRuby(state) : ""
1053
+ # Get the second number if any.
1054
+ number1 = ast[2] ? ast[2].to_HDLRuby(state) : ""
1055
+ # Depending on the base.
1056
+ case base
1057
+ when "'b"
1058
+ # Binary encoding.
1059
+ return "_#{number0}b#{number1}"
1060
+ when "'o"
1061
+ # Octal encoding.
1062
+ return "_#{number0}o#{number1}"
1063
+ when "'d"
1064
+ # Decimal encoding.
1065
+ return "_#{number0}d#{number1}"
1066
+ when "'h"
1067
+ # Hexadecimal encoding.
1068
+ return "_#{number0}h#{number1}"
1069
+ when ""
1070
+ # Simple number.
1071
+ return number0
1072
+ else
1073
+ ast.generate_error("Invalid number base: #{base}")
1074
+ end
1075
+ end
1076
+
1077
+
1078
+ TO_HDLRuby[:concatenation] = lambda do |ast,state|
1079
+ return "[ " + ast[0].map {|e| e.to_HDLRuby(state) }.join(", ") + " ]"
1080
+ end
1081
+
1082
+
1083
+ TO_HDLRuby[:multiple_concatenation] = lambda do |ast,state|
1084
+ return "[" + ast[1].map {|e| e.to_HDLRuby(state) }.join(", ") +
1085
+ " ].to_expr.as(bit[" + ast[0].to_HDLRuby(state) + "])"
1086
+ end
1087
+
1088
+
1089
+ TO_HDLRuby[:function_call] = lambda do |ast,state|
1090
+ # Get the name of the function.
1091
+ name_txt = ast[0].to_HDLRuby
1092
+ # Get the arguments if any.
1093
+ args_txt = ast[1] ? ast[1].map {|a|a.to_HDLRuby(state)}.join(",") : ""
1094
+ # Is it a system function call?
1095
+ if (ast[0].type == :name_of_system_function) then
1096
+ # Yes, specific process.
1097
+ return VerilogTools.system_to_HDLRuby(name_txt,args_txt)
1098
+ else
1099
+ # No, standard function call.
1100
+ return name_txt + "(" + args_txt + ")"
1101
+ end
1102
+ end
1103
+
1104
+
1105
+
1106
+ TO_HDLRuby[:event_expression] = lambda do |ast,state|
1107
+ return ast[0].map {|ev| ev.to_HDLRuby(state) }.join(",")
1108
+ end
1109
+
1110
+
1111
+ TO_HDLRuby[:event_primary] = lambda do |ast,state|
1112
+ edge = ast[0]
1113
+ case edge
1114
+ when "posedge"
1115
+ return ast[1].to_HDLRuby + ".posedge"
1116
+ when "negedge"
1117
+ return ast[1].to_HDLRuby + ".negedge"
1118
+ when "*"
1119
+ # Activated on all.
1120
+ return ""
1121
+ else
1122
+ # Actually it is not an edge.
1123
+ return edge.to_HDLRuby(state)
1124
+ end
1125
+ end
1126
+
1127
+
1128
+ TO_HDLRuby[:_IDENTIFIER] = lambda do |ast,state|
1129
+ VerilogTools.name_to_HDLRuby(ast[0])
1130
+ end
1131
+
1132
+
1133
+ TO_HDLRuby[:delay_control] = lambda do |ast,state|
1134
+ # Generate the delay.
1135
+ head_txt = state.indent + "!"
1136
+ delay_txt = ast[0].to_HDLRuby(state)
1137
+ # Compute the time scale.
1138
+ timescale = ast[-1][0][:timescale]
1139
+ if timescale then
1140
+ mult = timescale[0]
1141
+ if mult != 1 then
1142
+ return head_txt + "(" + delay_txt + "*#{mult}).fs\n"
1143
+ else
1144
+ return head_txt + delay_txt + ".fs\n"
1145
+ end
1146
+ else
1147
+ # By default use nanoseconds
1148
+ return delay_txt + ".ns\n"
1149
+ end
1150
+ end
1151
+
1152
+ end
1153
+ end