HDLRuby 3.3.4 → 3.4.0

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.
@@ -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