HDLRuby 2.10.5 → 2.11.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/HDLRuby.gemspec +1 -0
  3. data/README.md +8 -4
  4. data/Rakefile +8 -0
  5. data/{lib/HDLRuby/sim/Makefile → ext/hruby_sim/Makefile_csim} +0 -0
  6. data/ext/hruby_sim/extconf.rb +13 -0
  7. data/ext/hruby_sim/hruby_rcsim_build.c +1188 -0
  8. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim.h +255 -16
  9. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_calc.c +310 -181
  10. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_core.c +34 -17
  11. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_list.c +0 -0
  12. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_stack_calc.c +4 -1
  13. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_stack_calc.c.sav +0 -0
  14. data/ext/hruby_sim/hruby_sim_tree_calc.c +375 -0
  15. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_vcd.c +5 -5
  16. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_vizualize.c +2 -2
  17. data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_value_pool.c +4 -1
  18. data/lib/HDLRuby/hdr_samples/bstr_bench.rb +2 -0
  19. data/lib/HDLRuby/hdr_samples/case_bench.rb +2 -2
  20. data/lib/HDLRuby/hdr_samples/counter_bench.rb +0 -1
  21. data/lib/HDLRuby/hdr_samples/counter_dff_bench.rb +46 -0
  22. data/lib/HDLRuby/hdr_samples/dff_bench.rb +1 -1
  23. data/lib/HDLRuby/hdr_samples/print_bench.rb +62 -0
  24. data/lib/HDLRuby/hdr_samples/rom.rb +5 -3
  25. data/lib/HDLRuby/hdr_samples/simple_counter_bench.rb +43 -0
  26. data/lib/HDLRuby/hdrcc.rb +54 -8
  27. data/lib/HDLRuby/hruby_bstr.rb +1175 -917
  28. data/lib/HDLRuby/hruby_high.rb +200 -90
  29. data/lib/HDLRuby/hruby_high_fullname.rb +82 -0
  30. data/lib/HDLRuby/hruby_low.rb +41 -23
  31. data/lib/HDLRuby/hruby_low2c.rb +7 -0
  32. data/lib/HDLRuby/hruby_rcsim.rb +978 -0
  33. data/lib/HDLRuby/hruby_rsim.rb +1134 -0
  34. data/lib/HDLRuby/hruby_rsim_vcd.rb +322 -0
  35. data/lib/HDLRuby/hruby_values.rb +362 -18
  36. data/lib/HDLRuby/hruby_verilog.rb +21 -3
  37. data/lib/HDLRuby/version.rb +1 -1
  38. metadata +24 -13
