HDLRuby 3.2.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.html +4411 -2930
  3. data/README.md +396 -102
  4. data/ext/hruby_sim/hruby_rcsim_build.c +400 -3
  5. data/ext/hruby_sim/hruby_sim.h +2 -1
  6. data/ext/hruby_sim/hruby_sim_calc.c +1 -1
  7. data/ext/hruby_sim/hruby_sim_core.c +15 -5
  8. data/ext/hruby_sim/hruby_sim_tree_calc.c +1 -1
  9. data/lib/HDLRuby/hdr_samples/c_program/echo.c +33 -0
  10. data/lib/HDLRuby/hdr_samples/ruby_program/echo.rb +9 -0
  11. data/lib/HDLRuby/hdr_samples/ruby_program/stdrw.rb +6 -0
  12. data/lib/HDLRuby/hdr_samples/ruby_program/sw_cpu_terminal.rb +614 -0
  13. data/lib/HDLRuby/hdr_samples/ruby_program/sw_inc_mem.rb +32 -0
  14. data/lib/HDLRuby/hdr_samples/ruby_program/sw_log.rb +33 -0
  15. data/lib/HDLRuby/hdr_samples/with_board.rb +63 -0
  16. data/lib/HDLRuby/hdr_samples/with_clocks.rb +42 -0
  17. data/lib/HDLRuby/hdr_samples/with_of.rb +1 -1
  18. data/lib/HDLRuby/hdr_samples/with_program_c.rb +28 -0
  19. data/lib/HDLRuby/hdr_samples/with_program_ruby.rb +28 -0
  20. data/lib/HDLRuby/hdr_samples/with_program_ruby_cpu.rb +234 -0
  21. data/lib/HDLRuby/hdr_samples/with_program_ruby_io.rb +23 -0
  22. data/lib/HDLRuby/hdr_samples/with_program_ruby_mem.rb +58 -0
  23. data/lib/HDLRuby/hdr_samples/with_program_ruby_threads.rb +56 -0
  24. data/lib/HDLRuby/hdr_samples/with_sequencer_func.rb +2 -4
  25. data/lib/HDLRuby/hdrcc.rb +60 -21
  26. data/lib/HDLRuby/hruby_error.rb +13 -0
  27. data/lib/HDLRuby/hruby_high.rb +50 -7
  28. data/lib/HDLRuby/hruby_low.rb +74 -30
  29. data/lib/HDLRuby/hruby_rcsim.rb +89 -5
  30. data/lib/HDLRuby/std/clocks.rb +118 -50
  31. data/lib/HDLRuby/std/std.rb +5 -0
  32. data/lib/HDLRuby/ui/hruby_board.rb +1079 -0
  33. data/lib/HDLRuby/version.rb +1 -1
  34. data/lib/c/Rakefile +8 -0
  35. data/lib/c/cHDL.h +12 -0
  36. data/lib/c/extconf.rb +7 -0
  37. data/lib/rubyHDL.rb +33 -0
  38. data/tuto/gui_accum.png +0 -0
  39. data/tuto/gui_board.png +0 -0
  40. data/tuto/tutorial_sw.html +4163 -2081
  41. data/tuto/tutorial_sw.md +957 -62
  42. metadata +24 -5
  43. data/README.pdf +0 -0
  44. data/tuto/tutorial_sw.pdf +0 -0
data/README.md CHANGED
@@ -7,14 +7,33 @@ __Note__:
7
7
 
8
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
9
 
10
- * [HDLRuby tutorial for software people](tuto/tutorial_sw.md)
10
+ * [HDLRuby tutorial for software people](https://github.com/civol/HDLRuby/blob/master/tuto/tutorial_sw.md) [md]
11
+
12
+ And if you want an html version the following command with create a `tuto` folder containing all the required files, then just open `tuto/tutorial_sw.html`:
13
+
14
+ ```
15
+ hdrcc --get-tuto
16
+ ```
11
17
 
12
18
  __What's new__
13
19
 
20
+ For HDLRuby version 3.3.0:
21
+
22
+ * Remade the description of software components using the program construct.
23
+ Now the Code objects are deprecated.
24
+
25
+ * Added HW-SW co-simulation capability for Ruby and compiled C-compatible
26
+ software programs.
27
+
28
+ * Added a browser-based graphical interface simulating simulates a development board that interacts with the HDLRuby simulator.
29
+
30
+ * Updated the documentation and tutorial accordingly and fixed several typos.
31
+
32
+
14
33
  For HDLRuby version 3.2.0:
15
34
 
16
35
  * Added component for declaring BRAM and BRAM-based stacks.
17
- The goal is to efficiently allocate memories inside FPGAs.
36
+ The goal is to allocate memories inside FPGAs efficiently.
18
37
 
19
38
  * Inner code overhaul for preparing version 4.0.0
20
39
 
@@ -46,7 +65,7 @@ For HDLRuby version 3.0.0:
46
65
 
47
66
  __Install__:
48
67
 
49
- The recommended installation method is from rubygem as follows:
68
+ The recommended installation method is from rubygems as follows:
50
69
 
51
70
  ```
52
71
  gem install HDLRuby
@@ -55,13 +74,13 @@ gem install HDLRuby
55
74
  Developers willing to contribute to HDLRuby can install the sources from GitHub as follows:
56
75
 
57
76
  ```
58
- git clone HDLRuby
77
+ git clone https://github.com/civol/HDLRuby.git
59
78
  ```
60
79
 
61
80
  __Warning__:
62
81
 
63
82
  - This is still preliminary work which may change before we release a stable version.
64
- - It is highly recommended to have both basic knowledges of the Ruby language and hardware description languages before using HDLRuby.
83
+ - It is highly recommended to have both basic knowledge of the Ruby language and hardware description languages before using HDLRuby.
65
84
 
66
85
 
67
86
  # Compiling HDLRuby descriptions
@@ -108,7 +127,7 @@ __Notes__:
108
127
 
109
128
  * If no top system is given, it is automatically looked for from the input file.
110
129
  * If no option is given, it simply checks the input file.
111
- * 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:
130
+ * If you are new to HDLRuby, or if you want to see how new features work, we strongly encourage you to get a local copy of the test HDLRuby sample using:
112
131
 
113
132
  ```bash
114
133
  hdrcc --get-samples
@@ -165,7 +184,7 @@ hdrcc -I pry
165
184
 
166
185
  ## Using HDLRuby in interactive mode
167
186
 
168
- When running in interactive mode, the HDLRuby framework starts a REPL prompt and creates a working directory called 'HDLRubyWorkspace'. By default, the REPL is 'irb', but it can be set to 'pry'. Within this prompt, HDLRuby code can be written like in an HDLRuby description file. However, to process this code the following commands are added:
187
+ When running in interactive mode, the HDLRuby framework starts a REPL prompt and creates a working directory called `HDLRubyWorkspace`. By default, the REPL is `irb`, but it can be set to `pry`. Within this prompt, HDLRuby code can be written like in an HDLRuby description file. However, to process this code the following commands are added:
169
188
 
170
189
  * Compile an HDLRuby module:
171
190
 
@@ -384,7 +403,7 @@ system :reg do |typ|
384
403
  end
385
404
  ```
386
405
 
387
- Wait... I have just realized that D-FF without any inverted output does not look very serious. So, let us extend the existing `dff` to provide an inverted output. There are three ways for doing this. First, inheritance can be used: a new system is built inheriting from `dff` as it is done in the following code.
406
+ Wait... I have just realized that D-FF without any inverted output does not look very serious. So, let us extend the existing `dff` to provide an inverted output. There are three ways to do this. First, inheritance can be used: a new system is built inheriting from `dff` as it is done in the following code.
388
407
 
389
408
  ```ruby
390
409
  system :dff_full, dff do
@@ -442,7 +461,7 @@ system :shifter do |n|
442
461
  end
443
462
  ```
444
463
 
445
- 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.)
464
+ As can be seen in the above examples, in HDLRuby, any construct is an object and therefore includes 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.)
446
465
 
447
466
  ```ruby
448
467
  <type>.<direction> <list of symbols representing the signal>
@@ -493,7 +512,7 @@ end
493
512
  In the code above, there are two generic parameters,
494
513
  `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.
495
514
 
496
- 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`.
515
+ 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|` 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`.
497
516
 
498
517
  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).
