HDLRuby 2.11.11 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.html +3274 -0
  3. data/README.md +608 -99
  4. data/ext/hruby_sim/hruby_rcsim_build.c +27 -0
  5. data/ext/hruby_sim/hruby_sim.h +3 -0
  6. data/ext/hruby_sim/hruby_sim_calc.c +2 -0
  7. data/ext/hruby_sim/hruby_sim_core.c +17 -5
  8. data/ext/hruby_sim/hruby_sim_stack_calc.c +1 -1
  9. data/ext/hruby_sim/hruby_sim_tree_calc.c +8 -1
  10. data/ext/hruby_sim/hruby_sim_vcd.c +24 -7
  11. data/ext/hruby_sim/hruby_sim_vizualize.c +9 -1
  12. data/lib/HDLRuby/backend/hruby_allocator.rb +2 -2
  13. data/lib/HDLRuby/backend/hruby_c_allocator.rb +7 -7
  14. data/lib/HDLRuby/hdr_samples/constant_in_function.rb +3 -1
  15. data/lib/HDLRuby/hdr_samples/counter_dff_bench.rb +3 -1
  16. data/lib/HDLRuby/hdr_samples/huge_rom.rb +1 -1
  17. data/lib/HDLRuby/hdr_samples/mei8.rb +11 -11
  18. data/lib/HDLRuby/hdr_samples/mei8_bench.rb +12 -12
  19. data/lib/HDLRuby/hdr_samples/neg_arith_bench.rb +4 -4
  20. data/lib/HDLRuby/hdr_samples/rom_nest.rb +1 -1
  21. data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +4 -4
  22. data/lib/HDLRuby/hdr_samples/struct.rb +44 -10
  23. data/lib/HDLRuby/hdr_samples/with_bram.rb +45 -0
  24. data/lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb +105 -0
  25. data/lib/HDLRuby/hdr_samples/with_bram_stack.rb +69 -0
  26. data/lib/HDLRuby/hdr_samples/with_casts.rb +3 -3
  27. data/lib/HDLRuby/hdr_samples/with_concat.rb +6 -6
  28. data/lib/HDLRuby/hdr_samples/with_connector_memory.rb +2 -2
  29. data/lib/HDLRuby/hdr_samples/with_def.rb +10 -3
  30. data/lib/HDLRuby/hdr_samples/with_define_operator.rb +44 -0
  31. data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +12 -12
  32. data/lib/HDLRuby/hdr_samples/with_init.rb +3 -3
  33. data/lib/HDLRuby/hdr_samples/with_leftright.rb +21 -0
  34. data/lib/HDLRuby/hdr_samples/with_reduce.rb +13 -13
  35. data/lib/HDLRuby/hdr_samples/with_ref_array.rb +6 -6
  36. data/lib/HDLRuby/hdr_samples/with_register_stack.rb +150 -0
  37. data/lib/HDLRuby/hdr_samples/with_sequencer.rb +190 -0
  38. data/lib/HDLRuby/hdr_samples/with_sequencer_deep.rb +91 -0
  39. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +405 -0
  40. data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +89 -0
  41. data/lib/HDLRuby/hdr_samples/with_sequencer_sync.rb +120 -0
  42. data/lib/HDLRuby/hdr_samples/with_subsums.rb +3 -3
  43. data/lib/HDLRuby/hdr_samples/with_terminate.rb +3 -3
  44. data/lib/HDLRuby/hdr_samples/with_to_a.rb +10 -10
  45. data/lib/HDLRuby/hdr_samples/with_values.rb +3 -3
  46. data/lib/HDLRuby/hdrcc.rb +29 -3
  47. data/lib/HDLRuby/hdrlib.rb +1 -1
  48. data/lib/HDLRuby/hruby_bstr.rb +10 -5
  49. data/lib/HDLRuby/hruby_db.rb +2 -2
  50. data/lib/HDLRuby/hruby_high.rb +152 -47
  51. data/lib/HDLRuby/hruby_high_fullname.rb +3 -1
  52. data/lib/HDLRuby/hruby_low.rb +189 -18
  53. data/lib/HDLRuby/hruby_low2c.rb +129 -54
  54. data/lib/HDLRuby/hruby_low2hdr.rb +66 -40
  55. data/lib/HDLRuby/hruby_low2high.rb +86 -44
  56. data/lib/HDLRuby/hruby_low2seq.rb +26 -18
  57. data/lib/HDLRuby/hruby_low2sym.rb +14 -13
  58. data/lib/HDLRuby/hruby_low2vhd.rb +80 -44
  59. data/lib/HDLRuby/hruby_low_bool2select.rb +61 -46
  60. data/lib/HDLRuby/hruby_low_casts_without_expression.rb +56 -44
  61. data/lib/HDLRuby/hruby_low_cleanup.rb +18 -16
  62. data/lib/HDLRuby/hruby_low_fix_types.rb +65 -32
  63. data/lib/HDLRuby/hruby_low_mutable.rb +83 -119
  64. data/lib/HDLRuby/hruby_low_resolve.rb +38 -30
  65. data/lib/HDLRuby/hruby_low_with_bool.rb +33 -16
  66. data/lib/HDLRuby/hruby_low_with_port.rb +3 -3
  67. data/lib/HDLRuby/hruby_low_with_var.rb +23 -9
  68. data/lib/HDLRuby/hruby_low_without_concat.rb +45 -19
  69. data/lib/HDLRuby/hruby_low_without_namespace.rb +47 -32
  70. data/lib/HDLRuby/hruby_low_without_parinseq.rb +32 -16
  71. data/lib/HDLRuby/hruby_low_without_select.rb +37 -24
  72. data/lib/HDLRuby/hruby_low_without_subsignals.rb +280 -0
  73. data/lib/HDLRuby/hruby_rcsim.rb +158 -134
  74. data/lib/HDLRuby/hruby_rsim.rb +194 -20
  75. data/lib/HDLRuby/hruby_rsim_mute.rb +2 -3
  76. data/lib/HDLRuby/hruby_rsim_vcd.rb +125 -50
  77. data/lib/HDLRuby/hruby_values.rb +48 -33
  78. data/lib/HDLRuby/hruby_verilog.rb +90 -48
  79. data/lib/HDLRuby/soft/stacks.rb +219 -0
  80. data/lib/HDLRuby/std/bram.rb +26 -0
  81. data/lib/HDLRuby/std/clocks.rb +1 -1
  82. data/lib/HDLRuby/std/fixpoint.rb +2 -2
  83. data/lib/HDLRuby/std/fsm.rb +48 -11
  84. data/lib/HDLRuby/std/function_generator.rb +2 -2
  85. data/lib/HDLRuby/std/sequencer.rb +1857 -0
  86. data/lib/HDLRuby/std/sequencer_sync.rb +400 -0
  87. data/lib/HDLRuby/std/std.rb +12 -0
  88. data/lib/HDLRuby/version.rb +1 -1
  89. data/tuto/adder_sat_flags_vcd.png +0 -0
  90. data/tuto/addsub_vcd.png +0 -0
  91. data/tuto/alu_vcd.png +0 -0
  92. data/tuto/bit_pong_vcd.png +0 -0
  93. data/tuto/checksum_vcd.png +0 -0
  94. data/tuto/circuit_hdr.odg +0 -0
  95. data/tuto/circuit_hdr.png +0 -0
  96. data/tuto/circuit_hie.odg +0 -0
  97. data/tuto/circuit_hie.png +0 -0
  98. data/tuto/circuit_view.odg +0 -0
  99. data/tuto/circuit_view.png +0 -0
  100. data/tuto/clock_counter_vcd.png +0 -0
  101. data/tuto/counter_ext_vcd.png +0 -0
  102. data/tuto/fact_vcd.png +0 -0
  103. data/tuto/hw_flow.odg +0 -0
  104. data/tuto/hw_flow.png +0 -0
  105. data/tuto/maxxer_vcd.png +0 -0
  106. data/tuto/pingpong0_vcd.png +0 -0
  107. data/tuto/pingpong1_vcd.png +0 -0
  108. data/tuto/pingpong2_vcd.png +0 -0
  109. data/tuto/ram_vcd.png +0 -0
  110. data/tuto/serializer_vcd.png +0 -0
  111. data/tuto/sw_flow.odg +0 -0
  112. data/tuto/sw_flow.png +0 -0
  113. data/tuto/the_counter_vcd.png +0 -0
  114. data/tuto/tutorial_sw.html +2359 -0
  115. data/tuto/tutorial_sw.md +2684 -0
  116. data/tuto/tutorial_sw.pdf +0 -0
  117. data/tuto/tutorial_sw_jp.md +417 -0
  118. metadata +49 -3
  119. data/lib/HDLRuby/hdr_samples/sumprod.rb +0 -29
data/README.md CHANGED
@@ -3,6 +3,25 @@
3
3
  HDLRuby is a library for describing and simulating digital electronic
4
4
  systems.
5
5
 
