HDLRuby 2.10.5 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
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