@@ -0,0 +1,1134 @@
1
+ require "HDLRuby/hruby_high"
2
+ # require "HDLRuby/hruby_low_resolve"
3
+ require "HDLRuby/hruby_bstr"
4
+ require "HDLRuby/hruby_values"
5
+
6
+
7
+
8
+ module HDLRuby::High
9
+
10
+ ##
11
+ # Library for describing the Ruby simulator of HDLRuby
12
+ #
13
+ ########################################################################
14
+
15
+ ##
16
+ # Enhance a system type with Ruby simulation.
17
+ class SystemT
18
+
19
+ ## Add timed behavior +beh+.
20
+ # Returns the id of the timed behavior.
21
+ def add_timed_behavior(beh)
22
+ @timed_behaviors << beh
23
+ @total_timed_behaviors += 1
24
+ return @total_timed_behaviors - 1
25
+ end
26
+
27
+ ## Remove timed beahvior +beh+
28
+ def remove_timed_behavior(beh)
29
+ # puts "remove_timed_behavior"
30
+ @timed_behaviors.delete(beh)
31
+ end
32
+
33
+ ## Add +sig+ to the list of active signals.
34
+ def add_sig_active(sig)
35
+ # puts "Adding activated signal=#{sig.fullname}"
36
+ @sig_active << sig
37
+ end
38
+
39
+ ## Run the simulation from the current systemT and outputs the resuts
40
+ # on simout.
41
+ def sim(simout)
42
+ HDLRuby.show "Initializing Ruby-level simulator..."
43
+ HDLRuby.show "#{Time.now}#{show_mem}"
44
+ # Merge the included.
45
+ self.merge_included!
46
+ # Initializes the run mutex and the conditions.
47
+ @mutex = Mutex.new
48
+ @master = ConditionVariable.new
49
+ @master_flag = 0
50
+ @slave = ConditionVariable.new
51
+ @slave_flags_not = 0
52
+ @num_done = 0
53
+ # @lock = 0
54
+ # @runs = 0
55
+ # Initializes the time.
56
+ @time = 0
57
+ # Initializes the time and signals execution buffers.
58
+ @tim_exec = []
59
+ @sig_exec = []
60
+ # Initialize the list of currently exisiting timed behavior.
61
+ @timed_behaviors = []
62
+ # Initialize the list of activated signals.
63
+ @sig_active = []
64
+ # Initializes the total number of timed behaviors (currently
65
+ # existing or not: used for generating the id of the behaviors).
66
+ @total_timed_behaviors = 0
67
+ # Initilizes the simulation.
68
+ self.init_sim(self)
69
+ # Initialize the displayer.
70
+ self.show_init(simout)
71
+ # exit
72
+ # First all the timed behaviors are to be executed.
73
+ @timed_behaviors.each {|beh| @tim_exec << beh }
74
+ # But starts locked.
75
+ @slave_flags_not = 2**@timed_behaviors.size - 1
76
+ # Starts the threads.
77
+ @timed_behaviors.each {|beh| beh.make_thread }
78
+
79
+ HDLRuby.show "Starting Ruby-level simulator..."
80
+ HDLRuby.show "#{Time.now}#{show_mem}"
81
+ # Run the simulation.
82
+ self.run_init do
83
+ # # Wake the behaviors.
84
+ # @timed_behaviors.each {|beh| beh.run }
85
+ until @tim_exec.empty? do
86
+ # Display the time
87
+ self.show_time
88
+ # Execute the time behaviors that are ready.
89
+ self.run_ack
90
+ self.run_wait
91
+ shown_values = {}
92
+ # Get the behaviors waiting on activated signals.
93
+ until @sig_active.empty? do
94
+ # # Update the signals.
95
+ # @sig_active.each { |sig| sig.c_value = sig.f_value }
96
+ # puts "sig_active.size=#{@sig_active.size}"
97
+ # Look for the behavior sensitive to the signals.
98
+ @sig_active.each do |sig|
99
+ sig.each_anyedge { |beh| @sig_exec << beh }
100
+ if (sig.c_value.zero? && !sig.f_value.zero?) then
101
+ # puts "sig.c_value=#{sig.c_value.content}"
102
+ sig.each_posedge { |beh| @sig_exec << beh }
103
+ elsif (!sig.c_value.zero? && sig.f_value.zero?) then
104
+ sig.each_negedge { |beh| @sig_exec << beh }
105
+ end
106
+ end
107
+ # Update the signals.
108
+ @sig_active.each { |sig| sig.c_value = sig.f_value }
109
+ # puts "first @sig_exec.size=#{@sig_exec.size}"
110
+ @sig_exec.uniq! {|beh| beh.object_id }
111
+ # Display the activated signals.
112
+ @sig_active.each do |sig|
113
+ if !shown_values[sig].eql?(sig.f_value) then
114
+ self.show_signal(sig)
115
+ shown_values[sig] = sig.f_value
116
+ end
117
+ end
118
+ # Clear the list of active signals.
119
+ @sig_active.clear
120
+ # puts "sig_exec.size=#{@sig_exec.size}"
121
+ # Execute the relevant behaviors and connections.
122
+ @sig_exec.each { |obj| obj.execute(:par) }
123
+ @sig_exec.clear
124
+ @sig_active.uniq! {|sig| sig.object_id }
125
+ # puts "@sig_active.size=#{@sig_active.size}"
126
+ end
127
+ break if @timed_behaviors.empty?
128
+ # Advance time.
129
+ @time = (@timed_behaviors.min {|b0,b1| b0.time <=> b1.time }).time
130
+ # Schedule the next timed behavior to execute.
131
+ @tim_exec = []
132
+ @timed_behaviors.each do |beh|
133
+ @tim_exec << beh if beh.time == @time
134
+ end
135
+ # puts "@tim_exec.size=#{@tim_exec.size}"
136
+ # puts "@timed_bevaviors.size=#{@timed_behaviors.size}"
137
+ end
138
+ end
139
+ end
140
+
141
+ ## Initialize the simulation for system +systemT+.
142
+ def init_sim(systemT)
143
+ # puts "init_sim for #{self} (#{self.name})"
144
+ # Recurse on the signals.
145
+ self.each_signal { |sig| sig.init_sim(systemT) }
146
+ # Recure on the scope.
147
+ self.scope.init_sim(systemT)
148
+ end
149
+
150
+ ## Initialize run for executing +ruby_block+
151
+ def run_init(&ruby_block)
152
+ @mutex.synchronize(&ruby_block)
153
+ end
154
+
155
+ ## Request for running for timed behavior +id+
156
+ def run_req(id)
157
+ # puts "run_req with id=#{id} and @slave_flags_not=#{@slave_flags_not}"
158
+ @slave.wait(@mutex) while @slave_flags_not[id] == 1
159
+ end
160
+
161
+ ## Tell running part done for timed behavior +id+.
162
+ def run_done(id)
163
+ # puts "run_done with id=#{id}"
164
+ @num_done += 1
165
+ @slave_flags_not |= 2**id
166
+ if @num_done == @tim_exec.size
167
+ # puts "All done."
168
+ @master_flag = 1
169
+ @master.signal
170
+ end
171
+ end
172
+
173
+ ## Wait for all the run to complete.
174
+ def run_wait
175
+ # puts "run_wait"
176
+ @master.wait(@mutex) unless @master_flag == 1
177
+ @num_done = 0
178
+ @master_flag = 0
179
+ end
180
+
181
+ ## Acknowledge the run request the executable timed behavior.
182
+ def run_ack
183
+ # puts "run_ack"
184
+ mask = 0
185
+ @tim_exec.each { |beh| mask |= 2**beh.id }
186
+ mask = 2**@total_timed_behaviors - 1 - mask
187
+ @slave_flags_not &= mask
188
+ @slave.broadcast
189
+ end
190
+
191
+ ## Initializes the displayer
192
+ def show_init(simout)
193
+ # Sets the simulation output.
194
+ @simout = simout
195
+ end
196
+
197
+ ## Displays the time.
198
+ def show_time
199
+ @simout.puts("# #{@time}ps")
200
+ end
201
+
202
+ ## Displays the value of signal +sig+.
203
+ def show_signal(sig)
204
+ @simout.puts("#{sig.fullname}: #{sig.f_value.to_vstr}")
205
+ end
206
+
207
+ ## Displays value +val+.
208
+ def show_value(val)
209
+ @simout.print(val.to_vstr)
210
+ end
211
+
212
+ ## Displays string +str+.
213
+ def show_string(str)
214
+ @simout.print(str)
215
+ end
216
+
217
+
218
+ ## Returns the name of the signal with its hierarchy.
219
+ def fullname
220
+ @fullname ||= (self.parent ? self.parent.fullname + ":" : "") +
221
+ self.name.to_s
222
+ return @fullname
223
+ end
224
+ end
225
+
226
+
227
+ ##
228
+ # Describes scopes of system types.
229
+ class Scope
230
+
231
+ ## Initialize the simulation for system +systemT+.
232
+ def init_sim(systemT)
233
+ # Recurse on the inner signals.
234
+ self.each_inner { |sig| sig.init_sim(systemT) }
235
+ # Recurse on the behaviors.
236
+ self.each_behavior { |beh| beh.init_sim(systemT) }
237
+ # Recurse on the systemI.
238
+ self.each_systemI { |sys| sys.init_sim(systemT) }
239
+ # Recurse on the connections.
240
+ self.each_connection { |cnx| cnx.init_sim(systemT) }
241
+ # Recurse on the sub scopes.
242
+ self.each_scope { |sco| sco.init_sim(systemT) }
243
+ end
244
+
245
+ ## Returns the name of the signal with its hierarchy.
246
+ def fullname
247
+ @fullname ||= self.parent.fullname + ":" + self.name.to_s
248
+ return @fullname
249
+ end
250
+ end
251
+
252
+
253
+ ## Extends the TypeTuple class for Ruby simulation.
254
+ class TypeTuple
255
+ # Add the possibility to change the direction.
256
+ def direction=(dir)
257
+ @direction = dir == :little ? :little : :big
258
+ end
259
+ end
260
+
261
+ ## Extends the TypeStruct class for Ruby simulation.
262
+ class TypeStruct
263
+ # Add the possibility to change the direction.
264
+ def direction=(dir)
265
+ @direction = dir == :little ? :little : :big
266
+ end
267
+ end
268
+
269
+
270
+ ##
271
+ # Describes a behavior.
272
+ class Behavior
273
+
274
+ ## Execute the expression.
275
+ def execute(mode)
276
+ return self.block.execute(mode)
277
+ end
278
+
279
+ ## Initialize the simulation for system +systemT+.
280
+ def init_sim(systemT)
281
+ # Process the sensitivity list.
282
+ # Is it a clocked behavior?
283
+ events = self.each_event.to_a
284
+ if events.empty? then
285
+ # No events, this is not a clock behavior.
286
+ # And it is not a time behavior neigther.
287
+ # Generate the events list from the right values.
288
+ # First get the references.
289
+ refs = self.block.each_node_deep.select do |node|
290
+ node.is_a?(RefObject) && !node.leftvalue? &&
291
+ !node.parent.is_a?(RefObject)
292
+ end.to_a
293
+ # Keep only one ref per signal.
294
+ refs.uniq! { |node| node.fullname }
295
+ # Remove the inner signals from the list.
296
+ self.block.each_inner do |inner|
297
+ refs.delete_if {|r| r.name == inner.name }
298
+ end
299
+ # Generate the event.
300
+ events = refs.map {|ref| Event.new(:anyedge,ref.clone) }
301
+ # Add them to the behavior for further processing.
302
+ events.each {|event| self.add_event(event) }
303
+ end
304
+ # Now process the events: add the behavior to the corresponding
305
+ # activation list of the signals of the events.
306
+ self.each_event do |event|
307
+ sig = event.ref.object
308
+ case event.type
309
+ when :posedge
310
+ sig.add_posedge(self)
311
+ when :negedge
312
+ sig.add_negedge(self)
313
+ else
314
+ sig.add_anyedge(self)
315
+ end
316
+ end
317
+ # Now process the block.
318
+ self.block.init_sim(systemT)
319
+ end
320
+
321
+ ## Returns the name of the signal with its hierarchy.
322
+ def fullname
323
+ return self.parent.fullname
324
+ end
325
+ end
326
+
327
+
328
+ ##
329
+ # Describes a timed behavior.
330
+ #
331
+ # NOTE:
332
+ # * this is the only kind of behavior that can include time statements.
333
+ # * this kind of behavior is not synthesizable!
334
+ class TimeBehavior
335
+ ## Get the current time of the behavior.
336
+ attr_accessor :time
337
+ ## Get the id of the timed behavior.
338
+ attr_reader :id
339
+
340
+ ## Initialize the simulation for system +systemT+.
341
+ def init_sim(systemT)
342
+ @sim = systemT
343
+ # Add the behavior to the list of timed behavior.
344
+ @id = systemT.add_timed_behavior(self)
345
+ # Initialize the time to 0.
346
+ @time = 0
347
+ # Initialize the statements.
348
+ self.block.init_sim(systemT)
349
+ end
350
+
351
+ # Create the execution thread
352
+ def make_thread
353
+ systemT = @sim
354
+ @thread = Thread.new do
355
+ # puts "In thread."
356
+ # sleep
357
+ systemT.run_init do
358
+ begin
359
+ # puts "Starting thread"
360
+ systemT.run_req(@id)
361
+ self.block.execute(:par)
362
+ # puts "Ending thread"
363
+ rescue => e
364
+ puts "Got exception: #{e.full_message}"
365
+ end
366
+ systemT.remove_timed_behavior(self)
367
+ systemT.run_done(@id)
368
+ end
369
+ end
370
+ end
371
+
372
+ ## (Re)start execution of the thread.
373
+ def run
374
+ # Run.
375
+ @thread.run
376
+ end
377
+ end
378
+
379
+
380
+ ##
381
+ # Describes an event.
382
+ class Event
383
+ # Nothing to do.
384
+ end
385
+
386
+
387
+ ##
388
+ # Module for extending signal classes with Ruby-level simulation.
389
+ module SimSignal
390
+ # Access the current and future value.
391
+ attr_accessor :c_value, :f_value
392
+
393
+ ## Initialize the simulation for +systemT+
394
+ def init_sim(systemT)
395
+ if self.value then
396
+ @c_value = self.value.execute(:par).to_value
397
+ @f_value = @c_value.to_value
398
+ # puts "init signal value at=#{@c_value.to_bstr}"
399
+ # The signal is considered active.
400
+ systemT.add_sig_active(self)
401
+ else
402
+ # @c_value = Value.new(self.type,"x" * self.type.width)
403
+ # @f_value = Value.new(self.type,"x" * self.type.width)
404
+ @c_value = Value.new(self.type,"x")
405
+ @f_value = Value.new(self.type,"x")
406
+ end
407
+ end
408
+
409
+ ## Adds behavior +beh+ activated on a positive edge of the signal.
410
+ def add_posedge(beh)
411
+ @posedge_behaviors ||= []
412
+ @posedge_behaviors << beh
413
+ end
414
+
415
+ ## Adds behavior +beh+ activated on a negative edge of the signal.
416
+ def add_negedge(beh)
417
+ @negedge_behaviors ||= []
418
+ @negedge_behaviors << beh
419
+ end
420
+
421
+ ## Adds behavior +beh+ activated on a any edge of the signal.
422
+ def add_anyedge(beh)
423
+ @anyedge_behaviors ||= []
424
+ @anyedge_behaviors << beh
425
+ end
426
+
427
+ ## Iterates over the behaviors activated on a positive edge.
428
+ def each_posedge(&ruby_block)
429
+ @posedge_behaviors ||= []
430
+ @posedge_behaviors.each(&ruby_block)
431
+ end
432
+
433
+ ## Iterates over the behaviors activated on a negative edge.
434
+ def each_negedge(&ruby_block)
435
+ @negedge_behaviors ||= []
436
+ @negedge_behaviors.each(&ruby_block)
437
+ end
438
+
439
+ ## Iterates over the behaviors activated on any edge.
440
+ def each_anyedge(&ruby_block)
441
+ @anyedge_behaviors ||= []
442
+ @anyedge_behaviors.each(&ruby_block)
443
+ end
444
+
445
+
446
+ ## Execute the expression.
447
+ def execute(mode)
448
+ # puts "Executing signal=#{self.fullname}"
449
+ # return mode == :par ? self.c_value : self.f_value
450
+ return @mode == :seq ? self.f_value : self.c_value
451
+ end
452
+
453
+ ## Assigns +value+ the the reference.
454
+ def assign(mode,value)
455
+ # Set the next value.
456
+ @f_value = value
457
+ # Set the mode.
458
+ @mode = mode
459
+ # puts "assign #{value.content} (#{value.content.class}) with self.type.width=#{self.type.width} while value.type.width=#{value.type.width}" if self.name.to_s.include?("idx")
460
+ # @f_value = value.cast(self.type) # Cast inserted by HDLRuby normally
461
+ end
462
+
463
+ ## Assigns +value+ at +index+ (integer or range).
464
+ def assign_at(mode,value,index)
465
+ # @f_value = @f_value.assign_at(mode,value,index)
466
+ # Sets the next value.
467
+ if (@f_value.equal?(@c_value)) then
468
+ # Need to duplicate @f_value to avoid side effect.
469
+ @f_value = Value.new(@f_value.type,@f_value.content.clone)
470
+ end
471
+ @f_value[index] = value
472
+ # Sets the mode
473
+ @mode = mode
474
+ end
475
+
476
+
477
+
478
+ ## Returns the name of the signal with its hierarchy.
479
+ def fullname
480
+ @fullname ||= self.parent.fullname + ":" + self.name.to_s
481
+ return @fullname
482
+ end
483
+
484
+ end
485
+
486
+ ##
487
+ # Describes a signal.
488
+ class SignalI
489
+ include SimSignal
490
+ end
491
+
492
+ ##
493
+ # Describes a constant signal.
494
+ class SignalC
495
+ include SimSignal
496
+ end
497
+
498
+
499
+ ##
500
+ # Describes a system instance.
501
+ #
502
+ # NOTE: an instance can actually represented muliple layers
503
+ # of systems, the first one being the one actually instantiated
504
+ # in the final RTL code.
505
+ # This layering can be used for describing software or partial
506
+ # (re)configuration.
507
+ class SystemI
508
+ ## Initialize the simulation for system +systemT+.
509
+ def init_sim(systemT)
510
+ # Recurse on the Eigen system.
511
+ self.systemT.init_sim(systemT)
512
+ end
513
+ end
514
+
515
+
516
+ ##
517
+ # Describes a non-HDLRuby code chunk.
518
+ class Chunk
519
+ # TODO
520
+ end
521
+
522
+
523
+ ##
524
+ # Decribes a set of non-HDLRuby code chunks.
525
+ class Code
526
+ # TODO
527
+ end
528
+
529
+
530
+ ##
531
+ # Describes a statement.
532
+ #
533
+ # NOTE: this is an abstract class which is not to be used directly.
534
+ class Statement
535
+ ## Initialize the simulation for system +systemT+.
536
+ def init_sim(systemT)
537
+ raise "init_sim must be implemented in class #{self.class}"
538
+ end
539
+
540
+ ## Executes the statement in +mode+ (:blocking or :nonblocking)
541
+ # NOTE: to be overrided.
542
+ def execute(mode)
543
+ raise "execute must be implemented in class #{self.class}"
544
+ end
545
+ end
546
+
547
+
548
+ ##
549
+ # Decribes a transmission statement.
550
+ class Transmit
551
+ ## Initialize the simulation for system +systemT+.
552
+ def init_sim(systemT)
553
+ self.left.init_sim(systemT)
554
+ end
555
+
556
+ ## Executes the statement.
557
+ def execute(mode)
558
+ self.left.assign(mode,self.right.execute(mode))
559
+ end
560
+ end
561
+
562
+
563
+ ##
564
+ # Describes an if statement.
565
+ class If
566
+ ## Initialize the simulation for system +systemT+.
567
+ def init_sim(systemT)
568
+ self.yes.init_sim(systemT)
569
+ self.each_noif { |cond,stmnt| stmnt.init_sim(systemT) }
570
+ self.no.init_sim(systemT) if self.no
571
+ end
572
+
573
+ ## Executes the statement.
574
+ def execute(mode)
575
+ # Check the main condition.
576
+ if !(self.condition.execute(mode).zero?) then
577
+ self.yes.execute(mode)
578
+ else
579
+ # Check the other conditions (elsif)
580
+ success = false
581
+ self.each_noif do |cond,stmnt|
582
+ if !(cond.execute(mode).zero?) then
583
+ stmnt.execute(mode)
584
+ success = true
585
+ break
586
+ end
587
+ end
588
+ self.no.execute(mode) if self.no && !success
589
+ end
590
+ end
591
+ end
592
+
593
+
594
+ ##
595
+ # Describes a when for a case statement.
596
+ class When
597
+ ## Initialize the simulation for system +systemT+.
598
+ def init_sim(systemT)
599
+ self.statement.init_sim(systemT)
600
+ end
601
+ end
602
+
603
+
604
+ ##
605
+ # Describes a case statement.
606
+ class Case
607
+ ## Initialize the simulation for system +systemT+.
608
+ def init_sim(systemT)
609
+ self.each_when { |wh| wh.init_sim(systemT) }
610
+ self.default.init_sim(systemT)
611
+ end
612
+
613
+ ## Executes the statement.
614
+ def execute(mode)
615
+ unless self.each_when.find do |wh|
616
+ if wh.match.eql?(self.value.execute(mode)) then
617
+ wh.statement.execute(mode)
618
+ return
619
+ end
620
+ end
621
+ self.default.execute(mode)
622
+ end
623
+ end
624
+ end
625
+
626
+
627
+ ##
628
+ # Describes a delay: not synthesizable.
629
+ class Delay
630
+ ## Get the time of the delay in pico seconds.
631
+ def time_ps
632
+ case self.unit
633
+ when :ps
634
+ return self.value.to_i
635
+ when :ns
636
+ return self.value.to_i * 1000
637
+ when :us
638
+ return self.value.to_i * 1000000
639
+ when :ms
640
+ return self.value.to_i * 1000000000
641
+ when :s
642
+ return self.value.to_i * 1000000000000
643
+ end
644
+ end
645
+ end
646
+
647
+
648
+ ##
649
+ # Describes a print statement: not synthesizable!
650
+ class Print
651
+ ## Initialize the simulation for system +systemT+.
652
+ def init_sim(systemT)
653
+ @sim = systemT
654
+ end
655
+
656
+ ## Executes the statement.
657
+ def execute(mode)
658
+ self.each_arg.map do |arg|
659
+ case arg
660
+ when StringE
661
+ @sim.show_string(arg.content)
662
+ when SignalI
663
+ @sim.show_signal(arg)
664
+ when SignalC
665
+ @sim.show_signal(arg)
666
+ else
667
+ @sim.show_value(arg.execute(mode))
668
+ end
669
+ end
670
+ end
671
+ end
672
+
673
+
674
+ ##
675
+ # Describes a system instance (re)configuration statement: not synthesizable!
676
+ class Configure
677
+ ## TODO
678
+ end
679
+
680
+
681
+ ##
682
+ # Describes a wait statement: not synthesizable!
683
+ class TimeWait
684
+ ## Initialize the simulation for system +systemT+.
685
+ def init_sim(systemT)
686
+ @sim = systemT
687
+ end
688
+
689
+ ## Executes the statement.
690
+ def execute(mode)
691
+ @behavior ||= self.behavior
692
+ @behavior.time += self.delay.time_ps
693
+ # puts "Stopping #{@behavior.object_id} (@behavior.time=#{@behavior.time})..."
694
+ @sim.run_done(@behavior.id)
695
+ # puts "Rerunning #{@behavior.object_id} (@behavior.time=#{@behavior.time})..."
696
+ @sim.run_req(@behavior.id)
697
+ end
698
+ end
699
+
700
+
701
+ ##
702
+ # Describes a timed loop statement: not synthesizable!
703
+ class TimeRepeat
704
+ ## Deprecated
705
+ end
706
+
707
+
708
+ ##
709
+ # Describes a timed terminate statement: not synthesizable!
710
+ class TimeTerminate
711
+ ## Initialize the simulation for system +systemT+.
712
+ def init_sim(systemT)
713
+ @sim = systemT
714
+ end
715
+
716
+ ## Executes the statement.
717
+ def execute(mode)
718
+ # @behavior ||= self.get_behavior
719
+ # @behavior.terminate
720
+ exit
721
+ end
722
+ end
723
+
724
+
725
+ ##
726
+ # Describes a block.
727
+ class Block
728
+ ## Initialize the simulation for system +systemT+.
729
+ def init_sim(systemT)
730
+ # Recurse on the inner signals.
731
+ self.each_inner { |sig| sig.init_sim(systemT) }
732
+ # Recurde on the statements.
733
+ self.each_statement { |stmnt| stmnt.init_sim(systemT) }
734
+ end
735
+
736
+ ## Executes the statement.
737
+ def execute(mode)
738
+ self.each_statement { |stmnt| stmnt.execute(self.mode) }
739
+ end
740
+
741
+ ## Returns the name of the signal with its hierarchy.
742
+ def fullname
743
+ @fullname ||= self.parent.fullname + ":" + self.name.to_s
744
+ return @fullname
745
+ end
746
+ end
747
+
748
+ # Describes a timed block.
749
+ #
750
+ # NOTE:
751
+ # * this is the only kind of block that can include time statements.
752
+ # * this kind of block is not synthesizable!
753
+ class TimeBlock
754
+ ## Initialize the simulation for system +systemT+.
755
+ def init_sim(systemT)
756
+ self.each_statement { |stmnt| stmnt.init_sim(systemT) }
757
+ end
758
+
759
+ ## Executes the statement.
760
+ def execute(mode)
761
+ # puts "TimeBlock"
762
+ self.each_statement do |stmnt|
763
+ # puts "Going to execute statement: #{stmnt}"
764
+ stmnt.execute(self.mode)
765
+ end
766
+ # puts "End TimeBlock"
767
+ end
768
+ end
769
+
770
+
771
+ ##
772
+ # Describes a connection.
773
+ class Connection
774
+
775
+ ## Initialize the simulation for system +systemT+.
776
+ def init_sim(systemT)
777
+ # Recurse on the left.
778
+ self.left.init_sim(systemT)
779
+ # Process the sensitivity list.
780
+ # Is it a clocked behavior?
781
+ events = []
782
+ # Generate the events list from the right values.
783
+ # First get the references.
784
+ refs = self.right.each_node_deep.select do |node|
785
+ node.is_a?(RefObject) && !node.parent.is_a?(RefObject)
786
+ end.to_a
787
+ # Keep only one ref per signal.
788
+ refs.uniq! { |node| node.fullname }
789
+ # # Generate the event.
790
+ # events = refs.map {|ref| Event.new(:anyedge,ref) }
791
+ # # Add them to the behavior for further processing.
792
+ # events.each {|event| self.add_event(event) }
793
+ # Now process the events: add the connection to the corresponding
794
+ # activation list of the signals of the events.
795
+ refs.each {|ref| ref.object.add_anyedge(self) }
796
+ end
797
+
798
+ ## Executes the statement.
799
+ def execute(mode)
800
+ # puts "connection = #{self}"
801
+ self.left.assign(mode,self.right.execute(mode))
802
+ end
803
+ end
804
+
805
+
806
+
807
+ ##
808
+ # Describes an expression.
809
+ #
810
+ # NOTE: this is an abstract class which is not to be used directly.
811
+ class Expression
812
+ ## Executes the expression in +mode+ (:blocking or :nonblocking)
813
+ # NOTE: to be overrided.
814
+ def execute(mode)
815
+ raise "execute must be implemented in class #{self.class}"
816
+ end
817
+ end
818
+
819
+
820
+ ##
821
+ # Describes a value.
822
+ class Value
823
+ # include Vprocess
824
+
825
+ ## Executes the expression.
826
+ def execute(mode)
827
+ return self
828
+ end
829
+ end
830
+
831
+
832
+ ##
833
+ # Describes a cast.
834
+ class Cast
835
+ ## Executes the expression.
836
+ def execute(mode)
837
+ # Recurse on the child.
838
+ # res = tocast.execute(mode)
839
+ # Shall we reverse the content of a concat.
840
+ if self.child.is_a?(Concat) &&
841
+ self.type.direction != self.child.type.direction then
842
+ # Yes, do it.
843
+ res = self.child.execute(mode,:reverse)
844
+ else
845
+ res = self.child.execute(mode)
846
+ end
847
+ # Cast it.
848
+ res = res.cast(self.type,true)
849
+ # Returns the result.
850
+ return res
851
+ end
852
+ end
853
+
854
+
855
+ ##
856
+ # Describes an operation.
857
+ #
858
+ # NOTE: this is an abstract class which is not to be used directly.
859
+ class Operation
860
+ ## Left to the children.
861
+ end
862
+
863
+
864
+ ##
865
+ # Describes an unary operation.
866
+ class Unary
867
+ ## Execute the expression.
868
+ def execute(mode)
869
+ # puts "Unary with operator=#{self.operator}"
870
+ # Recurse on the child.
871
+ tmp = self.child.execute(mode)
872
+ # puts "tmp=#{tmp}"
873
+ # Apply the operator.
874
+ return tmp.send(self.operator)
875
+ end
876
+ end
877
+
878
+
879
+ ##
880
+ # Describes an binary operation.
881
+ class Binary
882
+ ## Execute the expression.
883
+ def execute(mode)
884
+ # Recurse on the children.
885
+ tmpl = self.left.execute(mode)
886
+ tmpr = self.right.execute(mode)
887
+ # Apply the operator.
888
+ return tmpl.send(self.operator,tmpr)
889
+ end
890
+ end
891
+
892
+
893
+ ##
894
+ # Describes a selection operation (generalization of the ternary operator).
895
+ #
896
+ # NOTE: choice is using the value of +select+ as an index.
897
+ class Select
898
+ ## Execute the expression.
899
+ def execute(mode)
900
+ # Recurse on the select.
901
+ tmps = self.select.execute(mode)
902
+ # Recurse on the selection result.
903
+ return @choices[tmps.to_i].execute(mode)
904
+ end
905
+ end
906
+
907
+
908
+ ##
909
+ # Describes a concatenation expression.
910
+ class Concat
911
+ ## Execute the expression.
912
+ def execute(mode, reverse=false)
913
+ # Recurse on the children.
914
+ tmpe = self.each_expression.map { |expr| expr.execute(mode) }
915
+ # Ensure the order of the elements matches the type.
916
+ if (self.type.direction == :little && !reverse) ||
917
+ (self.type.direction == :big && reverse) then
918
+ tmpe.reverse!
919
+ end
920
+ # puts "concat result=#{Vprocess.concat(*tmpe).to_bstr}"
921
+ # Concatenate the result.
922
+ return Vprocess.concat(*tmpe)
923
+ end
924
+ end
925
+
926
+
927
+ ##
928
+ # Describes a reference expression.
929
+ #
930
+ # NOTE: this is an abstract class which is not to be used directly.
931
+ class Ref
932
+ ## Initialize the simulation for system +systemT+.
933
+ def init_sim(systemT)
934
+ raise "assign must be implemented in class #{self.class}"
935
+ end
936
+
937
+ ## Assigns +value+ to the reference.
938
+ # Must be overriden.
939
+ def assign(mode,value)
940
+ raise "assign must be implemented in class #{self.class}"
941
+ end
942
+
943
+ ## Assigns +value+ at +index+ (integer or range).
944
+ def assign_at(mode,value,index)
945
+ raise "assign_at must be implemented in class #{self.class}"
946
+ end
947
+ end
948
+
949
+
950
+ ##
951
+ # Describes concatenation reference.
952
+ class RefConcat
953
+ ## Initialize the simulation for system +systemT+.
954
+ def init_sim(systemT)
955
+ self.each_ref { |ref| ref.init_sim(systemT) }
956
+ end
957
+
958
+ ## Execute the expression.
959
+ def execute(mode)
960
+ # Recurse on the children.
961
+ tmpe = self.each_ref.map { |ref| ref.execute(mode) }
962
+ # Concatenate the result.
963
+ return tmpe.reduce(:concat)
964
+ end
965
+
966
+ ## Assigns +value+ the the reference.
967
+ def assign(mode,value)
968
+ # puts "self.type=#{self.type}"
969
+ # Flatten the value type.
970
+ value.type = [value.type.width].to_type
971
+ pos = 0
972
+ width = 0
973
+ # Recurse on the children.
974
+ @refs.reverse_each do |ref|
975
+ # puts "ref.type=#{ref.type}"
976
+ width = ref.type.width
977
+ # puts "pos=#{pos} width=#{width}, pos+width-1=#{pos+width-1}"
978
+ # puts "value.content=#{value.content}"
979
+ # puts "value[(pos+width-1).to_expr..pos.to_expr].content=#{value[(pos+width-1).to_expr..pos.to_expr].content}"
980
+ ref.assign(mode,value[(pos+width-1).to_expr..pos.to_expr])
981
+ # Prepare for the next reference.
982
+ pos += width
983
+ end
984
+ end
985
+
986
+ ## Assigns +value+ at +index+ (integer or range).
987
+ def assign_at(mode,value,index)
988
+ # Get the refered value.
989
+ refv = self.execute(mode,value)
990
+ # Assign to it.
991
+ refv.assign_at(mode,value,index)
992
+ # Update the reference.
993
+ self.assign(mode,refv)
994
+ end
995
+ end
996
+
997
+
998
+ ##
999
+ # Describes a index reference.
1000
+ class RefIndex
1001
+ ## Initialize the simulation for system +systemT+.
1002
+ def init_sim(systemT)
1003
+ self.ref.init_sim(systemT)
1004
+ end
1005
+
1006
+ ## Execute the expression.
1007
+ def execute(mode)
1008
+ # Recurse on the children.
1009
+ tmpr = self.ref.execute(mode)
1010
+ idx = self.index.execute(mode)
1011
+ # puts "tmpr=#{tmpr} idx=#{idx} tmpr[idx]=#{tmpr[idx]}"
1012
+ return tmpr[idx]
1013
+ end
1014
+
1015
+ ## Assigns +value+ the the reference.
1016
+ def assign(mode,value)
1017
+ # Compute the index.
1018
+ idx = self.index.execute(mode).to_i
1019
+ # Assigns.
1020
+ self.ref.assign_at(mode,value,idx)
1021
+ end
1022
+
1023
+ ## Assigns +value+ at +index+ (integer or range).
1024
+ def assign_at(mode,value,index)
1025
+ # Get the refered value.
1026
+ refv = self.execute(mode)
1027
+ # Assign to it.
1028
+ refv = refv.assign_at(mode,value,index)
1029
+ # Update the refered value.
1030
+ self.assign(mode,refv)
1031
+ end
1032
+
1033
+ end
1034
+
1035
+
1036
+ ##
1037
+ # Describes a range reference.
1038
+ class RefRange
1039
+ ## Initialize the simulation for system +systemT+.
1040
+ def init_sim(systemT)
1041
+ self.ref.init_sim(systemT)
1042
+ end
1043
+
1044
+ ## Execute the expression.
1045
+ def execute(mode)
1046
+ # Recurse on the children.
1047
+ tmpr = self.ref.execute(mode)
1048
+ rng = (self.range.first.execute(mode))..
1049
+ (self.range.last.execute(mode))
1050
+ # puts "tmpr=#{tmpr} rng=#{rng} tmpr[rng]=#{tmpr[rng]}"
1051
+ return tmpr[rng]
1052
+ end
1053
+
1054
+ ## Assigns +value+ the the reference.
1055
+ def assign(mode,value)
1056
+ # Compute the index range.
1057
+ rng = (self.range.first.execute(mode).to_i)..
1058
+ (self.range.last.execute(mode).to_i)
1059
+ # Assigns.
1060
+ self.ref.assign_at(mode,value,rng)
1061
+ end
1062
+
1063
+ ## Assigns +value+ at +index+ (integer or range).
1064
+ def assign_at(mode,value,index)
1065
+ # Get the refered value.
1066
+ refv = self.execute(mode)
1067
+ # Assign to it.
1068
+ refv = refv.assign_at(mode,value,index)
1069
+ # Update the refered value.
1070
+ self.assign(mode,refv)
1071
+ end
1072
+ end
1073
+
1074
+
1075
+ ##
1076
+ # Describes a name reference.
1077
+ class RefName
1078
+ # Not used?
1079
+ end
1080
+
1081
+
1082
+ ##
1083
+ # Describe a this reference.
1084
+ #
1085
+ # This is the current system.
1086
+ class RefThis
1087
+ # Not used.
1088
+ end
1089
+
1090
+
1091
+ ##
1092
+ # Describes a high-level object reference: no low-level equivalent!
1093
+ class RefObject
1094
+ ## Initialize the simulation for system +systemT+.
1095
+ def init_sim(systemT)
1096
+ @sim = systemT
1097
+ end
1098
+
1099
+ ## Execute the expression.
1100
+ def execute(mode)
1101
+ return self.object.execute(mode)
1102
+ end
1103
+
1104
+ ## Assigns +value+ the the reference.
1105
+ def assign(mode,value)
1106
+ self.object.assign(mode,value)
1107
+ # puts "name=#{self.object.name} value=#{value.to_vstr}"
1108
+ # puts "c_value=#{self.object.c_value.content}" if self.object.c_value
1109
+ # puts "f_value=#{self.object.f_value.content}" if self.object.f_value
1110
+ if !(self.object.c_value.eql?(self.object.f_value)) then
1111
+ @sim.add_sig_active(self.object)
1112
+ end
1113
+ end
1114
+
1115
+ ## Assigns +value+ at +index+ (integer or range).
1116
+ def assign_at(mode,value,index)
1117
+ # puts "name=#{self.object.name} value=#{value.to_vstr}"
1118
+ self.object.assign_at(mode,value,index)
1119
+ # puts "c_value=#{self.object.c_value.content}" if self.object.c_value
1120
+ # puts "f_value=#{self.object.f_value.content}" if self.object.f_value
1121
+ if !(self.object.c_value.eql?(self.object.f_value)) then
1122
+ @sim.add_sig_active(self.object)
1123
+ end
1124
+ end
1125
+ end
1126
+
1127
+
1128
+ ##
1129
+ # Describes a string.
1130
+ #
1131
+ # NOTE: This is not synthesizable!
1132
+ class StringE
1133
+ end
1134
+ end