499
518
 
@@ -501,7 +520,7 @@ While slightly longer than the previous description, this description allows dec
501
520
  sumprod(signed[32], [3,78,43,246, 3,67,1,8, 47,82,99,13, 5,77,2,4]).(:my_circuit)
502
521
  ```
503
522
 
504
- 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.
523
+ 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 to avoid confusion.
505
524
 
506
525
  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 the 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:
507
526
 
@@ -547,7 +566,7 @@ hdef :add do |max, x, y|
547
566
  end
548
567
  ```
549
568
 
550
- 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 no general purpose.
569
+ 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 kinds of addition operations, and hence, the code of `sumprod` has no general purpose.
551
570
 
552
571
  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:
553
572
 
@@ -592,7 +611,7 @@ sat16_1000.define_operator(:+) do |x,y|
592
611
  end
593
612
  ```
594
613
 
595
- In the code above, the first line defines the new type `sat16_1000` to be 16-bit signed and the remaining overloads (redefines) the `+` operator for this type (the same should be done for the `*` operator).
614
+ In the code above, the first line defines the new type `sat16_1000` to be 16-bit signed, and the remaining overloads (redefines) the `+` operator for this type (the same should be done for the `*` operator).
596
615
  Then, the initial version of `sumprod` can be used with this type to achieve saturated computations as follows:
597
616
 
598
617
  ```ruby
@@ -668,7 +687,7 @@ Several constructs in HDLRuby are referred to by name, e.g., systems and signals
668
687
  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
669
688
  has been declared with `:hello` as the name, it will be afterward referred to by `hello`.
670
689
 
671
- ## Systems and signals
690
+ ## Systems and Signals
672
691
 
673
692
  A system represents a digital system and corresponds to a Verilog HDL module. A system has an interface comprising input, output, and inout signals, and includes structural and behavioral descriptions.
674
693
 
@@ -676,7 +695,7 @@ A signal represents a state in a system. It has a data type and a value, the lat
676
695
 
677
696
  ### Declaring an empty system
678
697
 
679
- A system is declared using the keyword `system`. It must be given a Ruby symbol for its name and a block that describe its content. For instance, the following code describes an empty system named `box`:
698
+ A system is declared using the keyword `system`. It must be given a Ruby symbol for its name and a block that describes its content. For instance, the following code describes an empty system named `box`:
680
699
 
681
700
  ```ruby
682
701
  system(:box) {}
@@ -684,7 +703,7 @@ system(:box) {}
684
703
 
685
704
  __Notes__:
686
705
 
687
- - Since this is Ruby code, the body can also be delimited by the `do` and `end` Ruby keywords (in which case the parentheses can be omitted) are as follows:
706
+ - Since this is Ruby code, the body can also be delimited by the `do` and `end` Ruby keywords (in which case the parentheses can be omitted) as follows:
688
707
 
689
708
  ```ruby
690
709
  system :box does
@@ -860,7 +879,7 @@ end
860
879
  ### Initialization of signals
861
880
  <a name="initialization"></a>
862
881
 
863
- Output, inner and constant signals of a system can be initialized when declared using the following syntax in place of the usual name of the signal:
882
+ Output, inner, and constant signals of a system can be initialized when declared using the following syntax in place of the usual name of the signal:
864
883
 
865
884
  ```ruby
866
885
  <signal name>: <intial value>
@@ -899,7 +918,7 @@ system :div2 do
899
918
 
900
919
  ```
901
920
 
902
- For robustness or, readability purpose, it is possible to add inner scope inside the existing scope using the `sub` keyword as follows:
921
+ For robustness or, readability purposes, it is possible to add an inner scope inside the existing scope using the `sub` keyword as follows:
903
922
 
904
923
  ```ruby
905
924
  sub do
@@ -981,7 +1000,7 @@ end
981
1000
  ```
982
1001
 
983
1002
  In addition, it is possible to declare inner signals within an execution block.
984
- 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.
1003
+ 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 makes it possible to declare several signals with identical names provided their respective scopes are different.
985
1004
 
986
1005
  An event represents a specific change in the state of a signal.
987
1006
  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
@@ -1024,7 +1043,7 @@ system :with_sequential_behavior do
1024
1043
  end
1025
1044
  ```
1026
1045
 
1027
- 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:
1046
+ 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:
1028
1047
 
1029
1048
  ```ruby
1030
1049
  system :with_sequential_behavior do
@@ -1133,7 +1152,7 @@ end
1133
1152
  ( a <= b+1 ).at(clk.posedge)
1134
1153
  ```
1135
1154
 
1136
- For sake of consistency, this operator can also be applied to block statements as follows, but it is probably less readable than the standard declaration of behaviors:
1155
+ For the sake of consistency, this operator can also be applied to block statements as follows, but it is probably less readable than the standard declaration of behaviors:
1137
1156
 
1138
1157
  ```ruby
