HDLRuby 3.7.2 → 3.7.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c6e130a54f880c57186b29328c125d603604f4da1f25a5c4f890549a9847782
4
- data.tar.gz: 19256d21296a7662f6241c27b41a969c0bb411c64084d8e48e740950c84867ac
3
+ metadata.gz: ab26bbb8abf18f4655b96e3db5109c32495edff20c80bf9e00522583b909bf91
4
+ data.tar.gz: e5434d17932f1aa1f4af983a88d53e3a38e7f38dfb91bf4233e5733fb07da36a
5
5
  SHA512:
6
- metadata.gz: c6069997b2fbeb1acf6a4202e72fa6558060283de21d2ed2ea6a8ef72032f7c54166788346e03b4b4ba79d3c8cf0565edd3bee945b4c736907210b35b97d8331
7
- data.tar.gz: be5e84ac24bd4df32e1a6a83fe37a294c9f17475de7c12bb8a40e96d944fb63f2e94556ea9cb6b954d82e81ff03fa44e9550dcd6cba349dc7d7b263e3808dece
6
+ metadata.gz: b3e62cf9f604e98b32a46b4b74fd7b82caf083f72baf25da70ebbdd941f65ac94645be9e3ed636e25ff3bf01e2d347f9700e4a294b70e630f61f2f875b2b5f5a
7
+ data.tar.gz: a9c531751ca079b4cd98c249d2b1a56c753482233e5d21dfba0b3a4a86f8063f516d31743c34f2f4181320bcee86d9703a20b6ef2b38c1013ab60b1cc69e5aab
data/README.md CHANGED
@@ -17,6 +17,10 @@ hdrcc --get-tuto
17
17
 
18
18
  __What's new__
19
19
 
20
+ For HDLRuby version 3.7.3:
21
+
22
+ * Added the possibility to use software sequencers inside HDLRuby's program construct, and use within them program ports like they were input or output signals.
23
+
20
24
  For HDLRuby version 3.7.2:
21
25
 
22
26
  * Added the `text` command for the sequencers in software.
@@ -3981,6 +3985,29 @@ sequencer do
3981
3985
  end