6
+ __Note__:
7
+
8
+ If you are new to HDLRuby, it is recommended that you consult first the following tutorial (even if you are a hardware person):
9
+
10
+ * [HDLRuby tutorial for software people](tuto/tutorial_sw.md)
11
+
12
+ __What's new__
13
+
14
+ For HDLRuby version 3.0.0:
15
+
16
+ * This section;
17
+
18
+ * [The sequencers](#sequencer-software-like-hardware-coding-stdsequencerrb) for software-like hardware design;
19
+
20
+ * A [tutorial](tuto/tutorial_sw.md) for software people;
21
+
22
+ * The stable [standard libraries](#standard-libraries) are loaded by default.
23
+
24
+
6
25
  __Install__:
7
26
 
8
27
  The recommended installation method is from rubygem as follows:
@@ -20,14 +39,14 @@ git clone HDLRuby
20
39
  __Warning__:
21
40
 
22
41
  - This is still preliminary work which may change before we release a stable version.
23
- - It is highly recommended to have both basic knowledges of the Ruby language and hardware description languages before using HDLRuby.
42
+ - It is highly recommended to have both basic knowledge of the Ruby language and hardware description languages before using HDLRuby.
24
43
 
25
44
 
26
45
  # Compiling HDLRuby descriptions
27
46
 
28
47
  ## Using the HDLRuby compiler
29
48
 
30
- 'hdrcc' is the HDLRuby compiler. It takes as input an HDLRuby file, checks it, and can produce as output a Verilog HDL, VHDL, or a YAML low-level descriptions of HW components but it can also simulate the input description.
49
+ 'hdrcc' is the HDLRuby compiler. It takes as input an HDLRuby file, checks it, and can produce as output a Verilog HDL, VHDL, or a YAML low-level description of HW components but it can also simulate the input description.
31
50
 
32
51
 
33
52
  __Usage__:
@@ -49,68 +68,76 @@ Where:
49
68
  | `-v, --verilog` | Output in Verilog HDL format |
50
69
  | `-V, --vhdl` | Output in VHDL format |
51
70
  | `-s, --syntax` | Output the Ruby syntax tree |
52
- | `-C, --clang` | Output the C code of the standalone simulator. |
53
- | `-S, --sim` | Perform the simulation with the default engine. |
54
- | `--csim` | Perform the simulation with the standalone engine. |
55
- | `--rsim` | Perform the simulation with the Ruby engine. |
56
- | `--rcsim` | Perform the simulation with the Hybris engine. |
71
+ | `-C, --clang` | Output the C code of the standalone simulator |
72
+ | `-S, --sim` | Perform the simulation with the default engine |
73
+ | `--csim` | Perform the simulation with the standalone engine |
74
+ | `--rsim` | Perform the simulation with the Ruby engine |
75
+ | `--rcsim` | Perform the simulation with the Hybris engine |
57
76
  | `--vcd` | Make the simulator generate a VCD file |
58
77
  | `-d, --directory` | Specify the base directory for loading the HDLRuby files |
59
78
  | `-D, --debug` | Set the HDLRuby debug mode |
60
79
  | `-t, --top system`| Specify the top system describing the circuit to compile |
61
80
  | `-p, --param x,y,z` | Specify the generic parameters |
62
- | `--version ` | Print the version number, then exit |
81
+ | `--get-samples` | Copy the sample directory (hdr_samples) to current one, then exit |
82
+ | `--version` | Show the version number, then exit |
63
83
  | `-h, --help` | Show the help message |
64
84
 
65
85
  __Notes__:
66
86
 
67
87
  * If no top system is given, it is automatically looked for from the input file.
68
88
  * If no option is given, it simply checks the input file.
69
- * The simulator option (-S) requires a standard compiler (accessible through the command `cc`) to be available in the executable path.
89
+ * If you are new to HDLRuby, or if you want to see how new features work, we strongly encourage to get a local copy of the test HDLRuby sample using:
90
+
91
+ ```bash
92
+ hdrcc --get-samples
93
+ ```
94
+
95
+ Then in your current directory (folder) the `hdr_samples` subdirectory will appear that contains several HDLRuby example files. For details about the samples can be found there: [samples](#sample-hdlruby-descriptions).
96
+
70
97
 
71
98
  __Examples__:
72
99
 
73
100
  * Compile system named `adder` from `adder.rb` input file and generate a low-level YAML description into directory `adder`:
74
101
 
75
- ```
102
+ ```bash
76
103
  hdrcc --yaml --top adder adder.rb adder
77
104
  ```
78
105
 
79
106
  * Compile `adder.rb` input file and generate a low-level Verilog HDL description into directory `adder`:
80
107
 
81
- ```
108
+ ```bash
82
109
  hdrcc -v adder.rb adder
83
110
  ```
84
111
 
85
112
  * Compile system `adder` whose bit width is generic from `adder_gen.rb` input file to a 16-bit circuit low-level VHDL description into directory `adder`:
86
113
 
87
- ```
114
+ ```bash
88
115
  hdrcc -V -t adder --param 16 adder_gen.rb adder
89
116
  ```
90
117
 
91
118
  * Compile system `multer` with inputs and output bit width is generic from `multer_gen.rb` input file to a 16x16->32-bit circuit whose low-level YAML description into directory `multer`:
92
119
 
93
- ```
120
+ ```bash
94
121
  hdrcc -y -t multer -p 16,16,32 multer_gen.rb multer
95
122
  ```
96
123
 
97
- * Simulate the circuit described in file `counter_bench.rb` using the default simluation engine and putting the simulator's files in directory `counter`:
124
+ * Simulate the circuit described in file `counter_bench.rb` using the default simulation engine and putting the simulator's files in directory `counter`:
98
125
 
99
- ```
126
+ ```bash
100
127
  hdrcc -S counter_bench.rb counter
101
128
  ```
102
129
 
103
- As a policy, the default simulation enigne is set to the fastest one (cuttently it is the hybrid engine).
130
+ As a policy, the default simulation engine is set to the fastest one (currently it is the hybrid engine).
104
131
 
105
132
  * Run in interactive mode.
106
133
 
107
- ```
134
+ ```bash
108
135
  hdrcc -I
109
136
  ```
110
137
 
111
138
  * Run in interactive mode using pry as UI.
112
139
 
113
- ```
140
+ ```bash
114
141
  hdrcc -I pry
115
142
  ```
116
143
 
@@ -166,13 +193,13 @@ The second specificity of HDLRuby is that it supports natively all the features
166
193
 
167
194
  __Notes__:
168
195
 
169
- - It is still possible to extend HDLRuby to support hardware descriptions of a higher level than RTL, please refer to section [Extending HDLRuby](#extend) for more details.
196
+ - It is still possible to extend HDLRuby to support hardware descriptions of a higher level than RTL, please refer to section [Extending HDLRuby](#extending-hdlruby) for more details.
170
197
  - In this document, HDLRuby constructs will often be compared to their Verilog HDL or VHDL equivalents for simpler explanations.
171
198
 
172
199
  ## Introduction
173
200
 
174
201
  This introduction gives a glimpse of the possibilities of the language.
175
- However, we do recommend consulting the section about the [high-level programming features](#highfeat) to have a more complete view of the advanced possibilities of this language.
202
+ However, we do recommend consulting the section about the [high-level programming features](#high-level-programming-features) to have a more complete view of the advanced possibilities of this language.
176
203
 
177
204
  At first glance, HDLRuby appears like any other HDL (like Verilog HDL or VHDL), for instance, the following code describes a simple D-FF:
178
205
 
@@ -187,7 +214,7 @@ system :dff do
187
214
  end
188
215
  ```
189
216
 
190
- As it can be seen in the code above, `system` is the keyword used for describing a digital circuit. This keyword is an equivalent of the Verilog HDL `module`. In such a system, signals are declared using a `<type>.<direction>` construct where `type` is the data type of the signal (e.g., `bit` as in the code above) and `direction` indicates if the signal is an input, an output, an inout or an inner one; and executable blocks (similar to `always` block of Verilog HDL) are described using the `par` keyword when they are parallel and `seq` when they are sequential (i.e., with respectively non-blocking and blocking assignments).
217
+ As can be seen in the code above, `system` is the keyword used for describing a digital circuit. This keyword is the equivalent of the Verilog HDL `module`. In such a system, signals are declared using a `<type>.<direction>` construct where `type` is the data type of the signal (e.g., `bit` as in the code above) and `direction` indicates if the signal is an input, an output, an inout or an inner one; and executable blocks (similar to `always` block of Verilog HDL) are described using the `par` keyword when they are parallel and `seq` when they are sequential (i.e., with respectively non-blocking and blocking assignments).
191
218
 
192
219
  After such a system has been defined, it can be instantiated. For example, a single instance of the `dff` system named `dff0` can be declared as follows:
193
220
 
@@ -195,7 +222,7 @@ After such a system has been defined, it can be instantiated. For example, a sin
195
222
  dff :dff0
196
223
  ```
197
224
 
198
- The ports of this instance can then be accessed to be used like any other signals, e.g., `dff0.d` for access the `d` input of the FF.
225
+ The ports of this instance can then be accessed to be used like any other signals, e.g., `dff0.d` for accessing the `d` input of the FF.
199
226
 
200
227
  Several instances can also be declared in a single statement. For example, a 2-bit counter based on the previous `dff` circuits can be described as follows:
201
228
 
@@ -230,7 +257,7 @@ system :counter2 do
230
257
  end
231
258
  ```
232
259
 
233
- In the code above, two possible connection methods are shown: for `dff0` ports are connected by name, and for `dff1` ports are connected by declaration order. Please notice that it is also possible to connect only a subset of the ports while declaring and to reconnect already connected ports in further statements.
260
+ In the code above, two possible connection methods are shown: for `dff0` ports are connected by name, and for `dff1` ports are connected by declaration order. Please notice that it is also possible to connect only a subset of the ports while declaring, and to reconnect already connected ports in further statements.
234
261
 
235
262
  While a circuit can be generated from the code given above, a benchmark must
236
263
  be provided to test it. Such a benchmark is described by constructs called
@@ -285,8 +312,7 @@ end
285
312
  ```
286
313
 
287
314
  Then, it often happens that a system will end up with only one instance.
288
- In such a case, the system declaration can be omitted and an instance
289
- can be directly declared as follows:
315
+ In such a case, the system declaration can be omitted, and an instance can be directly declared as follows:
290
316
 
291
317
  ```ruby
292
318
  instance :dff_single do
@@ -395,7 +421,7 @@ system :shifter do |n|
395
421
  end
396
422
  ```
397
423
 
398
- As it can be seen in the above examples, in HDLRuby, any construct is an object and therefore include methods. For instance, declaring a signal of a given `type` and direction (input, output, or inout) is done as follows so that `direction` is a method of the type, and the signal names are the arguments of this method (symbols or string are supported.)
424
+ As can be seen in the above examples, in HDLRuby, any construct is an object and therefore include methods. For instance, declaring a signal of a given `type` and direction (input, output, or inout) is done as follows so that `direction` is a method of the type, and the signal names are the arguments of this method (symbols or string are supported.)
399
425
 
400
426
  ```ruby
401
427
  <type>.<direction> <list of symbols representing the signal>
@@ -430,14 +456,14 @@ system :sumprod_16_3456 do
430
456
  end
431
457
  ```
432
458
 
433
- The description above is straightforward, but it would be necessary to rewrite it if another circuit with different bit width or coefficients is to be designed. Moreover, if the number of coefficients is large an error in the expression will be easy to make and hard to find. A better approach would be to use a generic description of such a circuit as follows:
459
+ The description above is straightforward, but it would be necessary to rewrite it if another circuit with different bit widths or coefficients is to be designed. Moreover, if the number of coefficients is large an error in the expression will be easy to make and hard to find. A better approach would be to use a generic description of such a circuit as follows:
434
460
 
435
461
  ```ruby
436
462
  system :sumprod do |typ,coefs|
437
463
  typ[coefs.size].input :ins
438
464
  typ.output :o
439
465
 
440
- o <= coefs.each_with_index.reduce(_0) do |sum,(coef,i)|
466
+ o <= coefs.each_with_index.reduce(_b0) do |sum,(coef,i)|
441
467
  sum + ins[i]*coef
442
468
  end
443
469
  end
@@ -446,7 +472,7 @@ end
446
472
  In the code above, there are two generic parameters,
447
473
  `typ`, which indicates the data type of the circuit, and `coefs`, which is assumed to be an array of coefficients. Since the number of inputs depends on the number of provided coefficients, it is declared as an array of `width` bit signed whose size is equal to the number of coefficients.
448
474
 
449
- The description of the sum of products may be more difficult to understand for people not familiar with the Ruby language. The `each_with_index` method iterates over the coefficients adding their index as iteration variable, the resulting operation (i.e., the iteration loop) is then modified by the `reduce` method that accumulates the code passed as arguments. This code, starting by `|sum,coef,i|` simply performs the addition of the current accumulation result (`sum`) with the product of the current coefficient (`coef`) and input (`ins[i]`, where `i` is the index) in the iteration. The argument `_0` initializes the sum to `0`.
475
+ The description of the sum of products may be more difficult to understand for people not familiar with the Ruby language. The `each_with_index` method iterates over the coefficients adding their index as an iteration variable, the resulting operation (i.e., the iteration loop) is then modified by the `reduce` method that accumulates the code passed as arguments. This code, starting by `|sum,coef,i|` simply performs the addition of the current accumulation result (`sum`) with the product of the current coefficient (`coef`) and input (`ins[i]`, where `i` is the index) in the iteration. The argument `_b0` initializes the sum to `0`.
450
476
 
451
477
  While slightly longer than the previous description, this description allows declaring a circuit implementing a sum of products with any bit width and any number of coefficients. For instance, the following code describes a signed 32-bit sum of products with 16 coefficients (just random numbers here).
452
478
 
@@ -456,14 +482,14 @@ sumprod(signed[32], [3,78,43,246, 3,67,1,8, 47,82,99,13, 5,77,2,4]).(:my_circuit
456
482
 
457
483
  As seen in the code above, when passing a generic argument for instantiating a generic system, the name of the instance is put between brackets for avoiding confusion.
458
484
 
459
- While the description `sumprod` is already usable in a wide range of cases, it still uses the standard addition and multiplication. However, there are cases where specific components are to be used for these operations, either for sake of performance, compliance with constraints, or because functionally different operations are required (e.g., saturated computations). This can be solved by using functions implementing such computation in place of operators, for example as follows:
485
+ While the description `sumprod` is already usable in a wide range of cases, it still uses standard addition and multiplication. However, there are cases where specific components are to be used for these operations, either for sake of performance, compliance with constraints, or because functionally different operations are required (e.g., saturated computations). This can be solved by using functions implementing such computation in place of operators, for example as follows:
460
486
 
461
487
  ```ruby
462
488
  system :sumprod_func do |typ,coefs|
463
489
  typ[coefs.size].input ins
464
490
  typ.output :o
465
491
 
466
- o <= coefs.each_with_index.reduce(_0) do
492
+ o <= coefs.each_with_index.reduce(_b0) do
467
493
  |sum,(coef,i)|
468
494
  add(sum, mult(ins[i]*coef))
469
495
  end
@@ -502,14 +528,14 @@ end
502
528
 
503
529
  It would however be necessary to add this argument when invoking the function, e.g., `add(1000,sum,mult(...))`. While this argument is relevant for addition with saturation, it is not for the other kind of addition operations, and hence, the code of `sumprod` is not general-purpose any longer.
504
530
 
505
- HDLRuby provides two ways to address such issues. First, it is possible to pass code as an argument. In the case of `sumprod` it would then be enough to add two arguments that perform the required addition and multiplication. The example is below:
531
+ HDLRuby provides two ways to address such issues. First, it is possible to pass code as an argument. In the case of `sumprod`, it would then be enough to add two arguments that perform the required addition and multiplication. The example is below:
506
532
 
507
533
  ```ruby
508
534
  system :sumprod_proc do |add,mult,typ,coefs|
509
535
  typ[coefs.size].input ins
510
536
  typ.output :o
511
537
 
512
- o <= coefs.each_with_index.reduce(_0) do
538
+ o <= coefs.each_with_index.reduce(_b0) do
513
539
  |sum,(coef,i)|
514
540
  add.(sum, mult.(ins[i]*coef))
515
541
  end
@@ -539,10 +565,8 @@ A second possible approach provided by HDLRuby is to declare a new data type wit
539
565
  signed[16].typedef(:sat16_1000)
540
566
 
541
567
  sat16_1000.define_operator(:+) do |x,y|
542
- [16].inner :res
543
- seq do
544
- res <= x + y
545
- ( res <= 1000 ).hif(res > 1000)
568
+ tmp = x + y
569
+ mux(tmp > 1000,tmp,1000)
546
570
  end
547
571
  end
548
572
  ```
@@ -565,10 +589,8 @@ end
565
589
 
566
590
 
567
591
  sat.define_operator(:+) do |width,max, x,y|
568
- [width].inner :res
569
- seq do
570
- res <= x + y
571
- ( res <= max ).hif(res > max)
592
+ tmp = x + y
593
+ mux(tmp > max, tmp, max)
572
594
  end
573
595
  end
574
596
  ```
@@ -629,10 +651,10 @@ From there, we will describe in more detail each construct of HDLRuby.
629
651
  ## Naming rules
630
652
  <a name="names"></a>
631
653
 
632
- Several constructs in HDLRuby are referred to by name, e.g., systems and signals. When such constructs are declared, their names are to be specified by Ruby symbols starting with a lower case. For example, `:hello` is a valid name declaration, but `:Hello` is not.
654
+ Several constructs in HDLRuby are referred to by name, e.g., systems and signals. When such constructs are declared, their names are to be specified by Ruby symbols starting with a lowercase. For example, `:hello` is a valid name declaration, but `:Hello` is not.
633
655
 
634
656
  After being declared, the construct can be referred to by using the name directly (i.e., without the `:` of Ruby symbols). For example, if a construct
635
- has been declared with `:hello` as name, it will be afterward referred to by `hello`.
657
+ has been declared with `:hello` as the name, it will be afterward referred to by `hello`.
636
658
 
637
659
  ## Systems and signals
638
660
 
@@ -654,7 +676,7 @@ __Notes__:
654
676
  Ruby keywords (in which case the parentheses can be omitted) are as follows:
655
677
 
656
678
  ```ruby
657
- system :box do
679
+ system :box does
658
680
  end
659
681
  ```
660
682
 
@@ -925,7 +947,7 @@ Where:
925
947
  * `<name>` is the name of the scope.
926
948
  * `<code>` is the code within the scope.
927
949
 
928
- Contrary to the case of scopes without a name, signals and instances declared within a named scope can be accessed outside using this name as a reference. For example, in the code below signal `sig` declared within scope named `scop` is accessed outside it using `scop.sig`:
950
+ Contrary to the case of scopes without a name, signals, and instances declared within a named scope can be accessed outside using this name as a reference. For example, in the code below signal `sig` declared within scope named `scop` is accessed outside it using `scop.sig`:
929
951
 
930
952
  ```ruby
931
953
  sub :scop do
@@ -952,7 +974,7 @@ end
952
974
  In addition, it is possible to declare inner signals within an execution block.
953
975
  While such signals will be physically linked to the system, they are only accessible within the block they are declared into. This permits a tighter scope for signals, which improves the readability of the code and make it possible to declare several signals with identical names provided their respective scopes are different.
954
976
 
955
- An event represents a specific change of state of a signal.
977
+ An event represents a specific change in the state of a signal.
956
978
  For example, a rising edge of a clock signal named `clk` will be represented by the event `clk.posedge`. In HDLRuby, events are obtained directly from
957
979
  expressions using the following methods: `posedge` for a rising edge, `negedge` for a falling edge, and `edge` for any edge.
958
980
  Events are described in more detail in section [Events](#events).
@@ -993,7 +1015,7 @@ system :with_sequential_behavior do
993
1015
  end
994
1016
  ```
995
1017
 
996
- A sub-block can also have a different execution mode if it is declared using `seq`, which will force sequential execution mode, and `par` which will force parallel execution mode. For example, in the following code a parallel sub-block is declared within a sequential one:
1018
+ A sub-block can also have a different execution mode if it is declared using `seq`, which will force sequential execution mode and `par` which will force parallel execution mode. For example, in the following code a parallel sub-block is declared within a sequential one:
997
1019
 
998
1020
  ```ruby
999
1021
  system :with_sequential_behavior do
@@ -1006,7 +1028,7 @@ system :with_sequential_behavior do
1006
1028
  end
1007
1029
  ```
1008
1030
 
1009
- Sub blocks have their scope so that it is possible to declare signals without colliding with existing ones. For example, it is possible to
1031
+ Sunblocks have their scope so that it is possible to declare signals without colliding with existing ones. For example, it is possible to
1010
1032
  declare three different inner signals all called `sig` as follows:
1011
1033
 
1012
1034
  ```ruby
@@ -1121,7 +1143,7 @@ unshift do
1121
1143
  end
1122
1144
  ```
1123
1145
 
1124
- For example the following code inserts two statements at the beginning of the current block:
1146
+ For example, the following code inserts two statements at the beginning of the current block:
1125
1147
 
1126
1148
  ```ruby
1127
1149
  par do
@@ -1133,7 +1155,7 @@ par do
1133
1155
  end
1134
1156
  ```
1135
1157
 
1136
- The code above will actually result in the following block:
1158
+ The code above will result in the following block:
1137
1159
 
1138
1160
  ```ruby
1139
1161
  par do
@@ -1155,7 +1177,7 @@ In HDLRuby, dynamically reconfigurable devices are modeled by instances having m
1155
1177
  <instance>.choice(<list of named systems>)
1156
1178
  ```
1157
1179
 
1158
- For example, assuming systems `sys0`, `sys1` and `sys2` have been previously declared a device named `dev012` able to be reconfigured to one of these three systems would be declared as follows (the connections of the instance, omitted in the example, can be done as usual):
1180
+ For example, assuming systems `sys0`, `sys1`, and `sys2` have been previously declared a device named `dev012` able to be reconfigured to one of these three systems would be declared as follows (the connections of the instance, omitted in the example, can be done as usual):
1159
1181
 
1160
1182
  ```ruby
1161
1183
  sys0 :dev012 # dev012 is at first a standard instance of sys0
@@ -1187,9 +1209,8 @@ These reconfiguration commands are treated as regular RTL statements in HDLRuby
1187
1209
 
1188
1210
 
1189
1211
  ## Events
1190
- <a name="events"></a>
1191
1212
 
1192
- Each behavior of a system is associated with a list of events, called a sensitivity list, that specifies when the behavior is to be executed. An event is associated with a signal and represents the instants when the signal reaches a given state.
1213
+ Each behavior of a system is associated with a list of events, called a sensitivity list, that specifies when the behavior is to be executed. An event is associated with a signal and represents the instant when the signal reaches a given state.
1193
1214
 
1194
1215
  There are three kinds of events: positive edge events represent the instants when their corresponding signals vary from 0 to 1, and negative edge events
1195
1216
  represent the instants when their corresponding signals vary from 1 to 0 and the change events represent the instants when their corresponding signals vary.
@@ -1215,7 +1236,6 @@ __Note:__
1215
1236
  - The `change` keyword can be omitted.
1216
1237
 
1217
1238
  ## Statements
1218
- <a name="statements"></a>
1219
1239
 
1220
1240
  Statements are the basic elements of a behavioral description. They are regrouped in blocks that specify their execution mode (parallel or sequential).
1221
1241
  There are four kinds of statements: the transmit statement which computes expressions and sends the result to the target signals, the control statement
@@ -1228,7 +1248,7 @@ __Note__:
1228
1248
 
1229
1249
  ### Transmit statement
1230
1250
 
1231
- A transmit statement is declared using the arrow operator `<=` within a behavior. Its right value is the expression to compute and its left value is a reference to the target signals (or parts of signals), i.e., the signals (or part of signals) that receive the computation result.
1251
+ A transmit statement is declared using the arrow operator `<=` within a behavior. Its right value is the expression to compute and its left value is a reference to the target signals (or parts of signals), i.e., the signals (or parts of signals) that receive the computation result.
1232
1252
 
1233
1253
  For example, the following code transmits the value `3` to signal `s0` and the sum of the values of signals `i0` and `i1` to the first four bits of signal `s1`:
1234
1254
 
@@ -1286,7 +1306,7 @@ end
1286
1306
 
1287
1307
  ### helsif
1288
1308
 
1289
- In addition to `helse` it is possible to set additional conditions to an `hif` using the `helsif` keyword as follows:
1309
+ In addition to `helse`, it is possible to set additional conditions to an `hif` using the `helsif` keyword as follows:
1290
1310
 
1291
1311
  ```ruby
1292
1312
  hif <condition 0> do
@@ -1420,13 +1440,12 @@ While the underlying structure of any HDLRuby type is the bit vector, complex ty
1420
1440
  <a name="expressions"></a>
1421
1441
 
1422
1442
  Expressions are any construct that represents a value associated with a type.
1423
- They include [immediate values](#values), [reference to signals](#references) and operations among other expressions using [expression operators](#operators).
1443
+ They include [immediate values](#immediate-values), [reference to signals](#references) and operations among other expressions using [expression operators](#expression-operators).
1424
1444
 
1425
1445
 
1426
1446
  ### Immediate values
1427
- <a name="values"></a>
1428
1447
 
1429
- The immediate values of HDLRuby can represent vectors of `bit`, `unsigned`, and `signed`, and integer or floating-point numbers. They are prefixed by a `_` character and include a header that indicates the vector type and the base used for representing the value, followed by a numeral representing the value. The bit width of a value is obtained by default from the width of the numeral, but it is also possible to enforce it in the header.
1448
+ The immediate values of HDLRuby can represent vectors of `bit`, `unsigned`, and `signed`, and integer or floating-point numbers. They are prefixed by a `_` character and include a header that indicates the vector type and the base used for representing the value, followed by a numeral representing the value. The bit width of a value is obtained by default from the width of the numeral, but it is also possible to specify it in the header. In addition, the character `_` can be put anywhere in the number for increasing the readability, it will be ignored.
1430
1449
 
1431
1450
  The vector type specifiers are the followings:
1432
1451
 
@@ -1438,7 +1457,7 @@ The vector type specifiers are the followings:
1438
1457
 
1439
1458
  The base specifiers are the followings:
1440
1459
 
1441
- - `b`: binary, can be omitted,
1460
+ - `b`: binary,
1442
1461
 
1443
1462
  - `o`: octal,
1444
1463
 
@@ -1446,21 +1465,30 @@ The base specifiers are the followings:
1446
1465
 
1447
1466
  - `h`: hexadecimal.
1448
1467
 
1449
- For example, all the following immediate values represent an 8-bit `100` (either in unsigned or signed representation):
1468
+ For example, all the following immediate values represent an 8-bit `hundred` (either in unsigned or signed representation):
1450
1469
 
1451
1470
  ```ruby
1452
1471
  _bb01100100
1453
- _b8b1100100
1472
+ _b8b110_0100
1454
1473
  _b01100100
1455
- _01100100
1456
1474
  _u8d100
1457
1475
  _s8d100
1458
1476
  _uh64
1459
1477
  _s8o144
1460
1478
  ```
1461
1479
 
1480
+ Finally, it is possible to omit either the type specifier, the default being unsigned bit, or the base specifier, the default being binary. For example, all the following immediate values represent an 8-bit unsigned `hundred`:
1481
+
1482
+ ```ruby
1483
+ _b01100100
1484
+ _h64
1485
+ _o144
1486
+ ```
1487
+
1462
1488
  __Notes__:
1463
1489
 
1490
+ - `_01100100` used to be considered as equivalent to `_b01100100`, however due to compatibility troubles with recent version of Ruby it is considered deprecated.
1491
+
1464
1492
  - Ruby immediate values can also be used, their bit width is automatically adjusted to match the data type of the expression they are used in. Please notice this adjusting may change the value of the immediate, for example, the following code will set `sig` to 4 instead of 100:
1465
1493
 
1466
1494
  ```ruby
@@ -1470,7 +1498,6 @@ __Notes__:
1470
1498
 
1471
1499
 
1472
1500
  ### References
1473
- <a name="references"></a>
1474
1501
 
1475
1502
  References are expressions used to designate signals or a part of signals.
1476
1503
 
@@ -1512,7 +1539,6 @@ end
1512
1539
  ```
1513
1540
 
1514
1541
  ### Expression operators
1515
- <a name="operators"></a>
1516
1542
 
1517
1543
  The following table gives a summary of the operators available in HDLRuby.
1518
1544
  More details are given for each group of operators in the subsequent sections.
@@ -1589,10 +1615,9 @@ __Notes__:
1589
1615
 
1590
1616
  - The operator precedence is the one of Ruby.
1591
1617
 
1592
- - Ruby does not allow to override the `&&`, the `||` and the `?:` operators so that they are not present in HDLRuby. Instead of the `?:` operator, HDLRuby provides the more general multiplex operator `mux`. However, HDLRuby does not provide any replacement for the `&&` and the `||` operators, please refer to section [Logic operators](#logic) for a justification about this issue.
1618
+ - Ruby does not allow to override the `&&`, the `||` and the `?:` operators so that they are not present in HDLRuby. Instead of the `?:` operator, HDLRuby provides the more general multiplex operator `mux`. However, HDLRuby does not provide any replacement for the `&&` and the `||` operators, please refer to section [Logic operators](#logic-and-shift-operators) for a justification about this issue.
1593
1619
 
1594
1620
  #### Assignment operators
1595
- <a name="assignment"></a>
1596
1621
 
1597
1622
  The assignment operators can be used with any type. They are the connection and the transmission operators both being represented by `<=`.
1598
1623
 
@@ -1620,7 +1645,6 @@ __Notes__:
1620
1645
 
1621
1646
 
1622
1647
  #### Logic and shift operators
1623
- <a name="logic"></a>
1624
1648
 
1625
1649
  In HDLRuby, the logic operators are all bitwise. For performing Boolean computations, it is necessary to use single-bit values. The bitwise logic binary operators are `&`, `|`, and `^`, and the unary one is `~`. They have the same meaning as their Ruby equivalents.
1626
1650
 
@@ -1646,11 +1670,10 @@ sig.rl(3)
1646
1670
  ```
1647
1671
 
1648
1672
  It is possible to perform other kinds of shifts or rotations using the selection and the concatenation operators. Please refer to section [Concatenation and
1649
- selection operators](#concat) for more details about these operators.
1673
+ selection operators](#concatenation-and-selection-operators) for more details about these operators.
1650
1674
 
1651
1675
 
1652
1676
  #### Conversion operators
1653
- <a name="conversion"></a>
1654
1677
 
1655
1678
  The conversion operators are used to change the type of an expression.
1656
1679
  There are two kinds of such operators: the type pun that does not change the raw value of the expression and the type cast that changes the raw value.
@@ -1662,7 +1685,7 @@ The type puns include `to_bit`, `to_unsigned` and `to_signed` that convert expre
1662
1685
  sig.to_bit <= _b01010011
1663
1686
  ```
1664
1687
 
1665
- The type casts change both the type and the value and are used to adjust the width of the types. They can only be applied to vectors of `bit`, `signed`, or `unsinged` and can only increase the bit width (bit width can be truncated using the selection operator, please refer to the [next section](#concat)).
1688
+ The type casts change both the type and the value and are used to adjust the width of the types. They can only be applied to vectors of `bit`, `signed`, or `unsinged` and can only increase the bit width (bit width can be truncated using the selection operator, please refer to the next section).
1666
1689
  These operators comprise the bit width conversions: `ljust`, `rjust`, `zext` and `sext`.
1667
1690
 
1668
1691
  More precisely, the bit width conversions operate as follows:
@@ -1696,7 +1719,6 @@ More precisely, the bit width conversions operate as follows:
1696
1719
 
1697
1720
 
1698
1721
  #### Concatenation and selection operators
1699
- <a name="concat"></a>
1700
1722
 
1701
1723
  Concatenation and selection are done using the `[]` operator as follows:
1702
1724
 
@@ -1907,7 +1929,6 @@ Ruby functions can be compared to the macros of the C languages: they are more f
1907
1929
 
1908
1930
 
1909
1931
  ## Time
1910
- <a name="time"></a>
1911
1932
 
1912
1933
  ### Time values
1913
1934
  <a name="time_val"></a>
@@ -1982,7 +2003,6 @@ sequential blocks. The execution semantic is the following:
1982
2003
 
1983
2004
 
1984
2005
  ## High-level programming features
1985
- <a name="highfeat"></a>
1986
2006
 
1987
2007
  ### Using Ruby in HDLRuby
1988
2008
 
@@ -2309,7 +2329,7 @@ Where:
2309
2329
  * `type` is the type from which the operation is overloaded.
2310
2330
  * `op` is the operator that is overloaded (e.g., `+`)
2311
2331
  * `args` are the arguments of the operation.
2312
- * `operation description` is an HDLRuby description of the new operation.
2332
+ * `operation description` is an HDLRuby expression of the new operation.
2313
2333
 
2314
2334
  For example, for `fix32` a 32-bit (decimal point at 16-bit) fixed-point type defined as follows:
2315
2335
 
@@ -2520,7 +2540,6 @@ When describing a system, it is possible to disconnect or completely undefine a
2520
2540
 
2521
2541
 
2522
2542
  ## Extending HDLRuby
2523
- <a name="extend"></a>
2524
2543
 
2525
2544
  Like any Ruby classes, the constructs of HDLRuby can be dynamically extended. If it is not recommended to change their internal structure, it is possible to add methods to them for an extension.
2526
2545
 
@@ -2648,8 +2667,7 @@ This way, calling directly `to_low` will automatically use `my_generation`.
2648
2667
 
2649
2668
 
2650
2669
 
2651
- # Standard library
2652
- <a name="library"></a>
2670
+ # Standard libraries
2653
2671
 
2654
2672
  The standard libraries are included in the module `Std`.
2655
2673
  They can be loaded as follows, where `<library name>` is the name of the
@@ -2665,9 +2683,23 @@ After the libraries are loaded, the module `Std` must be included as follows:
2665
2683
  include HDLRuby::High::Std
2666
2684
  ```
2667
2685
 
2686
+ > However, `hdrcc` does load the stable components of the standard library by default, so that you do not need to require nor include anything more to use them. In the current version, the stable components are the followings:
2687
+
2688
+ - `std/clocks.rb`
2689
+
2690
+ - `std/fixpoint.rb`
2691
+
2692
+ - `std/decoder.rb`
2693
+
2694
+ - `std/fsm.rb`
2668
2695
 
2696
+ - `std/sequencer.rb`
2669
2697
 
2670
- ## Clocks
2698
+ - `std/sequencer_sync.rb`
2699
+
2700
+
2701
+
2702
+ ## Clocks: `std/clocks.rb`
2671
2703
  <a name="clocks"></a>
2672
2704
 
2673
2705
  The `clocks` library provides utilities for easier handling of clock synchronizations.
@@ -2689,7 +2721,7 @@ end
2689
2721
 
2690
2722
  __Note__: this library does generate all the RTL code for the circuit handling the division of the frequency.
2691
2723
 
2692
- ## Counters
2724
+ ## Counters: `std/counters.rb`
2693
2725
  <a name="counters"></a>
2694
2726
 
2695
2727
  This library provides two new constructs for implementing synthesizable wait statements.
@@ -2706,12 +2738,12 @@ Where:
2706
2738
  * `<clock>` is the clock to use, this argument can be omitted.
2707
2739
  * `<reset>` is the signal used to reset the counter used for waiting, this argument can be omitted.
2708
2740
 
2709
- This statement can be used either inside or outside a clocked behavior. When used within a clocked behavior, the clock event of the behavior is used for the counter unless specified otherwise. When used outside such a behavior, the clock is the global default clock `$clk`. In both cases, the reset is the global reset `$rst` unless specified otherwise.
2741
+ This statement can be used either inside or outside a clocked behavior. When used within a clocked behavior, the clock event of the behavior is used for the counter unless specified otherwise. When used outside such behavior, the clock is the global default clock `$clk`. In both cases, the reset is the global reset `$rst` unless specified otherwise.
2710
2742
 
2711
2743
  The second construct is the `before` statement that activates a block until a given number of clock cycles is passed. Its syntax and usage are identical to the `after` statement.
2712
2744
 
2713
2745
 
2714
- ## Decoder
2746
+ ## Decoder: `std/decoder.rb`
2715
2747
  <a name="decoder"></a>
2716
2748
 
2717
2749
  This library provides a new set of control statements for easily describing an instruction decoder.
@@ -2728,7 +2760,7 @@ Where `signal` is the signal to decode and `block` is a procedure block (i.e., R
2728
2760
  entry(<pattern>) <block>
2729
2761
  ```
2730
2762
 
2731
- Where `pattern` is a string describing the pattern to match for the entry, and `block` is a procedure block describing the actions (some HDLRuby code) that are performed when the entry matches. The string describing the pattern can include `0` and `1` characters for specifying a specific value for the corresponding bit, or any alphabetical character for specifying a field in the pattern. The fields in the pattern can then be used by name in the block describing the action. When a letter is used several times within a pattern, the corresponding bits are concatenated and are used as a signal multi-bit signal in the block.
2763
+ Where `pattern` is a string describing the pattern to match the entry, and `block` is a procedure block describing the actions (some HDLRuby code) that are performed when the entry matches. The string describing the pattern can include `0` and `1` characters for specifying a specific value for the corresponding bit, or any alphabetical character for specifying a field in the pattern. The fields in the pattern can then be used by name in the block describing the action. When a letter is used several times within a pattern, the corresponding bits are concatenated and are used as a signal multi-bit signal in the block.
2732
2764
 
2733
2765
  For example, the following code describes a decoder for signal `ir` with two entries, the first one computing the sum of fields `x` and `y` and assigning the result to signal `s` and the second one computing the sum of fields `x` `y` and `z` and assigning the result to signal `s`:
2734
2766
 
@@ -2741,12 +2773,12 @@ end
2741
2773
 
2742
2774
  It can be noticed for field `z` in the example above that the bits are not required to be contiguous.
2743
2775
 
2744
- ## FSM
2776
+ ## FSM: `std/fsm.rb`
2745
2777
  <a name="fsm"></a>
2746
2778
 
2747
2779
  This library provides a new set of control statements for easily describing a finite state machine (FSM).
2748
2780
 
2749
- A finite state machine can be declared anywhere provided it is outside a behavior using the `fsm` keyword as follows:
2781
+ A finite state machine can be declared anywhere in a system provided it is outside a behavior using the `fsm` keyword as follows:
2750
2782
 
2751
2783
  ```ruby
2752
2784
  fsm(<event>,<reset>,<mode>) <block>
@@ -2789,7 +2821,7 @@ goto(cond,:st_a,:st_b,:st_c)
2789
2821
 
2790
2822
  Several goto statements can be used, the last one having priority provided it is taken (i.e., its condition corresponds to one of the target states). If no goto is taken, the next transition is the next declared one.
2791
2823
 
2792
- For example, the following code describes a FSM describing a circuit that checks if two buttons (`but_a` and `but_b`) are pressed and released in sequence for activating an output signal (`ok`):
2824
+ For example, the following code describes an FSM describing a circuit that checks if two buttons (`but_a` and `but_b`) are pressed and released in sequence for activating an output signal (`ok`):
2793
2825
 
2794
2826
  ```ruby
2795
2827
  fsm(clk.posedge,rst,:sync) do
@@ -2813,8 +2845,481 @@ fsm(clk.posedge,rst,:sync) do
2813
2845
  end
2814
2846
  ```
2815
2847
 
2848
+ __Note__: the goto statements act globally, i.e., they are independent of the place where they are declared within the state. For example for both following statements, the next state will always be `st_a` whatever `cond` maybe:
2849
+
2850
+ ```ruby
2851
+ state(:st_0) do
2852
+ goto(:st_a)
2853
+ end
2854
+ state(:st_1) do
2855
+ hif(cond) { goto(:st_a) }
2856
+ end
2857
+ ```
2858
+
2859
+ That is to say, for a conditional `goto` for `st_1` the code should have been written as follows:
2860
+
2861
+ ```ruby
2862
+ state(:st_1) do
2863
+ goto(cond,:st_a)
2864
+ end
2865
+ ```
2866
+
2867
+ The use of `goto` makes the design of FSM shorter for a majority of the cases, be sometimes, a finer control is required. For that purpose, it is also possible to configure the FSM is `static` mode where the `next_state` statement that indicates implicitly the next state. Putting in static mode is done by passing `:static` as an argument when declaring the FSM. For example, the following FSM uses `next_state` to specify explicitly the next states depending on some condition signals `cond0` and `cond1`:
2868
+
2869
+ ```ruby
2870
+ fsm(clk.posedge,rst,:static)
2871
+ state(:st_0) do
2872
+ next_state(:st_1)
2873
+ state(:st_1) do
2874
+ hif(cond) { next_state(:st_1) }
2875
+ helse { next_state(:st_0) }
2876
+ end
2877
+ end
2878
+ ```
2879
+
2880
+ ## Sequencer (software-like hardware coding):: `std/sequencer.rb`
2881
+ <a name="sequencer"></a>
2882
+
2883
+ This library provides a new set of control statements for describing the behavior of a circuit. Behind the curtain, these constructs build a finite state machine where states are deduced from the control points within the description.
2884
+
2885
+ A sequencer can be declared anywhere in a system provided it is outside a behavior using the `sequencer` keyword as follows:
2886
+
2887
+ ```ruby
2888
+ sequencer(<clock>,<start>) <block>
2889
+ ```
2890
+
2891
+ Where `clock` is the clock signal advancing the execution of the sequence, `start` is the signal starting the execution, and `block` is the description of the sequence to be executed. Both `clock` and `start` can also be events (i.e., `posedge` or `negedge`).
2892
+
2893
+ A sequence is a specific case of a `seq` block that includes the following software-like additional constructs:
2894
+
2895
+ - `step`: wait until the next event (given argument `event` of the sequencer).
2896
+
2897
+ - `sif(<condition>) <block>`: executes `block` if `condition` is met.
2898
+
2899
+ - `selsif(<condition>) <block>`: executes `block` if previous `sif` or `selsif` condition is not met and if current `condition` is met.
2900
+
2901
+ - `selse <block>`: executes `block` if the condition of the previous `sif` statement is not met.
2902
+
2903
+ - `swait(<condition>)`: waits until that `condition` is met.
2904
+
2905
+ - `swhile(<condition>) <block>`: executes `block` while `condition` is met.
2906
+
2907
+ - `sfor(<enumerable>) <block>`: executes `block` on each element of `enumerable`. This latter can be any enumerable Ruby object or any signal. If the signal is not hierarchical (e.g., bit vector), the iteration will be over each bit.
2908
+
2909
+ - `sbreak`: ends current iteration.
2910
+
2911
+ - `scontinue`: goes to the next step of the iteration.
2912
+
2913
+ - `sterminate`: ends the execution of the sequence.
2914
+
2915
+ It is also possible to use enumerators (iterators) similar to the Ruby `each` using the following methods within sequences:
2916
+
2917
+ - `<object>.seach`: `object` any enumerable Ruby object or any signal. If a block is given, it works like `sfor`, otherwise, it returns a HDLRuby enumerator (please see [enumerator](#hdlruby-enumerators-and-enumerable-objects-stdsequencerrb) for details about them).
2918
+
2919
+ - `<object>.stimes`: can be used on integers and is equivalent to `seach` on each integer from 0 up to `object-1`.
2920
+
2921
+ - `<object>.supto(<last>)`: can be used on integers and is equivalent to `seach` on each integer from `object` up to `last`.
2922
+
2923
+ - `<object>.sdownto(<last>)`: can be used on an integer and is equivalent to `seach` on each integer from `object` down to `last`.
2924
+
2925
+ The objects that support these methods are called _enumerable_ objects. They include the HDLRuby signals, the HDLRuby enumerators, and all the Ruby enumerable objects (e.g., ranges, arrays).
2926
+
2927
+
2928
+ Here are a few examples of sequencers synchronized in the positive edge of `clk` and starting when `start` becomes one. The first one computes the Fibonacci series until 100, producing a new term in signal `v` at each cycle:
2929
+
2930
+ ```ruby
2931
+ require 'std/sequencer.rb'
2932
+ include HDLRuby::High::Std
2933
+
2934
+ system :a_circuit do
2935
+ inner :clk, :start
2936
+ [16].inner :a, :b
2937
+
2938
+ sequencer(clk.posedge,start) do
2939
+ a <= 0
2940
+ b <= 1
2941
+ swhile(v < 100) do
2942
+ b <= a + b
2943
+ a <= b - a
2944
+ end
2945
+ end
2946
+ end
2947
+ ```
2948
+
2949
+ The second one computes the square of the integers from 10 to 100, producing one result per cycle in signal `a`:
2950
+
2951
+ ```ruby
2952
+ inner :clk, :start
2953
+ [16].inner :a
2954
+
2955
+ sequencer(clk.posedge,start) do
2956
+ 10.supto(100) { |i| a <= i*i }
2957
+ end
2958
+ ```
2959
+
2960
+ The third one reverses the content of memory `mem` (the result will be "!dlrow olleH"):
2961
+
2962
+ ```ruby
2963
+ inner :clk, :start
2964
+ bit[8][-12].inner mem: "Hello world!"
2965
+
2966
+ sequencer(clk.posedge,start) do
2967
+ mem.size.stimes do |i|
2968
+ [8].inner :tmp
2969
+ tmp <= mem[i]
2970
+ mem[i] <= mem[-i-1]
2971
+ mem[-i-1] <= tmp
2972
+ end
2973
+ end
2974
+ ```
2975
+
2976
+ The fourth one computes the sum of all the elements of memory `mem` but stops if the sum is larger than 16:
2977
+
2978
+ ```ruby
2979
+ inner :clk, :start
2980
+ bit[8][-8].inner mem: [ _h02, _h04, _h06, _h08, _h0A, _h0C, _h0E ]
2981
+ bit[8] :sum
2982
+
2983
+ sequencer(clk.posedge,start) do
2984
+ sum <= 0
2985
+ sfor(mem) do |elem|
2986
+ sum <= sum + elem
2987
+ sif(sum > 16) { sterminate }
2988
+ end
2989
+ end
2990
+ ```
2991
+
2992
+
2993
+ ### HDLRuby enumerators and enumerable objects: `std/sequencer.rb`
2994
+
2995
+ HDLRuby enumerators are objects for generating iterations within sequencers. They are created using the method `seach` on enumerable objects as presented in the previous section.
2996
+
2997
+ The enumerators can be controlled using the following methods:
2998
+
2999
+ - `size`: returns the number of elements the enumerator can access.
3000
+
3001
+ - `type`: returns the type of the elements accessed by the enumerator.
3002
+
3003
+ - `seach`: returns the current enumerator. If a block is given, performs the iteration instead of returning an enumerator.
3004
+
3005
+ - `seach_with_index`: returns an enumerator over the elements of the current enumerator associated with their index position. If a block is given, performs the iteration instead of returning an enumerator.
3006
+
3007
+ - `seach_with_object(<obj>)`: returns an enumerator over the elements of the current enumerator associated with object `obj` (any object, HDLRuby or not, can be used). If a block is given, performs the iteration instead of returning an enumerator.
3008
+
3009
+ - `with_index`: identical to `seach_with_index`.
3010
+
3011
+ - `with_object(<obj>)`: identical to `seach_with_object`.
3012
+
3013
+ - `clone`: create a new enumerator on the same elements.
3014
+
3015
+ - `speek`: returns the current element pointed by the enumerator without advancing it.
3016
+
3017
+ - `snext`: returns the current element pointed by the enumerator and goes to the next one.
3018
+
3019
+ - `srewind`: restart the enumeration.
3020
+
3021
+ - `+`: concatenation of enumerators.
3022
+
3023
+ It is also possible to define a custom enumerator using the following command:
3024
+
3025
+ ```ruby
3026
+ <enum> = senumerator(<typ>,<size>) <block>
3027
+ ```
3028
+
3029
+ Where `enum` is a Ruby variable referring to the enumerator, `typ` is the data type and `size` is the number of the elements to enumerate and `block` is the block that implements the access to an element by index. For example, an enumerator on a memory could be defined as follows:
3030
+
3031
+ ```ruby
3032
+ bit[8][-8].inner mem: [ _h01, _h02, _h03, _h04, _h30, _h30, _h30, _h30 ]
3033
+ [3].inner :addr
3034
+ [8].inner :data
3035
+
3036
+ data <= mem[addr]
3037
+
3038
+ mem_enum = senumerator(bit[8],8) do |i|
3039
+ addr <= i
3040
+ step
3041
+ data
3042
+ end
3043
+ ```
3044
+
3045
+ In the code above, `mem_enum` is the variable referring to the resulting enumerator built for accessing memory `mem`. For the access, it is assumed that one cycle must be waited after the address is sets, and therefore a `step` command is added in the access procedure before `data` can be returned.
3046
+
3047
+ With this basis, several algorithms have been implemented using enumerators and are usable for all the enumerable objects. All these algorithms are HW implantation of the Ruby Enumerable methods. They are accessible using the corresponding ruby method prefixed by character `s`. For example, the HW implementation of the ruby `all?` method is generated by the `sall?` method. In details:
3048
+
3049
+ - `sall?`: HW implementation of the Ruby `all?` method. Returns a single-bit signal. When 0 this value means false and when 1 it means true.
3050
+
3051
+ - `sany?`: HW implementation of the Ruby `any?` method. Returns a single-bit signal. When 0 this value means false and when 1 it means true.
2816
3052
 
2817
- ## Fixed-point (fixpoint)
3053
+ - `schain`: HW implementation of the Ruby `chain`.
3054
+
3055
+ - `smap`: HW implementation of the Ruby `map` method. When used with a block returns a vector signal containing each computation result.
3056
+
3057
+ - `scompact`: HW implementation of the Ruby `compact` method. However, since there is no nil value in HW, use 0 instead for compacting. Returns a vector signal containing the compaction result.
3058
+
3059
+ - `scount`: HW implementation of the Ruby `count` method. Returns a signal whose bit width matches the size of the enumerator containing the count result.
3060
+
3061
+ - `scycle`: HW implementation of the Ruby `cycle` method.
3062
+
3063
+ - `sfind`: HW implementation of the Ruby `find` method. Returns a signal containing the found element, or 0 if not found.
3064
+
3065
+ - `sdrop`: HW implementation of the Ruby `drop` method. Returns a vector signal containing the remaining elements.
3066
+
3067
+ - `sdrop_while`: HW implementation of the Ruby `drop_while` method. Returns a vector signal containing the remaining elements.
3068
+
3069
+ - `seach_cons`: HW implementation of the Ruby `each_cons` method.
3070
+
3071
+ - `seach_slice`: HW implementation of the Ruby `each_slice` method.
3072
+
3073
+ - `seach_with_index`: HW implementation of the Ruby `each_with_index` method.
3074
+
3075
+ - `seach_with_object`: HW implementation of the Ruby `each_with_object` method.
3076
+
3077
+ - `sto_a`: HW implementation of the Ruby `to_a` method. Returns a vector signal containing all the elements of the enumerator.
3078
+
3079
+ - `sselect`: HW implementation of the Ruby `select` method. Returns a vector signal containing the selected elements.
3080
+
3081
+ - `sfind_index`: HW implementation of the Ruby `find_index` method. Returns the index of the found element or -1 if not.
3082
+
3083
+ - `sfirst`: HW implementation of the Ruby `first` method. Returns a vector signal containing the first elements.
3084
+
3085
+ - `sinclude?`: HW implementation of the Ruby `include?` method. Returns a single-bit signal. When 0 this value means false and when 1 it means true.
3086
+
3087
+ - `sinject`: HW implementation of the Ruby `inject` method. Return a signal of the type of elements containing the computation result.
3088
+
3089
+ - `smax`: HW implementation of the Ruby `max` method. Return a vector signal containing the found max values.
3090
+
3091
+ - `smax_by`: HW implementation of the Ruby `max_by` method. Return a vector signal containing the found max values.
3092
+
3093
+ - `smin`: HW implementation of the Ruby `min` method. Return a vector signal containing the found min values.
3094
+
3095
+ - `smin_by`: HW implementation of the Ruby `min_by` method. Return a vector signal containing the found min values.
3096
+
3097
+ - `sminmax`: HW implementation of the Ruby `minmax` method. Returns a 2-element vector signal containing the resulting min and max values.
3098
+
3099
+ - `sminmax_by`: HW implementation of the Ruby `minmax_by` method. Returns a 2-element vector signal containing the resulting min and max values.
3100
+
3101
+ - `snone?`: HW implementation of the Ruby `none?` method. Returns a single-bit signal. When 0 this value means false and when 1 it means true.
3102
+
3103
+ - `sone?`: HW implementation of the Ruby `one?` method. Returns a single-bit signal. When 0 this value means false and when 1 it means true.
3104
+
3105
+ - `sreject`: HW implementation of the Ruby `reject` method. Returns a vector signal containing the remaining elements.
3106
+
3107
+ - `sreverse_each`: HW implementation of the Ruby `reverse_each` method.
3108
+
3109
+ - `ssort`: HW implementation of the Ruby `sort` method. Returns a vector signal containing the sorted elements.
3110
+
3111
+ - `ssort_by`: HW implementation of the Ruby `sort_by` method. Returns a vector signal containing the sorted elements.
3112
+
3113
+ - `ssum`: HW implementation of the Ruby `sum` method. Returns a signal with the type of elements containing the sum result.
3114
+
3115
+ - `stake`: HW implementation of the Ruby `take` method. Returns a vector signal containing the taken elements.
3116
+
3117
+ - `stake_while`: HW implementation of the Ruby `take_while` method. Returns a vector signal containing the taken elements.
3118
+
3119
+ - `suniq`: HW implementation the Ruby `uniq` method. Returns a vector signal containing the selected elements.
3120
+
3121
+
3122
+
3123
+ ### Shared signals, arbiters and monitors: `std/sequencer_sync.rb`
3124
+ <a name="shared"></a>
3125
+
3126
+ #### Shared signals
3127
+
3128
+ Like any other processes, It is not possible for several sequencers to write to the same signal. This is because there would be race competition that may destroy physically the device if such operations where authorized. In standard RTL design, this limitation is overcome by implementing three-state buses, multiplexers and arbiters. However, HDLRuby sequencers supports another kind of signals called the *shared signals* that abstract the implementation details for avoiding race competition.
3129
+
3130
+ The shared signals are declared like the other kind of signals from their type. The syntax is the following:
3131
+
3132
+ ```ruby
3133
+ <type>.shared <list of names>
3134
+ ```
3135
+
3136
+ They can also have an initial (and default) value when declared as follows:
3137
+
3138
+ ```ruby
3139
+ <type>.shared <list of names with initialization>
3140
+ ```
3141
+
3142
+ For example the following code declare two 8-bit shared signals `x` and `y` and two signed 16-bit shared signals initialized to 0 `u` and `v`:
3143
+
3144
+ ```ruby
3145
+ [8].shared :x, :y
3146
+ signed[8].shared u: 0, v: 0
3147
+ ```
3148
+
3149
+ A shared signals can then be read and written to by any sequencer from anywhere in the subsequent code of the current scope. However, they cannot be written to outside a sequencer. For example, the following code is valid:
3150
+
3151
+ ```ruby
3152
+ input :clk, :start
3153
+ [8].inner :val0, :val1
3154
+ [8].shared :x, :y
3155
+
3156
+ val0 <= x+y
3157
+ par(clk.posedge) { val1 <= x+y }
3158
+
3159
+ sequencer(clk.posedge,start) do
3160
+ 10.stimes { |i| x <= i }
3161
+ end
3162
+
3163
+ sequencer(clk.posedge,start) do
3164
+ 5.stimes { |i| x <= i*2 ; y <= i*2 }
3165
+ end
3166
+ ```
3167
+
3168
+ But the following code is not valid:
3169
+
3170
+ ```ruby
3171
+ [8].shared w: 0
3172
+
3173
+ par(clk.posedge) { w <= w + 1 }
3174
+ ```
3175
+
3176
+ By default, a shared signal acknowledge writing from the first sequencer that access it in order of declaration, the others are ignored. In the first example given above, that means for signal `x` the value is always the one written by the first sequencer, i.e., from 0 to 9 changing once per clock cycle. However, the value of signal `y` is set by the second sequencer since it is this one only that writes to this signal.
3177
+
3178
+ This default behavior of shared signal avoids race competition, but is not very useful in practice. For a better control, it is possible to select which sequencer is to be acknowledged for writing. This is done by setting the number of the sequencer which can write the signal that controls the sharing accessed as follows:
3179
+
3180
+ ```ruby
3181
+ <shared signal>.select
3182
+ ```
3183
+
3184
+ The select value starts from 0 for the first sequencer writing to the shared signal, and is increased by one per writing sequencer. For example, in the first example, for selecting the second sequencer for writing to `x` the follow code can be added after this signal is declared:
3185
+
3186
+ ```ruby
3187
+ x.select <= 1
3188
+ ```
3189
+
3190
+ This value can be changed at runtime too. For example, instead of setting the second sequencer, it is possible to switch sequencer every clock cycle as follows:
3191
+
3192
+ ```ruby
3193
+ par(clk.posedge) { x.select <= x.select + 1 }
3194
+ ```
3195
+
3196
+ __Note__: this select sub signal is a standard RTL signal that has the same properties and limitations as the other ones, i.e., this is not a shared signal itself.
3197
+
3198
+
3199
+ #### Arbiters
3200
+
3201
+ Usually, it is not the signals that we want to share, but the resources they drives. For example, in a CPU, it is an ALU that is shared as a whole rather than each of its input separately. In order to support such cases and ease the handling of shared signals, the library also provides the *arbiter* components. This component is instantiated like a standard module as follows, where `name` is the name of the arbiter instance:
3202
+
3203
+ ```ruby
3204
+ arbiter(:<name>).(<list of shared signal>)
3205
+ ```
3206
+
3207
+ When instantiated, an arbiter will take control of the select sub signals of the shared signals (hence, you cannot control the selection yourself for them any longer). In returns, it provides the possibility of requiring or releasing access to the shared signals. Requiring access is done by sending the value 1 to the arbiter, and releasing is done by sending the value 0. If a sequencer writes to a shared signal under arbitration without requiring access first, the write will simply be ignored.
3208
+
3209
+ The following is an example of arbiter that controls access to shared signals `x` and `y` and two sequencers acquiring and releasing accesses to them:
3210
+
3211
+ ```ruby
3212
+ input :clk, :start
3213
+ [8].shared x, y
3214
+ arbiter(:ctrl_xy).(x,y)
3215
+
3216
+ sequencer(clk.posedge,start) do
3217
+ ctrl_xy <= 1
3218
+ x <= 0 ; y <= 0
3219
+ 5.stime do |i|
3220
+ x <= x + 1
3221
+ y <= y + 2
3222
+ end
3223
+ ctrl_xy <= 0
3224
+ end
3225
+
3226
+ sequencer(clk.posedge,start) do
3227
+ ctrl_xy <= 1
3228
+ x <= 2; y <= 1
3229
+ 10.stime do |i|
3230
+ x <= x + 2
3231
+ y <= y + 1
3232
+ end
3233
+ ctrl_xy <= 0
3234
+ end
3235
+ ```
3236
+
3237
+ In the example, both sequencers require access to signals `x` and `y` before accessing them and then releasing the access.
3238
+
3239
+ Requiring access does not guaranties that the access will be granted by the arbiter though. In the access is not granted, the write access will be ignored.
3240
+ The default access granting policy of an arbiter is the priority in order of sequencer declaration. I.e., if several sequencer are requiring at the same time, then the one declared the earliest in the code gains write access. For example, with the code given about, the first sequencer have write access to `x` and `y`, and since after five write cycles it releases access, the second sequencer can then write to these signals. However, not obtaining write access does not block the execution of the sequencer, simply, its write access to the corresponding shared signals is simple ignored. In the example, the second sequencer will do its first five loop cycles without any effect, and have only its five last ones that change the shared signals. To avoid such a behavior, it is possible to check if the write access is granted using arbiter sub signal `acquired`: if this signal is one in current sequencer, that means the access is granted, otherwise its is 0. For example the following will increase signal `x` only if write access is granted:
3241
+
3242
+ ```ruby
3243
+ hif(ctrl_xy.acquired) { x <= x + 1 }
3244
+ ```
3245
+
3246
+ The policy of an arbiter can be changed using command policy. You can either provide a new priority table, containing the number of the sequencers in order of priority (the first one having higher priority. The number of a sequencer is assign in order of declaration provided it uses the arbiter. For example, in the previous code, the second sequencer can be given higher priority by adding the following code after having declared the arbiter:
3247
+
3248
+ ```ruby
3249
+ ctrl_xy.policy([1,0])
3250
+ ```
3251
+
3252
+ It is also possible to set a more complex policy by providing to the policy method a block of code whose argument is a vector indicating which sequencer is currently requiring write access to the shared signals and whose result will be the number of the sequencer to grant the access. This code will be executing each time an write access is actually performed. For example, in the previous code, a policy switch priorities at each access can be implemented as follows:
3253
+
3254
+ ```ruby
3255
+ inner priority_xy: 0
3256
+ inner grant_xy
3257
+ ctrl_xy.policy do |acq|
3258
+ hcase(acq)
3259
+ hwhen(_b01) do
3260
+ grant_xy <= 0
3261
+ priority_xy <= ~priority_xy
3262
+ end
3263
+ hwhen(_b10) do
3264
+ grant_xy <= 1
3265
+ priority_xy <= ~priority_xy
3266
+ end
3267
+ hwhen(_b11) do
3268
+ grant_xy <= priority_xy
3269
+ priority_xy <= ~priority_xy
3270
+ end
3271
+ grant_xy
3272
+ end
3273
+ ```
3274
+
3275
+ As seen in the code above, each bit of the `acq` vector is one when the corresponding sequencer required an access or 0 otherwise, bit 0 corresponding to sequencer 0, bit 1 to sequencer 1 and so one.
3276
+
3277
+
3278
+ #### Monitors
3279
+
3280
+ Arbiters a especially useful when we can ensure that the sequencers accessing the same resource do not overlap or when the do not need to synchronize with each other. If such synchronizations are required, instead of arbiters, it is possible to use the *monitor* components.
3281
+
3282
+ The monitor component are instantiated like the arbiters as follows:
3283
+
3284
+ ```ruby
3285
+ monitor(:<name>).(<list of shared signals>)
3286
+ ```
3287
+
3288
+ Monitors are used exactly the same ways as arbiters (including the write access granting policies), but blocks the execution of the sequencers that require a write access until the access is granted. If we take the example of code with two sequencers given as illustration of arbiter usage, replacing the arbiter by a monitor as follows will lock the second sequencer until it can write to shared variables `x` and `y` ensuring that all its loop cycles have the specified result:
3289
+
3290
+ ```ruby
3291
+ monitor(:ctrl_xy).(x,y)
3292
+ ```
3293
+
3294
+ Since monitors locks processes, it automatically insert a step, hence to avoid confusion, aquiring access to a monitor is done by using method `lock` instead of assigning 1, and releasing is done by using method `unlock` instead of assigning 0. Hence, when using a monitor, the previous arbiter-based code should be rewriten as follows:
3295
+
3296
+ ```ruby
3297
+ input :clk, :start
3298
+ [8].shared x, y
3299
+ monitor(:ctrl_xy).(x,y)
3300
+
3301
+ sequencer(clk.posedge,start) do
3302
+ ctrl_xy.lock
3303
+ x <= 0 ; y <= 0
3304
+ 5.stime do |i|
3305
+ x <= x + 1
3306
+ y <= y + 2
3307
+ end
3308
+ ctrl_xy.unlock
3309
+ end
3310
+
3311
+ sequencer(clk.posedge,start) do
3312
+ ctrl_xy.lock
3313
+ x <= 2; y <= 1
3314
+ 10.stime do |i|
3315
+ x <= x + 2
3316
+ y <= y + 1
3317
+ end
3318
+ ctrl_xy.unlock
3319
+ end
3320
+ ```
3321
+
3322
+ ## Fixed-point (fixpoint): `std/fixpoint.rb`
2818
3323
  <a name="fixpoint"></a>
2819
3324
 
2820
3325
  This library provides a new fixed point set of data types. These new data types can be bit vectors, unsigned or signed values and are declared respectively as follows:
@@ -2839,14 +3344,14 @@ In addition to the fixed point data type, a method is added to the literal objec
2839
3344
  <litteral>.to_fix(<number of bits after the decimal point>)
2840
3345
  ```
2841
3346
 
2842
- For example, the following code converts a floating-point value to a fixed point value with 16 bits after the decimal point:
3347
+ For example, the following code converts a floating-point value to a fixed-point value with 16 bits after the decimal point:
2843
3348
 
2844
3349
  ```
2845
3350
  3.178.to_fix(16)
2846
3351
  ```
2847
3352
 
2848
3353
 
2849
- ## Channel
3354
+ ## Channel: `std/channel.rb`
2850
3355
  <a name="channel"></a>
2851
3356
 
2852
3357
  This library provides a unified interface to complex communication protocols through a new kind of component called the channels that abstract the details of communication protocols. The channels can be used similarly to the ports of a system and are used through a unified interface so that changing the kind of channel, i.e., the communication protocol, does not require any modification of the code.
@@ -2886,9 +3391,9 @@ The access points to a channel can also be handled individually by declaring por
2886
3391
  * `output <name>`: declares a port for writing to the channel and associates them to `name` if any
2887
3392
  * `inout <name>`: declares a port for reading and writing to the channel and associates them to `name` if any
2888
3393
 
2889
- Such port can then be accessed using the same `read` and `write` method of a channel, the difference being that they can also be configured for new access procedures using the `wrap` method:
3394
+ Such a port can then be accessed using the same `read` and `write` method of a channel, the difference being that they can also be configured for new access procedures using the `wrap` method:
2890
3395
 
2891
- * `wrap(<args>) <code>`: creates a new port whose read or write procedure has the elements of `<args>` and the ones produced by `<code>` assign to the arguments of the read or write procedure.
3396
+ * `wrap(<args>) <code>`: creates a new port whose read or write procedure has the elements of `<args>` and the ones produced by `<code>` assigned to the arguments of the read or write procedure.
2892
3397
 
2893
3398
  For example, assuming `mem` is a channel whose read and write access have as argument the target address and data signals, the following code creates a port for always accessing at address 0:
2894
3399
 
@@ -2902,7 +3407,7 @@ Some channels may include several branches, they are accessed by name using the
2902
3407
 
2903
3408
  * `branch(<name>)`: gets branch named `name` from the channel. This name can be any ruby object (e.g., a number) but it will be converted internally to a ruby symbol.
2904
3409
 
2905
- A branch is a full-fledge channel and is used identically. For instance, the following code gets access to branch number 0 of channel `ch`, gets its inputs port, reads it, and put the result in signal `val` on the rising edges of signal `clk`:
3410
+ A branch is a full-fledged channel and is used identically. For instance, the following code gets access to branch number 0 of channel `ch`, gets its inputs port, reads it, and put the result in signal `val` on the rising edges of signal `clk`:
2906
3411
 
2907
3412
  ```ruby
2908
3413
  br = ch.branch(0)
@@ -3024,17 +3529,18 @@ end
3024
3529
 
3025
3530
  __Note__:
3026
3531
 
3027
- * The code of the circuits, in the examples `producer8`, `consumer8`, and `producer_consummer8` is independent of the content of the channel. For example, the sample `with_channel.rb` (please see [sample](#sample)) use the same circuits with a channel implementing handshaking.
3532
+ * The code of the circuits, in the examples `producer8`, `consumer8`, and `producer_consummer8` is independent of the content of the channel. For example, the sample `with_channel.rb` (please see [samples](#sample-hdlruby-descriptions)) uses the same circuits with a channel implementing handshaking.
3028
3533
 
3534
+ <!---
3029
3535
 
3030
3536
  ## Pipeline
3031
3537
  <a name="pipeline"></a>
3032
3538
 
3033
3539
  This library provides a construct for an easy description of pipeline architectures.
3034
3540
 
3541
+ -->
3035
3542
 
3036
3543
  # Sample HDLRuby descriptions
3037
- <a name="sample"></a>
3038
3544
 
3039
3545
  Several samples HDLRuby descriptions are available in the following directory:
3040
3546
 
@@ -3042,15 +3548,22 @@ path/to/HDLRuby/lib/HDLRuby/hdr\_samples
3042
3548
 
3043
3549
  For the gem install, the path to HDLRuby can be found using the following:
3044
3550
 
3045
- ```
3551
+ ```bash
3046
3552
  gem which HDLRuby
3047
3553
  ```
3048
3554
 
3555
+ But you can also import the samples to your local directory with the following command (recommended):
3556
+
3557
+ ```bash
3558
+ hdrcc --get-samples
3559
+ ```
3560
+
3049
3561
  The naming convention of the samples is the following:
3050
3562
 
3051
3563
  * `<name>.rb`: default type of sample.
3052
3564
  * `<name>_gen.rb`: generic parameters are required for processing the sample.
3053
3565
  * `<name>_bench.rb`: sample including a simulation benchmark, these are the only samples that can be simulated using `hdrcc -S`. Please notice that such a sample cannot be converted to VHDL or Verilog HDL yet.
3566
+ * `with_<name>.rb`: sample illustrating a single aspect of HDLRuby or one of its library, usually includes a benchmark.
3054
3567
 
3055
3568
 
3056
3569
  # Contributing
@@ -3060,10 +3573,6 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/civol/
3060
3573
 
3061
3574
  # To do
3062
3575
 
3063
- * Test the compatibility of the HDLRuby framework with the Microsoft Windows environments.
3064
- * Add the generation of VHDL and Verilog code for the time behaviors.
3065
- * Provide targets for the `Reconf` library.
3066
- * Add a standard wave output for the simulator.
3067
3576
  * Find and fix the (maybe) terrifying number of bugs.
3068
3577
  * Add a GUI (any volunteer to do it?).
3069
3578