1139
1158
  ( seq do
@@ -1247,8 +1266,7 @@ __Note:__
1247
1266
  ## Statements
1248
1267
 
1249
1268
  Statements are the basic elements of a behavioral description. They are regrouped in blocks that specify their execution mode (parallel or sequential).
1250
- There are four kinds of statements: the transmit statement which computes expressions and sends the result to the target signals, the control statement
1251
- that changes the execution flow of the behavior, the block statement (described earlier), and the inner signal declaration.
1269
+ There are four kinds of statements: the transmit statement which computes expressions and sends the result to the target signals, the control statement which changes the execution flow of the behavior, the block statement (described earlier), and the inner signal declaration.
1252
1270
 
1253
1271
  __Note__:
1254
1272
 
@@ -1329,8 +1347,7 @@ end
1329
1347
 
1330
1348
  #### About loops
1331
1349
 
1332
- HDLRuby does not include any hardware construct for describing loops. This might look poor compared to the other HDL, but it is important to understand
1333
- that the current synthesis tools do not really synthesize hardware from such loops but instead preprocess them (e.g., unroll them) to synthesizable loopless hardware. In HDLRuby, such features are natively supported by the Ruby loop constructs (`for`, `while`, and so on), but also by advanced Ruby constructs like the enumerators (`each`, `times`, and so on).
1350
+ HDLRuby does not include any hardware construct for describing loops. This might look poor compared to the other HDL, but it is important to understand that the current synthesis tools do not synthesize hardware from such loops but instead preprocess them (e.g., unroll them) to synthesizable loopless hardware. In HDLRuby, such features are natively supported by the Ruby loop constructs (`for`, `while`, and so on), but also by advanced Ruby constructs like the enumerators (`each`, `times`, and so on).
1334
1351
 
1335
1352
  __Notes__:
1336
1353
 
@@ -1348,10 +1365,9 @@ __Notes__:
1348
1365
  ## Types
1349
1366
  <a name="types"></a>
1350
1367
 
1351
- Each signal and each expression is associated with a data type that describes the kind of value it can represent. In HDLRuby, the data types represent
1352
- bit-vectors associated with the way they should be interpreted, i.e., as bit strings, unsigned values, signed values, or hierarchical contents.
1368
+ Each signal and each expression is associated with a data type that describes the kind of value it can represent. In HDLRuby, the data types represent bit-vectors associated with the way they should be interpreted, i.e., as bit strings, unsigned values, signed values, or hierarchical contents.
1353
1369
 
1354
- ### Type construction
1370
+ ### Type Construction
1355
1371
 
1356
1372
  There are five basic types, `bit`, `signed`, `unsigned`, `integer`, and `float` that represent respectively single bit logical values, single-bit unsigned values, single-bit signed values, Ruby integer values, and Ruby floating-point values (double precision). The first three types are HW and support four-valued logic, whereas the two last ones are SW (but are compatible with HW) and only support Boolean logic. Ruby integers can represent any element of **Z** (the mathematical integers) and have for that purpose a variable bit-width.
1357
1373
 
@@ -1454,9 +1470,9 @@ They include [immediate values](#immediate-values), [reference to signals](#refe
1454
1470
 
1455
1471
  ### Immediate values
1456
1472
 
1457
- 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.
1473
+ 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 to increase the readability, but it will be ignored.
1458
1474
 
1459
- The vector type specifiers are the followings:
1475
+ The vector type specifiers are the following:
1460
1476
 
1461
1477
  - `b`: `bit` type, can be omitted,
1462
1478
 
@@ -1464,7 +1480,7 @@ The vector type specifiers are the followings:
1464
1480
 
1465
1481
  - `s`: `signed` type, the last figure is sign-extended if required by the binary, octal, and hexadecimal bases, but not for the decimal base.
1466
1482
 
1467
- The base specifiers are the followings:
1483
+ The base specifiers are the following:
1468
1484
 
1469
1485
  - `b`: binary,
1470
1486
 
@@ -1510,8 +1526,7 @@ __Notes__:
1510
1526
 
1511
1527
  References are expressions used to designate signals or a part of signals.
1512
1528
 
1513
- The simplest reference is simply the name of a signal. It designates the signal corresponding to this name in the current scope. For instance, in the
1514
- following code, inner signal `sig0` is declared, and therefore the name *sig0* becomes a reference to designate this signal.
1529
+ The simplest reference is simply the name of a signal. It designates the signal corresponding to this name in the current scope. For instance, in the following code, inner signal `sig0` is declared, and therefore the name *sig0* becomes a reference to designate this signal.
1515
1530
 
1516
1531
  ```ruby
1517
1532
  # Declaration of signal sig0.
@@ -1603,7 +1618,7 @@ __Conversion operators:__
1603
1618
  | :to\_bit | cast to bit vector |
1604
1619
  | :to\_unsigned | cast to unsigned vector |
1605
1620
  | :to\_signed | cast to signed vector |
1606
- | :to\_big | cast to big endian |
1621
+ | :to\_big | cast to big-endian |
1607
1622
  | :to\_little | cast to little endian |
1608
1623
  | :reverse | reverse the bit order |
1609
1624
  | :ljust | increase width from the left, preserves the sign |
@@ -1615,7 +1630,7 @@ __Selection /concatenation operators:__
1615
1630
 
1616
1631
  | &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;symbol&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | description&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |
1617
1632
  | :--- | :--- |
1618
- | :[] | sub vector selection |
1633
+ | :[] | sub-vector selection |
1619
1634
  | :@[] | concatenation operator |
1620
1635
  | :. | field selection |
1621
1636
 
@@ -1693,8 +1708,8 @@ The type puns include `to_bit`, `to_unsigned`, and `to_signed` that convert expr
1693
1708
  sig.to_bit <= _b01010011
1694
1709
  ```
1695
1710
 
1696
- 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).
1697
- These operators comprise the bit width conversions: `ljust`, `rjust`, `zext` and `sext`.
1711
+ 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 `unsigned` and can only increase the bit width (bit width can be truncated using the selection operator, please refer to the next section).
1712
+ These operators comprise the bit width conversions: `ljust`, `rjust`, `zext`, and `sext`.
1698
1713
 
1699
1714
  More precisely, the bit width conversions operate as follows:
1700
1715
 
@@ -1757,7 +1772,7 @@ Concatenation and selection are done using the `[]` operator as follows:
1757
1772
  #### Implicit conversions
1758
1773
  <a name="implicit"></a>
1759
1774
 
1760
- When there is no ambiguity, HDLRuby will automatically insert conversion operators when two types are not compatible with one another. The cases where such implicit conversions are applied are summarized in the following tables where:
1775
+ When there is no ambiguity, HDLRuby will automatically insert conversion operators when two types are not compatible with one another. The cases where such implicit conversions are applied are summarized in the following tables, where:
1761
1776
 
1762
1777
  - `operator` is the operator in use
1763
1778
  - `result width` is the width of the result's type
@@ -1854,7 +1869,7 @@ __Notes__:
1854
1869
  function :one { 1 }
1855
1870
  ```
1856
1871
 
1857
- - Functions can accept any kind of object as an argument, including variadic arguments or blocks of code as shown below with a function that applies the code passed as an argument to all the variadic arguments of `args`:
1872
+ - Functions can accept any object as an argument, including variadic arguments or blocks of code as shown below with a function that applies the code passed as an argument to all the variadic arguments of `args`:
1858
1873
 
1859
1874
  ```ruby
1860
1875
  function :apply do |*args, &code|
@@ -1862,7 +1877,7 @@ __Notes__:
1862
1877
  end
1863
1878
  ```
1864
1879
 
1865
- Such a function can be used for example for connecting a signal to a set of other signals as follows (where `sig` is connected to `x`, `y` and `z`):
1880
+ Such a function can be used for example for connecting a signal to a set of other signals as follows (where `sig` is connected to `x`, `y`, and `z`):
1866
1881
  ```ruby
1867
1882
  apply(x,y,z) { |v| v <= sig }
1868
1883
  ```
@@ -1915,7 +1930,7 @@ As another example, the following function will add an alternative code that gen
1915
1930
 
1916
1931
  ```ruby
1917
1932
  def too_bad
1918
- helse { $rst <= 1 }
1933
+ helse { rst <= 1 }
1919
1934
  end
1920
1935
  ```
1921
1936
 
@@ -1936,6 +1951,308 @@ end
1936
1951
  Ruby functions can be compared to the macros of the C languages: they are more flexible since they edit the code they are invoked in, but they are also dangerous to use. In general, it is not recommended to use them, unless when designing a library of generic code for HDLRuby.
1937
1952
 
1938
1953
 
1954
+ ## Software code
1955
+
1956
+ It is possible to describe hardware-software components in HDLRuby using the `program` construct that encapsulates some software code a provides an interface for communicating with the hardware. This interface is composed of three kinds of components:
1957
+
1958
+ * The activation events: 1-bit signal that triggers the execution of a given software function when the switch from 0 to 1 (or for negative ones, from 1 to 0).
1959
+
1960
+ * The reading ports: bit-vector signals that can be read from a software function.
1961
+
1962
+ * The writing ports: bit-vector signals that can be written from a software function.
1963
+
1964
+ __Note:__
1965
+
1966
+ The same signal can be used at the same time by multiple ports for both reading and writing, however, from the software point of view, it will correspond to two different ports.
1967
+
1968
+ ### Declaring a software component
1969
+
1970
+ A software component is declared like a hardware process within a system. The syntax is the following:
1971
+
1972
+ ```ruby
1973
+ program(<programming language>, <function name>) do
1974
+ <location of the software files and description of its interface>
1975
+ end
1976
+ ```
1977
+
1978
+ In the code above, `programming language` is a symbol representing the programming language used for the software. For now, only two languages are supported:
1979
+
1980
+ * `:ruby`: for programs in Ruby.
1981
+
1982
+ * `:c`: for programs in C. However, for this case, any language that can be compiled to a shared library linkable with C is supported.
1983
+
1984
+ The `function name` parameter indicates which function is to be executed when an activation event occurs. There can be only one such function per program, but any number of programs can be declared inside the same module.
1985
+
1986
+ The `location of the software files and description of its interface` part can include the following declaration statements:
1987
+
1988
+ * `actport <list of events>`: for declaring the list of events that activates the program, i.e., that will trigger the execution of the program's start function.
1989
+
1990
+ * `inport <list of port names associated with a signal>`: for declaring the list of ports that the software code of the program can read.
1991
+
1992
+ * `outport <list of port names associated with a signal>`: for declaring the list of ports that the software code of the program can write to.
1993
+
1994
+ * `code <list of filenames>`: for declaring the source code files.
1995
+
1996
+ For example the following declares a program in the Ruby language whose start function is `echo` that is activated on the positive edge of signal `req`, has a read port called `inP` that is connected to signal `count` and a write port called `outP` that is connected to signal `val`, finally the code of this program is given in a file named `echo.rb`:
1997
+
1998
+ ```ruby
1999
+ system :my_system do
2000
+ inner :req
2001
+ [8].inner :count, :val
2002
+
2003
+ ...
2004
+
2005
+ program(:ruby,'echo') do
2006
+ actport req.posedge
2007
+ inport inP: count
2008
+ outport outP: val
2009
+ code "echo.rb"
2010
+ end
2011
+ end
2012
+ ```
2013
+
2014
+
2015
+ __Note:__
2016
+
2017
+ The size of the input and output ports is one of the signals they give access to. However, from the software side, their values are converted to `long long` types.
2018
+
2019
+
2020
+
2021
+ ### About the software code used in HDLRuby programs
2022
+
2023
+ #### Location and format of the files
2024
+
2025
+ The file names indicating the software code to use must indicate the path to these files relative to where the HDLRuby tools are used. In the example above, that would mean that the `echo.rb` program must be in the same directory as the HDLRuby description. If this code were to be into a `ruby` directory under the current directory, the declaration would become: `code "ruby/echo.rb"`.
2026
+ For the Ruby language, any number of source files can be declared, and plain Ruby code can be used as is. However, for the C language, the software code must first be compiled, and it is the resulting file that must be declared in the code declaration. For example, if for the example above, C had to be used, then the program description would be the following:
2027
+
2028
+ ```ruby
2029
+ program(:c, :echo) do
2030
+ actport req.posedge
2031
+ inport inP: count
2032
+ outport outP: val
2033
+ code "echo"
2034
+ end
2035
+ ```
2036
+
2037
+ Then, for this program to work, the C code must be compiled to a file named `echo`. Please notice that, in the example, the extension is omitted, to allow the system to look for the valid file type (e.g., `.so` for a Linux shared library).
2038
+
2039
+ __Note:__
2040
+
2041
+ The same software file can be used for several different program constructs, however the functions it contains will be unique for the whole device.
2042
+
2043
+
2044
+ #### The hardware interface
2045
+
2046
+ From the software point of view, the hardware interface consists only of a list of ports that can either be read or written. However, the implementation of this interface depends on the language.
2047
+
2048
+ ##### For Ruby
2049
+
2050
+ For ruby, the interface is accessed by requiring the `rubyHDL` library. It gives provides the `RubyHDL` module that provides accessors to ports of the program.
2051
+ For example, the following program reads on port `inP` and writes the results on port `outP`:
2052
+
2053
+ ```ruby
2054
+ require 'rubyHDL'
2055
+
2056
+ def echo
2057
+ val = RubyHDL.inP
2058
+ RubyHDL.outP = val
2059
+ end
2060
+ ```
2061
+
2062
+ __Note:__
2063
+
2064
+ As long as a port has been declared in the HDLRuby description of the program, it will be available to the software as a module accessor without the need for any additional declaration or configuration.
2065
+
2066
+ ##### For C
2067
+
2068
+ For C (and C-compatible compiled languages), the interface is accessed by including the `cHDL.h` file. This file must be generated using the following command:
2069
+
2070
+ ```bash
2071
+ hdrcc --ch <destination project>
2072
+ ```
2073
+
2074
+ In the command above, `<destination project>` is the directory where the C code is meant to be.
2075
+
2076
+
2077
+ Once generated, this file provides the three following C functions:
2078
+
2079
+ * `void* c_get_port(const char* name)`: returns a pointer to the port whose name is passed as argument.
2080
+
2081
+ * `int c_read_port(void* port)`: reads the port whose pointer is passed as argument and returns its value.
2082
+
2083
+ * `int c_write_port(void* port, int val)`: write the value `val` to the port passed as argument.
2084
+
2085
+ For example, the following program reads on port `inP` and writes the results on port `outP`:
2086
+
2087
+ ```c
2088
+ #include "cHDL.h"
2089
+
2090
+ void echo() {
2091
+ void* inP = c_get_port("inP");
2092
+ void* outP = c_get_port("outP");
2093
+ int val;
2094
+
2095
+ val = c_read_port(inP);
2096
+ c_write_port(outP,val);
2097
+ }
2098
+ ```
2099
+
2100
+ __Note:__
2101
+
2102
+ * The command for generating the C header file for using the HDLRuby hardware interface also generates files for helping to compile the source code. Please see [compile for simulation](#compiling-the-c-code).
2103
+
2104
+ * **Important:** for windows, dynamically loaded functions must be declared with the following prefix: `__declspec(dllexport)`. If this prefix is not present before each function that is used as an HDLRuby program, the simulation will not work. For example, for Windows, the function echo *must* be written as follows:
2105
+
2106
+ ```c
2107
+ #include "cHDL.h"
2108
+
2109
+ __declspec(dllexport) void echo() {
2110
+ void* inP = c_get_port("inP");
2111
+ void* outP = c_get_port("outP");
2112
+ int val;
2113
+
2114
+ val = c_read_port(inP);
2115
+ c_write_port(outP,val);
2116
+ }
2117
+ ```
2118
+
2119
+
2120
+
2121
+ #### Hardware-software co-simulation
2122
+
2123
+ As long as your programs a correctly described and the software files provided (and compiled in the case of C), the hardware-software co-simulation will be automatically performed when executing the HDLRuby simulator.
2124
+
2125
+ ##### Compiling the C code
2126
+
2127
+ While programs in Ruby can be used directly, programs in C must be compiled first. For that purpose, the required files, including the hardware interface `cHDL.h`, must be generated. This is done by using the following HDLRruby command:
2128
+
2129
+ ```bash
2130
+ hdrcc --ch <destination project>
2131
+ ```
2132
+
2133
+ In the command above, `<destination project>` is both the directory where the C code is and the name of the resulting shared library.
2134
+
2135
+ For example, if you want to compile the code located in the directory `echo` you need first to execute:
2136
+
2137
+ ```bash
2138
+ hdrcc --ch echo
2139
+ ```
2140
+
2141
+ Then, you will have to put your C files into the resulting directory and go inside it for compiling. If you have some specific needs for this compiling, or if you do not want to rely on the Ruby environment, you can compile your program there as a shared library like any other project. For example, if you are using GCC, you could type (after entering the `echo` directory):
2142
+
2143
+ ```bash
2144
+ gcc -shared -fPIC -undefined dynamic_lookup -o c_program.so echo.c
2145
+ ```
2146
+
2147
+ The command above is for compiling a single file project on a Linux system.
2148
+
2149
+ Otherwise, it may be easier to use the Ruby environment by first installing `rake-compiler` as follows:
2150
+
2151
+ ```bash
2152
+ gem install rake-compiler
2153
+ ```
2154
+
2155
+ And simply type the following command (after entering the `echo` directory):
2156
+
2157
+ ```bash
2158
+ rake compile
2159
+ ```
2160
+
2161
+ The rake tool will take care of everything for performing the compiling whatever your system may be.
2162
+
2163
+
2164
+ #### Hardware generation
2165
+
2166
+ In the current stage, HDLRuby only generates the hardware part of a description. E.g., when generating Verilog, the programs are simply being ignored. It is therefore up to the user to provide additional code for implementing the hardware-software interface. The reason is that such interfaces are target-dependent, and often comprise licensed software and IP components that cannot be integrated into HDLruby.
2167
+
2168
+ This is less a limitation than it seems since it is possible to write program constructs that wrap such accesses so that the software and HDLRuby code can be used as is in the target system. As an illustration, you can consult the example given in the tutorial: [7.6. Hardware-software co-synthesis](tuto/tutorial_sw.md#7-6-hardware-software-co-synthesis).
2169
+
2170
+
2171
+ ### Extended co-simulation
2172
+
2173
+ Since HDLRuby programs can support any compiled software, these components can also be used for executing any kind of application that is not specifically meant to be executed on the target CPU. For instance, some peripheral circuits like a keyboard or a monitor can be modeled using an HDLRuby program, as illustrated in the HDLRuby sample `with_program_ruby_cpu.rb`.
2174
+
2175
+
2176
+
2177
+ ### Development board simulation graphical interface
2178
+
2179
+ HDLRuby provides a web browser-based GUI for the simulator as an extension of the co-design platform presented in this section. This GUI is to be declared as follows within a module:
2180
+
2181
+ ```ruby
2182
+ board(:<board name>,<server port>) do
2183
+ actport <event>
2184
+ <description of the GUI>
2185
+ end
2186
+ ```
2187
+
2188
+ In the code above, `board name` is the name of the board, `server port` is the local port the browser has to connect to for accessing the GUI (by default it is set to 8000), and `event` is the event (e.g., the rising edge of a clock) that activates the synchronization of the GUI with the simulator.
2189
+
2190
+ Then the description of the GUI consists of a list of the following possible development board-oriented elements. Active elements are to be given a name and attached to a HDLRuby signal as follows:
2191
+
2192
+ ```ruby
2193
+ <element> <element name>: <HDLRuby signal>
2194
+ ```
2195
+
2196
+ The list of possible elements is as follows:
2197
+
2198
+ * `sw`: represents a set of slide switches, their number is set to match the bit-width of the attached signal.
2199
+
2200
+ * `bt`: represents a set of push buttons, their number is set to match the bit-width of the attached signal.
2201
+
2202
+ * `led`: represents a set of LEDs, their number is set to match the bit-width of the attached signal.
2203
+
2204
+ * `hexa`: represents a hexadecimal number display, its character width is set to match the width of the largest possible value of the attached signal.
2205
+
2206
+ * `digit`: represents a decimal number display, its character width is set to match the width of the largest possible positive or the smallest possible negative value of the attached signal.
2207
+
2208
+ * `scope`: represents an oscilloscope display, the vertical axis represents the value of the attached signal, its range is determined by its data type, and the horizontal axis represents the time is number of synchronization of the GUI.
2209
+
2210
+ * `row`: inserts a new line in the GUI.
2211
+
2212
+
2213
+ For example, for a GUI presenting an interface to an adder with input signals `x` and `y` and output signal `z` displayed as LEDs, a digit display, and an oscilloscope, the following description can be used:
2214
+
2215
+ ```ruby
2216
+ system :adder_with_gui do
2217
+ [8].inner :x, :y, :z
2218
+
2219
+ z <= x + y
2220
+
2221
+ inner :gui_sync
2222
+
2223
+ board(:adder_gui) do
2224
+ actport gui_sync.posedge
2225
+ sw x: x
2226
+ sw y: y
2227
+ row
2228
+ led z_led: z
2229
+ digit z_digit: z
2230
+ row
2231
+ scope z_scope: z
2232
+ end
2233
+
2234
+ timed do
2235
+ clk <= 0
2236
+ repeat(10000) do
2237
+ !10.ns
2238
+ clk <= ~clk
2239
+ end
2240
+ end
2241
+ end
2242
+ ```
2243
+
2244
+ With the code above, the GUI will show a row containing two sets of slide switches for input `x` and `y`, a row containing a set of LEDs and a digital display for showing `z`, and a row containing an oscilloscope for showing the evolution `z`.
2245
+
2246
+ This code is simulated exactly like any other HDLRuby description, e.g., the following command will start the simulation and generate a VCD wave file:
2247
+
2248
+ ```bash
2249
+ hdrcc --sim --vcd my_adder.rb my_adder
2250
+ ```
2251
+
2252
+ However, the simulator will wait until a browser connects to it. For that, you can open a web browser, and go to the local url: `http://localhost:8000`. The simulation will then start and you can interact with the GUI.
2253
+
2254
+
2255
+
1939
2256
  ## Time
1940
2257
 
1941
2258
  ### Time values
@@ -1978,7 +2295,7 @@ There are two kinds of such statements:
1978
2295
  !10.ns
1979
2296
  ```
1980
2297
 
1981
- - The `repeat` statements: such a statement takes as argument a number of iteration and a block. The execution of the block is repeated the given number times. For example, the following code executes 10 times the inversion of the `clk` signal every 10 nanoseconds:
2298
+ - The `repeat` statements: such a statement takes as argument the number of iterations and a block. The execution of the block is repeated the given number of times. For example, the following code executes 10 times the inversion of the `clk` signal every 10 nanoseconds:
1982
2299
 
1983
2300
  ```ruby
1984
2301
  repeat(10) do
@@ -2002,7 +2319,7 @@ sequential blocks. The execution semantic is the following:
2002
2319
 
2003
2320
  1. Statements are grouped in sequence until a time statement is met.
2004
2321
 
2005
- 2. The grouped sequence are executed in parallel.
2322
+ 2. The grouped sequences are executed in parallel.
2006
2323
 
2007
2324
  3. The time statement is executed.
2008
2325
 
@@ -2146,8 +2463,7 @@ In the code above, `some_sig` is a signal available in the current context. This
2146
2463
 
2147
2464
  #### Basics
2148
2465
 
2149
- In HDLRuby, a system can inherit from the content of one or several other parent systems using the `include` command as follows: `include <list of
2150
- systems>`. Such an include can be put anywhere in the body of a system, but the resulting content will be accessible only after this command.
2466
+ In HDLRuby, a system can inherit from the content of one or several other parent systems using the `include` command as follows: `include <list of systems>`. Such an include can be put anywhere in the body of a system, but the resulting content will be accessible only after this command.
2151
2467
 
2152
2468
  For example, the following code describes first a simple D-FF, and then uses it to describe a FF with an additional reversed output (`qb`):
2153
2469
 
@@ -2193,8 +2509,7 @@ __Note__:
2193
2509
 
2194
2510
  #### About inner signals and system instances
2195
2511
 
2196
- By default, inner signals and instances of a parent system are not accessible by its child systems. They can be made accessible using the `export` keyword as follows: `export <symbol 0>, <symbol 1>, ...` . For example, the following
2197
- code exports signals `clk` and `rst` and instance `dff0` of system `exporter` so that they can be accessed in child system `importer`.
2512
+ By default, inner signals and instances of a parent system are not accessible by its child systems. They can be made accessible using the `export` keyword as follows: `export <symbol 0>, <symbol 1>, ...`. For example, the following code exports signals `clk` and `rst` and instance `dff0` of system `exporter` so that they can be accessed in child system `importer`.
2198
2513
 
2199
2514
  ```ruby
2200
2515
  system :exporter do
@@ -2356,7 +2671,7 @@ end
2356
2671
  Please notice, that in the code above, the left value has been cast to a plain bit-vector to avoid the infinite recursive call of the `*` operator.
2357
2672
 
2358
2673
  Operators can also be overloaded with generic types. However, in such a case, the generic argument must also be present in the list of arguments of the overloaded operators.
2359
- For instance, let us consider the following fixed-point type of variable width (and whose decimal point is set at half of its bit range):
2674
+ For instance, let us consider the following fixed-point type of variable width (whose decimal point is set at half of its bit range):
2360
2675
 
2361
2676
  ```ruby
2362
2677
  typedef(:fixed) do |width|
@@ -2402,22 +2717,6 @@ Several enumerators are also provided for accessing the internals of the current
2402
2717
  | `each_statement` | statements of the current block |
2403
2718
  | `each_inner` | inner signals of the current block (or system if not within a block) |
2404
2719
 
2405
- ### Global signals
2406
-
2407
- HDLRuby allows the declaration of global signals the same way system's signals are declared but outside the scope of any system. After being declared, these signals are accessible directly from within any hardware construct.
2408
-
2409
- To ease the design of standardized libraries, the following global signals are defined by default:
2410
-
2411
- | signal name | signal type | signal function |
2412
- | :--- | :--- | :--- |
2413
- | `$reset` | bit | global reset |
2414
- | `$resetb` | bit | global reset complement |
2415
- | `$clk` | bit | global clock |
2416
-
2417
- __Note__:
2418
-
2419
- - When not used, the global signals are discarded.
2420
-
2421
2720
 
2422
2721
 
2423
2722
  ### Defining and executing Ruby methods within HDLRuby constructs
@@ -2497,7 +2796,7 @@ end
2497
2796
  While requiring caution, a properly designed method can be very useful for clean code reuse. For example, the following method allows to start the execution of a block after a given number of cycles:
2498
2797
 
2499
2798
  ```ruby
2500
- def after(cycles,rst = $rst, &code)
2799
+ def after(cycles, rst, &code)
2501
2800
  sub do
2502
2801
  inner :count
2503
2802
  hif rst == 1 do
@@ -2517,34 +2816,28 @@ end
2517
2816
 
2518
2817
  In the code above:
2519
2818
 
2520
- - the default initialization of `rst` to `$rst` allows resetting the counter even if no such signal is provided as an argument.
2521
-
2522
2819
  - `sub` ensures that the `count` signal does not conflict with another signal with the same name.
2523
2820
 
2524
2821
  - the `instance_eval` keyword is a standard Ruby method that executes the block passed as an argument in context.
2525
2822
 
2526
- The following is an example that switches a LED on after 1000000 clock cycles using the previously defined `after` ruby method:
2823
+ The following is an example that switches an LED on after 1000000 clock cycles using the previously defined `after` ruby method:
2527
2824
 
2528
2825
  ```ruby
2529
2826
  system :led_after do
2530
2827
  output :led
2531
- input :clk
2828
+ input :clk, :rst
2532
2829
 
2533
2830
  par(clk.posedge) do
2534
- (led <= 0).hif($rst)
2535
- after(100000) { led <= 1 }
2831
+ (led <= 0).hif(rst)
2832
+ after(100000,rst) { led <= 1 }
2536
2833
  end
2537
2834
  end
2538
2835
  ```
2539
2836
 
2540
2837
  __Note__:
2541
2838
 
2542
- - Ruby's closure still applies in HDLRuby, hence, the block sent to `after` can use the signals and instances of the current block. Moreover, the signal declared in this method will not collide with them.
2543
-
2544
-
2545
- ### Dynamic description
2839
+ - Ruby's closure still applies in HDLRuby, hence, the block sent to `after` can use the signals and instances of the current block. Moreover, the signals declared in this method will not collide with them.
2546
2840
 
2547
- When describing a system, it is possible to disconnect or completely undefine a signal or an instance.
2548
2841
 
2549
2842
 
2550
2843
  ## Extending HDLRuby
@@ -2582,11 +2875,12 @@ The following table gives the class of each construct of HDLRuby.
2582
2875
  | transmit | Transmit |
2583
2876
  | hif | If |
2584
2877
  | hcase | Case |
2878
+ | program | Program |
2585
2879
 
2586
2880
 
2587
2881
  ### Extending HDLRuby constructs locally
2588
2882
 
2589
- By local extension of a hardware construct, we mean that while the construct will be changed, all the other constructs will remain unchanged. This is achieved like in Ruby by accessing the Eigen class using the `singleton_class` method and extending it using the `class_eval` method. For example, with the following code, only system `dff` will respond to method `interface_size`:
2883
+ By local extension of a hardware construct, we mean that while the construct will be changed, all the other constructs will remain unchanged. This is achieved like with Ruby by accessing the Eigen class using the `singleton_class` method and extending it using the `class_eval` method. For example, with the following code, only system `dff` will respond to method `interface_size`:
2590
2884
 
2591
2885
  ```ruby
2592
2886
  dff.singleton_class.class_eval do
@@ -2691,7 +2985,7 @@ After the libraries are loaded, the module `Std` must be included as follows:
2691
2985
  include HDLRuby::High::Std
2692
2986
  ```
2693
2987
 
2694
- > However, `hdrcc` loads the stable components of the standard library by default, so you do not need to require nor include anything more to use them. In the current version, the stable components are the followings:
2988
+ > However, `hdrcc` loads the stable components of the standard library by default, so you do not need to require nor include anything more to use them. In the current version, the stable components are the following:
2695
2989
 
2696
2990
  - `std/clocks.rb`
2697
2991
 
@@ -2746,7 +3040,7 @@ Where:
2746
3040
  * `<clock>` is the clock to use, this argument can be omitted.
2747
3041
  * `<reset>` is the signal used to reset the counter used for waiting, this argument can be omitted.
2748
3042
 
2749
- 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.
3043
+ This statement can be used inside a clocked behavior where the clock event of the behavior is used for the counter unless specified otherwise.
2750
3044
 
2751
3045
  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.
2752
3046
 
@@ -2792,7 +3086,7 @@ A finite state machine can be declared anywhere in a system provided it is outsi
2792
3086
  fsm(<event>,<reset>,<mode>) <block>
2793
3087
  ```
2794
3088
 
2795
- Where `event` is the event (rising or falling edge of a signal) activating the state transitions, `rst` is the reset signal, and `mode` is the default execution mode and `block` is the execution block describing the states of the FSM. This last parameter can be either `:sync` for synchronous (Moore type) or `:async` for asynchronous (Mealy type).
3089
+ Where `event` is the event (rising or falling edge of a signal) activating the state transitions, `rst` is the reset signal, `mode` is the default execution mode, and `block` is the execution block describing the states of the FSM. This last parameter can be either `:sync` for synchronous (Moore type) or `:async` for asynchronous (Mealy type).
2796
3090
 
2797
3091
  The states of an FSM are described as follows:
2798
3092
 
@@ -2800,12 +3094,12 @@ The states of an FSM are described as follows:
2800
3094
  <kind>(<name>) <block>
2801
3095
  ```
2802
3096
 
2803
- Where `kind` is the kind of state, `name` is the name of the state, and `block` is the actions to execute for the corresponding state. The kinds of states are the followings:
3097
+ Where `kind` is the kind of state, `name` is the name of the state, and `block` is the actions to execute for the corresponding state. The kinds of states are the following:
2804
3098
 
2805
3099
  * reset: the state reached when resetting the FSM. This state can be forced to be asynchronous by setting the `name` argument to `:async` and forced to be synchronous by setting the `name` argument to `:sync`. By default, the `name` argument is to be omitted.
2806
- * state: the default kind of state, it will be synchronous if the FSM is synchronous or asynchronous otherwise.
2807
- * sync: the synchronous kind of state, it will be synchronous whatever the kind of FSM is used.
2808
- * async: the asynchronous kind of state, it will be asynchronous whatever the kind of FSM is used.
3100
+ * state: the default kind of state, will be synchronous if the FSM is synchronous or asynchronous otherwise.
3101
+ * sync: the synchronous kind of state, will be synchronous whatever the kind of FSM is used.
3102
+ * async: the asynchronous kind of state, will be asynchronous whatever the kind of FSM is used.
2809
3103
 
2810
3104
  In addition, it is possible to define a default action that will be executed whatever the state is using the following statement:
2811
3105
 
@@ -2853,7 +3147,7 @@ fsm(clk.posedge,rst,:sync) do
2853
3147
  end
2854
3148
  ```
2855
3149
 
2856
- __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:
3150
+ __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` may be:
2857
3151
 
2858
3152
  ```ruby
2859
3153
  state(:st_0) do
@@ -3010,11 +3304,11 @@ The enumerators can be controlled using the following methods:
3010
3304
 
3011
3305
  - `type`: returns the type of the elements accessed by the enumerator.
3012
3306
 
3013
- - `seach`: returns the current enumerator. If a block is given, performs the iteration instead of returning an enumerator.
3307
+ - `seach`: returns the current enumerator. If a block is given, it performs the iteration instead of returning an enumerator.
3014
3308
 
3015
- - `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.
3309
+ - `seach_with_index`: returns an enumerator over the elements of the current enumerator associated with their index position. If a block is given, it performs the iteration instead of returning an enumerator.
3016
3310
 
3017
- - `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.
3311
+ - `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, it performs the iteration instead of returning an enumerator.
3018
3312
 
3019
3313
  - `with_index`: identical to `seach_with_index`.
3020
3314
 
@@ -3036,7 +3330,7 @@ It is also possible to define a custom enumerator using the following command:
3036
3330
  <enum> = senumerator(<typ>,<size>) <block>
3037
3331
  ```
3038
3332
 
3039
- 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:
3333
+ Where `enum` is a Ruby variable referring to the enumerator, `typ` is the data type, `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:
3040
3334
 
3041
3335
  ```ruby
3042
3336
  bit[8][-8].inner mem: [ _h01, _h02, _h03, _h04, _h30, _h30, _h30, _h30 ]
@@ -3135,7 +3429,7 @@ With this basis, several algorithms have been implemented using enumerators and
3135
3429
 
3136
3430
  #### Shared signals
3137
3431
 
3138
- Like any other process, 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 were authorized. In standard RTL design, this limitation is overcome by implementing three-state buses, multiplexers, and arbiters. However, HDLRuby sequencers support another kind of signal called the *shared signals* that abstract the implementation details for avoiding race competition.
3432
+ Like any other process, several sequencers can't write to the same signal. This is because there would be race competition that may physically destroy the device if such operations were authorized. In standard RTL design, this limitation is overcome by implementing three-state buses, multiplexers, and arbiters. However, HDLRuby sequencers support another kind of signal called the *shared signals* that abstract the implementation details for avoiding race competition.
3139
3433
 
3140
3434
  The shared signals are declared like the other kind of signals from their type. The syntax is the following:
3141
3435
 
@@ -3149,14 +3443,14 @@ They can also have an initial (and default) value when declared as follows:
3149
3443
  <type>.shared <list of names with initialization>
3150
3444
  ```
3151
3445
 
3152
- For example, the following code declares two 8-bit shared signals `x` and `y` and two signed 16-bit shared signals initialized to 0 `u` and `v`:
3446
+ For example, the following code declares two 8-bit shared signals `x` and `y`, and two signed 16-bit shared signals initialized to 0 `u` and `v`:
3153
3447
 
3154
3448
  ```ruby
3155
3449
  [8].shared :x, :y
3156
3450
  signed[8].shared u: 0, v: 0
3157
3451
  ```
3158
3452
 
3159
- A shared signal 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:
3453
+ A shared signal 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 outside a sequencer. For example, the following code is valid:
3160
3454
 
3161
3455
  ```ruby
3162
3456
  input :clk, :start
@@ -3191,7 +3485,7 @@ This default behavior of shared signal avoids race competition but is not very u
3191
3485
  <shared signal>.select
3192
3486
  ```
3193
3487
 
3194
- 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 following code can be added after this signal is declared:
3488
+ 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 following code can be added after this signal is declared:
3195
3489
 
3196
3490
  ```ruby
3197
3491
  x.select <= 1
@@ -3203,12 +3497,12 @@ This value can be changed at runtime too. For example, instead of setting the se
3203
3497
  par(clk.posedge) { x.select <= x.select + 1 }
3204
3498
  ```
3205
3499
 
3206
- __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.
3500
+ __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.
3207
3501
 
3208
3502
 
3209
3503
  #### Arbiters
3210
3504
 
3211
- Usually, it is not the signals that we want to share, but the resources they drive. For example, in a CPU, it is an ALU that is shared as a whole rather than each of its inputs 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:
3505
+ Usually, it is not the signals that we want to share, but the resources they drive. For example, with a CPU, it is the ALU that is shared as a whole rather than each of its inputs separately. 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:
3212
3506
 
3213
3507
  ```ruby
3214
3508
  arbiter(:<name>).(<list of shared signal>)
@@ -3247,7 +3541,7 @@ end
3247
3541
  In the example, both sequencers require access to signals `x` and `y` before accessing them and then releasing the access.
3248
3542
 
3249
3543
  Requiring access does not guarantee that the access will be granted by the arbiter though. In the access is not granted, the write access will be ignored.
3250
- The default access granting policy of an arbiter is the priority in the order of sequencer declaration. I.e., if several sequencers are requiring one at the same time, then the one declared the earliest in the code gains write access. For example, with the code given above, the first sequencer has to 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 simply 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 the current sequencer, that means the access is granted, otherwise it is 0. For example the following will increase signal `x` only if write access is granted:
3544
+ The default access granting policy of an arbiter is the priority in the order of sequencer declaration. I.e., if several sequencers are requiring one at the same time, then the one declared the earliest in the code gains write access. For example, with the code given above, the first sequencer has to 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 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 the current sequencer, that means the access is granted, otherwise it is 0. For example the following will increase signal `x` only if write access is granted:
3251
3545
 
3252
3546
  ```ruby
3253
3547
  hif(ctrl_xy.acquired) { x <= x + 1 }
@@ -3259,7 +3553,7 @@ The policy of an arbiter can be changed using command policy. You can either pro
3259
3553
  ctrl_xy.policy([1,0])
3260
3554
  ```
3261
3555
 
3262
- 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 executed each time write access is actually performed. For example, in the previous code, a policy switch priorities at each access can be implemented as follows:
3556
+ 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 executed each time write access is performed. For example, in the previous code, a policy switch priorities at each access can be implemented as follows:
3263
3557
 
3264
3558
  ```ruby
3265
3559
  inner priority_xy: 0
@@ -3282,7 +3576,7 @@ ctrl_xy.policy do |acq|
3282
3576
  end
3283
3577
  ```
3284
3578
 
3285
- 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 corresponds to sequencer 0, bit 1 to sequencer 1 and so on.
3579
+ As seen in the code above, each bit of the `acq` vector is one when the corresponding sequencer requires access or 0 otherwise, bit 0 corresponds to sequencer 0, bit 1 to sequencer 1, and so on.
3286
3580
 
3287
3581
 
3288
3582
  #### Monitors
@@ -3295,7 +3589,7 @@ The monitor component is instantiated like the arbiters as follows:
3295
3589
  monitor(:<name>).(<list of shared signals>)
3296
3590
  ```
3297
3591
 
3298
- Monitors are used exactly the same ways as arbiters (including the write access granting policies) but block the execution of the sequencers that require write access until the access is granted. If we take the example of code with two sequencers given as an illustration of arbiter usage, replacing the arbiter with 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:
3592
+ Monitors are used the same ways as arbiters (including the write access granting policies) but block the execution of the sequencers that require write access until the access is granted. If we take the example of code with two sequencers given as an illustration of arbiter usage, replacing the arbiter with 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:
3299
3593
 
3300
3594
  ```ruby
3301
3595
  monitor(:ctrl_xy).(x,y)
@@ -3331,7 +3625,7 @@ end
3331
3625
 
3332
3626
  ### Sequencer-specific function: `std/sequencer_func.rb`
3333
3627
 
3334
- HDLRuby function defined by `hdef` can be used in sequencer like any other HDLRuyby construct. But like the process constructs `hif` and so on, the body of these functions cannot include any sequencer-specific constructs.
3628
+ HDLRuby function defined by `hdef` can be used in a sequencer like any other HDLRuyby construct. But like the process constructs `hif` and so on, the body of these functions cannot include any sequencer-specific constructs.
3335
3629
 
3336
3630
  However, it is possible to define functions that do support the sequencer constructs using `sdef` instead of `hdef` as follows:
3337
3631
 
@@ -3354,7 +3648,7 @@ end
3354
3648
 
3355
3649
  As seen in the code above, a new construct `sreturn` can be used for returning a value from anywhere inside the function.
3356
3650
 
3357
- When a recursion is present, HDLRuby automatically defines a stack for storing the return state and the arguments of the function. The size of the stack is heuristically set to the maximum number of bits of the arguments of the function when it is recursively called. For example, for the previous `fact` function, if when called, `n` is 16-bit, the stack will be able to hold 16 recursions. If this heuristic does not match the circuit's needs, the size can be forced as a second argument when defining the function. For example, the following code set the size to 32 whatever the arguments are:
3651
+ When a recursion is present, HDLRuby automatically defines a stack for storing the return state and the arguments of the function. The size of the stack is heuristically set to the maximum number of bits of the arguments of the function when it is recursively called. For example, for the previous `fact` function, if when called, `n` is 16-bit, the stack will be able to hold 16 recursions. If this heuristic does not match the circuit's needs, the size can be forced as a second argument when defining the function. For example, the following code sets the size to 32 whatever the arguments are:
3358
3652
 
3359
3653
  ```ruby
3360
3654
  sdef(:fact,32) do |n|
@@ -3633,7 +3927,7 @@ The naming convention of the samples is the following:
3633
3927
  * `<name>.rb`: default type of sample.
3634
3928
  * `<name>_gen.rb`: generic parameters are required for processing the sample.
3635
3929
  * `<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.
3636
- * `with_<name>.rb`: sample illustrating a single aspect of HDLRuby or one of its library, usually includes a benchmark.
3930
+ * `with_<name>.rb`: sample illustrating a single aspect of HDLRuby or one of its libraries, usually includes a benchmark.
3637
3931
 
3638
3932
 
3639
3933
  # Contributing