3982
3986
  ```
3983
3987
 
3988
+ #### Using Software Sequencer Inside a HDLRuby program.
3989
+
3990
+ HDLRuby supports hardware/software co-design through the `program` [construct](#declaring-a-software-component). Since software sequencers are software components, they can be used within this construct when the selected language is Ruby, however the command `activate_sequencer_sw(binding)` must be inserted in the first line of the Ruby code. Software sequencers can also be used with the C language, but in that case, the corresponding C code must first be generated.
3991
+
3992
+ For Ruby, software sequencer signals can be automatically connected to the ports of the program construct by declaring them as input signals for `inport` and output signals for `outport`. For example, the following code describes a software sequencer that echoes the value from the input port `inP` to the output port `outP` (`sig0` and `sig1` are signals from the upper RTL design).
3993
+
3994
+ ```ruby
3995
+ program(:ruby) do
3996
+ actport clk.posedge
3997
+ inport inP: sig0
3998
+ outport outP: sig1
3999
+ code do
4000
+ activate_sequencer_sw(binding)
4001
+ input :inP
4002
+ output :outP
4003
+ sequencer do
4004
+ outP <= inP
4005
+ end
4006
+ end
4007
+ end
4008
+ ```
4009
+
4010
+
3984
4011
 
3985
4012
  ## Fixed-point (fixpoint): `std/fixpoint.rb`
3986
4013
  <a name="fixpoint"></a>
@@ -1682,7 +1682,7 @@ VALUE rcsim_transmit_fixnum_to_signal(VALUE mod, VALUE signalV, VALUE valR) {
1682
1682
  /* Get the C signal from the Ruby value. */
1683
1683
  SignalI signal;
1684
1684
  value_to_rcsim(SignalIS,signalV,signal);
1685
- /* Compute the simualtion value from valR. */
1685
+ /* Compute the simulation value from valR. */
1686
1686
  Value value = get_value();
1687
1687
  value->type = signal->type;
1688
1688
  value->numeric = 1;
@@ -1699,7 +1699,7 @@ VALUE rcsim_transmit_fixnum_to_signal_seq(VALUE mod, VALUE signalV, VALUE valR)
1699
1699
  /* Get the C signal from the Ruby value. */
1700
1700
  SignalI signal;
1701
1701
  value_to_rcsim(SignalIS,signalV,signal);
1702
- /* Compute the simualtion value from valR. */
1702
+ /* Compute the simulation value from valR. */
1703
1703
  Value value = get_value();
1704
1704
  value->type = signal->type;
1705
1705
  value->numeric = 1;
@@ -1711,6 +1711,49 @@ VALUE rcsim_transmit_fixnum_to_signal_seq(VALUE mod, VALUE signalV, VALUE valR)
1711
1711
  }
1712
1712
 
1713
1713
 
1714
+ /** Reads an elements of a C signal array at an index and returns
1715
+ * the result as a Ruby fixnum.
1716
+ * Sets 0 if the value contains x or z bits. */
1717
+ VALUE rcsim_read_index_fixnum(VALUE mod, VALUE signalV, VALUE idxV) {
1718
+ Value value = get_value();
1719
+ /* Get the C signal from the Ruby value. */
1720
+ SignalI signal;
1721
+ value_to_rcsim(SignalIS,signalV,signal);
1722
+ /* Get its base type.*/
1723
+ Type base = get_type_vector(get_type_bit(),signal->type->base);
1724
+ /* Get the index. */
1725
+ unsigned long long idx = FIX2LONG(idxV);
1726
+ /* Access the value. */
1727
+ read_range(signal->c_value,idx,idx,base,value);
1728
+ /* Get the value from the signal. */
1729
+ return LONG2FIX(value2integer(value));
1730
+ }
1731
+
1732
+ /** Transmit a Ruby fixnum inside a C signal array at an index in
1733
+ * a blocking fashion.
1734
+ * NOTE: the simulator events are updated. */
1735
+ VALUE rcsim_write_index_fixnum_seq(VALUE mod, VALUE signalV, VALUE idxV, VALUE valR) {
1736
+ /* Get the C signal from the Ruby value. */
1737
+ SignalI signal;
1738
+ value_to_rcsim(SignalIS,signalV,signal);
1739
+ // /* Get its base type.*/
1740
+ // Type base = get_type_vector(get_type_bit(),signal->type->base);
1741
+ /* Get the index. */
1742
+ unsigned long long idx = FIX2LONG(idxV);
1743
+ /* Compute the simulation value from valR. */
1744
+ Value value = get_value();
1745
+ value->type = signal->type;
1746
+ value->numeric = 1;
1747
+ value->data_int = FIX2LONG(valR);
1748
+ /* Transmit it. */
1749
+ transmit_to_signal_range_num_seq(value, signal, idx,idx);
1750
+ /* End, return the transmitted expression. */
1751
+ return valR;
1752
+ }
1753
+
1754
+
1755
+
1756
+
1714
1757
  // /** Execute a behavior. */
1715
1758
  // VALUE rcsim_execute_behavior(VALUE mod, VALUE behaviorV) {
1716
1759
  // /* Get the behavior. */
@@ -1900,6 +1943,8 @@ void Init_hruby_sim() {
1900
1943
  /* The Ruby software interface. */
1901
1944
  rb_define_singleton_method(mod,"rcsim_get_signal_fixnum",rcsim_get_signal_fixnum,1);
1902
1945
  rb_define_singleton_method(mod,"rcsim_transmit_fixnum_to_signal_seq",rcsim_transmit_fixnum_to_signal_seq,2);
1946
+ rb_define_singleton_method(mod,"rcsim_read_index_fixnum",rcsim_read_index_fixnum,2);
1947
+ rb_define_singleton_method(mod,"rcsim_write_index_fixnum_seq",rcsim_write_index_fixnum_seq,3);
1903
1948
  // rb_define_singleton_method(mod,"rcsim_execute_behavior",rcsim_execute_behavior,1);
1904
1949
 
1905
1950
  }
@@ -901,6 +901,14 @@ extern void transmit_to_signal_seq(Value value, SignalI signal);
901
901
  * value to. */
902
902
  extern void transmit_to_signal_range_seq(Value value, RefRangeS ref);
903
903
 
904
+ /** Transmit a value to a range within a signal in case of sequential
905
+ * execution model.
906
+ * @param value the value to transmit
907
+ * @param ref the reference to the range in the signal to transmit the
908
+ * value to. */
909
+ extern void transmit_to_signal_range_num_seq(Value value, SignalI signal,
910
+ unsigned long long first, unsigned long long last);
911
+
904
912
  /** Creates an event.
905
913
  * @param edge the edge of the event
906
914
  * @param signal the signal of the event */
@@ -2449,7 +2449,7 @@ static int same_content_value_range_numeric(Value value0,
2449
2449
  Value read_range_numeric(Value value,
2450
2450
  unsigned long long first, unsigned long long last,
2451
2451
  Type base, Value dst) {
2452
- /* printf("read_range_numeric with value=%llx and first=%llu and last=%llu\n",value->data_int,first,last); */
2452
+ // printf("read_range_numeric with value=%llx and first=%llu and last=%llu\n",value->data_int,first,last);
2453
2453
  /* Ensure first is the smaller. */
2454
2454
  if (first > last) {
2455
2455
  long long tmp = last;
@@ -2465,7 +2465,7 @@ Value read_range_numeric(Value value,
2465
2465
  first *= bw;
2466
2466
  last *= bw;
2467
2467
  length *= bw;
2468
- /* printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length); */
2468
+ // printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length); */
2469
2469
 
2470
2470
  /* Set the type and size of the destination from the type of the source.*/
2471
2471
  dst->type = make_type_vector(get_type_bit(),length);
@@ -3427,6 +3427,7 @@ unsigned long long value2integer(Value value) {
3427
3427
  Value read_range(Value value,
3428
3428
  unsigned long long first, unsigned long long last,
3429
3429
  Type base, Value dst) {
3430
+ // printf("Read range with first=%d, last=%d\n",first,last);
3430
3431
  /* Is the value numeric? */
3431
3432
  if (value->numeric) {
3432
3433
  /* Yes, do a numeric range read. */
@@ -735,18 +735,35 @@ void transmit_to_signal_seq(Value value, SignalI signal) {
735
735
  * @param value the value to transmit
736
736
  * @param ref the reference to the range in the signal to transmit the
737
737
  * value to. */
738
+ void transmit_to_signal_range_num_seq(Value value, SignalI signal,
739
+ unsigned long long first, unsigned long long last) {
740
+ // printf("Tansmit to signal range seq: %s(%p) [%llu,%llu]\n",signal->name,signal,first,last);
741
+ /* The base type is stored here to avoid allocating a new type each time.
742
+ * It have an arbitrary base size a single element. */
743
+ static TypeS baseT = { 1, 1 };
744
+ baseT.base = signal->f_value->type->base;
745
+ // printf("Tansmit to signal range: %s(%p) [%lld:%lld]\n",signal->name,signal,first,last);
746
+ /* Can transmit, copy the content. */
747
+ if (signal->fading)
748
+ signal->f_value = write_range(value,first,last,&baseT,
749
+ signal->f_value);
750
+ else
751
+ signal->f_value = write_range_no_z(value,first,last,&baseT,
752
+ signal->f_value);
753
+ /* And touch the signal. */
754
+ touch_signal_seq(signal);
755
+ }
756
+
757
+ /** Transmit a value to a range given with by first and last values, within a signal in case of sequential
758
+ * execution model.
759
+ * @param value the value to transmit
760
+ * @param ref the reference to the range in the signal to transmit the
761
+ * value to. */
738
762
  void transmit_to_signal_range_seq(Value value, RefRangeS ref) {
739
763
  SignalI signal = ref.signal;
740
764
  unsigned long long first = ref.first;
741
765
  unsigned long long last = ref.last;
742
766
  // printf("Tansmit to signal range seq: %s(%p) [%llu,%llu]\n",signal->name,signal,first,last);
743
- // /* Can transmit, copy the content. */
744
- // if (signal->fading)
745
- // // write_range(value,first,last,signal->f_value->type,signal->f_value);
746
- // write_range(value,first,last,ref.type,signal->f_value);
747
- // else
748
- // // write_range_no_z(value,first,last,signal->f_value->type,signal->f_value);
749
- // write_range_no_z(value,first,last,ref.type,signal->f_value);
750
767
  /* The base type is stored here to avoid allocating a new type each time.
751
768
  * It have an arbitrary base size a single element. */
752
769
  static TypeS baseT = { 1, 1 };
@@ -0,0 +1,31 @@
1
+ require 'HDLRuby/std/sequencer_sw'
2
+
3
+ include RubyHDL::High
4
+ using RubyHDL::High
5
+
6
+ # Sequencer for testing arithmetic computations.
7
+
8
+ sdef(:truc) do |m,n|
9
+ sreturn(n+m*2)
10
+ end
11
+
12
+ signed[32].inner :x,:y, :result
13
+ signed[32].inner :clk
14
+
15
+ my_seq = sequencer(clk) do
16
+ x <= 0
17
+ y <= 0
18
+ 100.stimes do
19
+ x <= x + 1
20
+ 10.times do
21
+ y <= truc(x,y)
22
+ end
23
+ end
24
+ result <= y
25
+ end
26
+
27
+ puts "code=" + my_seq.source
28
+
29
+ my_seq.()
30
+
31
+ puts "result=#{result}"
@@ -0,0 +1,48 @@
1
+
2
+ # A benchmark for testing the use of Ruby software code with array ports.
3
+ system :with_ruby_prog do
4
+ inner :clk
5
+ bit[8][-8].inner ar: [ _h00, _h01, _h04, _h09, _h10, _h19, _h24, _h31 ]
6
+
7
+ program(:ruby,:show) do
8
+ actport clk.posedge
9
+ arrayport arP: ar
10
+ code(proc do
11
+ def show
12
+ 8.times do |i|
13
+ val = RubyHDL.arP[i]
14
+ puts "# ar[#{i}]=#{val}"
15
+ RubyHDL.arP[i] = i+i
16
+ end
17
+ end
18
+ end)
19
+ end
20
+
21
+
22
+ timed do
23
+ clk <= 0
24
+ hprint("ar[0]=",ar[0],"\n")
25
+ hprint("ar[1]=",ar[1],"\n")
26
+ hprint("ar[2]=",ar[2],"\n")
27
+ hprint("ar[3]=",ar[3],"\n")
28
+ hprint("ar[4]=",ar[4],"\n")
29
+ hprint("ar[5]=",ar[5],"\n")
30
+ hprint("ar[6]=",ar[6],"\n")
31
+ hprint("ar[7]=",ar[7],"\n")
32
+ !10.ns
33
+ repeat(8) do
34
+ clk <= ~clk
35
+ !10.ns
36
+ end
37
+ !10.ns
38
+ hprint("ar[0]=",ar[0],"\n")
39
+ hprint("ar[1]=",ar[1],"\n")
40
+ hprint("ar[2]=",ar[2],"\n")
41
+ hprint("ar[3]=",ar[3],"\n")
42
+ hprint("ar[4]=",ar[4],"\n")
43
+ hprint("ar[5]=",ar[5],"\n")
44
+ hprint("ar[6]=",ar[6],"\n")
45
+ hprint("ar[7]=",ar[7],"\n")
46
+ !10.ns
47
+ end
48
+ end
@@ -0,0 +1,49 @@
1
+
2
+ # A benchmark for testing the use of Ruby software code including a
3
+ # sequencer.
4
+ #
5
+ system :with_ruby_prog_seq do
6
+ inner :clk
7
+ [8].inner :count, :echo
8
+
9
+ program(:ruby,:echo) do
10
+ actport clk.posedge
11
+ inport inP: count
12
+ outport outP: echo
13
+ code(proc do
14
+ activate_sequencer_sw(binding)
15
+
16
+ $my_seq = nil
17
+
18
+ def echo
19
+ unless $my_seq then
20
+ [32].input :inP
21
+ [32].output :outP
22
+ $my_seq = sequencer do
23
+ sloop do
24
+ outP <= inP
25
+ sync
26
+ end
27
+ end
28
+ end
29
+ $my_seq.()
30
+ end
31
+ end)
32
+ end
33
+
34
+
35
+ timed do
36
+ clk <= 0
37
+ count <= 0
38
+ !10.ns
39
+ repeat(10) do
40
+ clk <= 1
41
+ hprint("echo=",echo,"\n")
42
+ !10.ns
43
+ count <= count + 1
44
+ clk <= 0
45
+ !10.ns
46
+ end
47
+
48
+ end
49
+ end
@@ -2584,6 +2584,8 @@ module HDLRuby::High
2584
2584
  self.each_inport { |p| progL.add_inport(p[0],p[1].to_low) }
2585
2585
  # Add the output signals references.
2586
2586
  self.each_outport { |p| progL.add_outport(p[0],p[1].to_low) }
2587
+ # Add the array signals references.
2588
+ self.each_arrayport { |p| progL.add_arrayport(p[0],p[1].to_low) }
2587
2589
  # Return the resulting program.
2588
2590
  return progL
2589
2591
  end
@@ -2607,6 +2609,11 @@ module HDLRuby::High
2607
2609
  def outport(ports = {})
2608
2610
  ports.each { |k,v| self.add_outport(k,v) }
2609
2611
  end
2612
+
2613
+ # Adds new array ports.
2614
+ def arrayport(ports = {})
2615
+ ports.each { |k,v| self.add_arrayport(k,v) }
2616
+ end
2610
2617
  end
2611
2618
 
2612
2619
 
@@ -5555,4 +5562,20 @@ def self.configure_high
5555
5562
  def self.booting?
5556
5563
  false
5557
5564
  end
5565
+
5566
+
5567
+ end
5568
+
5569
+
5570
+
5571
+
5572
+ # Activate the software sequencer for Ruby code embedded in HDLRuby
5573
+ def activate_sequencer_sw(binding_context)
5574
+ eval <<~RUBY, binding_context
5575
+ alias require_ruby require
5576
+ require_ruby 'HDLRuby/std/sequencer_sw'
5577
+ include RubyHDL::High
5578
+ using RubyHDL::High
5579
+ RUBY
5558
5580
  end
5581
+
@@ -3019,6 +3019,7 @@ module HDLRuby::Low
3019
3019
  @codes = [] # The code files.
3020
3020
  @inports = {} # The input ports.
3021
3021
  @outports = {} # The output ports.
3022
+ @arrayports ={}# The array ports.
3022
3023
  end
3023
3024
 
3024
3025
  # Add a new activation port.
@@ -3063,6 +3064,20 @@ module HDLRuby::Low
3063
3064
  @outports[name] = sig
3064
3065
  end
3065
3066
 
3067
+ # Add a new array port.
3068
+ def add_arrayport(name, sig)
3069
+ # Ensure name is a symbol.
3070
+ unless name.is_a?(Symbol) then
3071
+ name = name.to_s.to_sym
3072
+ end
3073
+ # Ensure sig is a signal.
3074
+ unless sig.is_a?(SignalI) then
3075
+ raise AnyError, "Invalid class for a signal: #{sig.class}"
3076
+ end
3077
+ # Add the new port.
3078
+ @arrayports[name] = sig
3079
+ end
3080
+
3066
3081
 
3067
3082
  # Iterates over each activation event.
3068
3083
  #
@@ -3104,6 +3119,16 @@ module HDLRuby::Low
3104
3119
  @outports.each(&ruby_block)
3105
3120
  end
3106
3121
 
3122
+ # Iterate over each array port.
3123
+ #
3124
+ # Returns an enumerator if no ruby block is given.
3125
+ def each_arrayport(&ruby_block)
3126
+ # No block? Return an enumerator.
3127
+ return to_enum(:each_arrayport) unless ruby_block
3128
+ # A block is given, apply it.
3129
+ @arrayports.each(&ruby_block)
3130
+ end
3131
+
3107
3132
  end
3108
3133
 
3109
3134
 
@@ -572,6 +572,10 @@ module HDLRuby::High
572
572
  self.each_outport do |sym, sig|
573
573
  RubyHDL.outport(sym,sig.rcsignalI)
574
574
  end
575
+ # Add the array ports.
576
+ self.each_arrayport do |sym, sig|
577
+ RubyHDL.arrayport(sym,sig.rcsignalI)
578
+ end
575
579
  elsif self.language == :c then
576
580
  # Loads the code file: only the last one remains.
577
581
  self.each_code do |code|
@@ -601,6 +605,10 @@ module HDLRuby::High
601
605
  self.each_outport do |sym, sig|
602
606
  RCSim::CPorts[sym] = sig.rcsignalI
603
607
  end
608
+ # Add the array ports.
609
+ self.each_arrayport do |sym, sig|
610
+ RCSim::CPorts[sym] = sig.rcsignalI
611
+ end
604
612
  end
605
613
 
606
614
 
@@ -315,6 +315,11 @@ module HDLRuby::High::Std
315
315
  expr.seach.with_index(&ruby_block)
316
316
  end
317
317
 
318
+ # Does nothing: just for compatibility with the software
319
+ # implementation of sequencers.
320
+ def sync
321
+ end
322
+
318
323
  # Tell if the sequencer ends it execution.
319
324
  def alive?
320
325
  return @fsm.cur_state_sig != self.end_state_value