HDLRuby 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.html +2330 -2670
  3. data/README.md +391 -101
  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 +2263 -1890
  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,29 @@ __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](tuto/tutorial_sw.md) [md]
11
+
12
+ * [HDLRuby tutorial for software people](tuto/tutorial_sw.html) [html]
11
13
 
12
14
  __What's new__
13
15
 
16
+ For HDLRuby version 3.3.0:
17
+
18
+ * Remade the description of software components using the program construct.
19
+ Now the Code objects are deprecated.
20
+
21
+ * Added HW-SW co-simulation capability for Ruby and compiled C-compatible
22
+ software programs.
23
+
24
+ * Added a browser-based graphical interface simulating simulates a development board that interacts with the HDLRuby simulator.
25
+
26
+ * Updated the documentation and tutorial accordingly and fixed several typos.
27
+
28
+
14
29
  For HDLRuby version 3.2.0:
15
30
 
16
31
  * Added component for declaring BRAM and BRAM-based stacks.
17
- The goal is to efficiently allocate memories inside FPGAs.
32
+ The goal is to allocate memories inside FPGAs efficiently.
18
33
 
19
34
  * Inner code overhaul for preparing version 4.0.0
20
35
 
@@ -46,7 +61,7 @@ For HDLRuby version 3.0.0:
46
61
 
47
62
  __Install__:
48
63
 
49
- The recommended installation method is from rubygem as follows:
64
+ The recommended installation method is from rubygems as follows:
50
65
 
51
66
  ```
52
67
  gem install HDLRuby
@@ -61,7 +76,7 @@ git clone HDLRuby
61
76
  __Warning__:
62
77
 
63
78
  - 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.
79
+ - It is highly recommended to have both basic knowledge of the Ruby language and hardware description languages before using HDLRuby.
65
80
 
66
81
 
67
82
  # Compiling HDLRuby descriptions
@@ -108,7 +123,7 @@ __Notes__:
108
123
 
109
124
  * If no top system is given, it is automatically looked for from the input file.
110
125
  * 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:
126
+ * 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
127
 
113
128
  ```bash
114
129
  hdrcc --get-samples
@@ -165,7 +180,7 @@ hdrcc -I pry
165
180
 
166
181
  ## Using HDLRuby in interactive mode
167
182
 
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:
183
+ 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
184
 
170
185
  * Compile an HDLRuby module:
171
186
 
@@ -384,7 +399,7 @@ system :reg do |typ|
384
399
  end
385
400
  ```
386
401
 
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.
402
+ 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
403
 
389
404
  ```ruby
390
405
  system :dff_full, dff do
@@ -442,7 +457,7 @@ system :shifter do |n|
442
457
  end
443
458
  ```
444
459
 
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.)
460
+ 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
461
 
447
462
  ```ruby
448
463
  <type>.<direction> <list of symbols representing the signal>
@@ -493,7 +508,7 @@ end
493
508
  In the code above, there are two generic parameters,
494
509
  `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
510
 
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`.
511
+ 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
512
 
498
513
  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
514
 
@@ -501,7 +516,7 @@ While slightly longer than the previous description, this description allows dec
501
516
  sumprod(signed[32], [3,78,43,246, 3,67,1,8, 47,82,99,13, 5,77,2,4]).(:my_circuit)
502
517
  ```
503
518
 
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.
519
+ 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
520
 
506
521
  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
522
 
@@ -547,7 +562,7 @@ hdef :add do |max, x, y|
547
562
  end
548
563
  ```
549
564
 
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.
565
+ 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
566
 
552
567
  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
568
 
@@ -592,7 +607,7 @@ sat16_1000.define_operator(:+) do |x,y|
592
607
  end
593
608
  ```
594
609
 
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).
610
+ 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
611
  Then, the initial version of `sumprod` can be used with this type to achieve saturated computations as follows:
597
612
 
598
613
  ```ruby
@@ -668,7 +683,7 @@ Several constructs in HDLRuby are referred to by name, e.g., systems and signals
668
683
  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
684
  has been declared with `:hello` as the name, it will be afterward referred to by `hello`.
670
685
 
671
- ## Systems and signals
686
+ ## Systems and Signals
672
687
 
673
688
  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
689
 
@@ -676,7 +691,7 @@ A signal represents a state in a system. It has a data type and a value, the lat
676
691
 
677
692
  ### Declaring an empty system
678
693
 
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`:
694
+ 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
695
 
681
696
  ```ruby
682
697
  system(:box) {}
@@ -684,7 +699,7 @@ system(:box) {}
684
699
 
685
700
  __Notes__:
686
701
 
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:
702
+ - 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
703
 
689
704
  ```ruby
690
705
  system :box does
@@ -860,7 +875,7 @@ end
860
875
  ### Initialization of signals
861
876
  <a name="initialization"></a>
862
877
 
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:
878
+ 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
879
 
865
880
  ```ruby
866
881
  <signal name>: <intial value>
@@ -899,7 +914,7 @@ system :div2 do
899
914
 
900
915
  ```
901
916
 
902
- For robustness or, readability purpose, it is possible to add inner scope inside the existing scope using the `sub` keyword as follows:
917
+ For robustness or, readability purposes, it is possible to add an inner scope inside the existing scope using the `sub` keyword as follows:
903
918
 
904
919
  ```ruby
905
920
  sub do
@@ -981,7 +996,7 @@ end
981
996
  ```
982
997
 
983
998
  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.
999
+ 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
1000
 
986
1001
  An event represents a specific change in the state of a signal.
987
1002
  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 +1039,7 @@ system :with_sequential_behavior do
1024
1039
  end
1025
1040
  ```
1026
1041
 
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:
1042
+ 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
1043
 
1029
1044
  ```ruby
1030
1045
  system :with_sequential_behavior do
@@ -1133,7 +1148,7 @@ end
1133
1148
  ( a <= b+1 ).at(clk.posedge)
1134
1149
  ```
1135
1150
 
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:
1151
+ 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
1152
 
1138
1153
  ```ruby
1139
1154
  ( seq do
@@ -1247,8 +1262,7 @@ __Note:__
1247
1262
  ## Statements
1248
1263
 
1249
1264
  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.
1265
+ 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
1266
 
1253
1267
  __Note__:
1254
1268
 
@@ -1329,8 +1343,7 @@ end
1329
1343
 
1330
1344
  #### About loops
1331
1345
 
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).
1346
+ 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
1347
 
1335
1348
  __Notes__:
1336
1349
 
@@ -1348,10 +1361,9 @@ __Notes__:
1348
1361
  ## Types
1349
1362
  <a name="types"></a>
1350
1363
 
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.
1364
+ 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
1365
 
1354
- ### Type construction
1366
+ ### Type Construction
1355
1367
 
1356
1368
  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
1369
 
@@ -1454,9 +1466,9 @@ They include [immediate values](#immediate-values), [reference to signals](#refe
1454
1466
 
1455
1467
  ### Immediate values
1456
1468
 
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.
1469
+ 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
1470
 
1459
- The vector type specifiers are the followings:
1471
+ The vector type specifiers are the following:
1460
1472
 
1461
1473
  - `b`: `bit` type, can be omitted,
1462
1474
 
@@ -1464,7 +1476,7 @@ The vector type specifiers are the followings:
1464
1476
 
1465
1477
  - `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
1478
 
1467
- The base specifiers are the followings:
1479
+ The base specifiers are the following:
1468
1480
 
1469
1481
  - `b`: binary,
1470
1482
 
@@ -1510,8 +1522,7 @@ __Notes__:
1510
1522
 
1511
1523
  References are expressions used to designate signals or a part of signals.
1512
1524
 
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.
1525
+ 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
1526
 
1516
1527
  ```ruby
1517
1528
  # Declaration of signal sig0.
@@ -1603,7 +1614,7 @@ __Conversion operators:__
1603
1614
  | :to\_bit | cast to bit vector |
1604
1615
  | :to\_unsigned | cast to unsigned vector |
1605
1616
  | :to\_signed | cast to signed vector |
1606
- | :to\_big | cast to big endian |
1617
+ | :to\_big | cast to big-endian |
1607
1618
  | :to\_little | cast to little endian |
1608
1619
  | :reverse | reverse the bit order |
1609
1620
  | :ljust | increase width from the left, preserves the sign |
@@ -1615,7 +1626,7 @@ __Selection /concatenation operators:__
1615
1626
 
1616
1627
  | &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
1628
  | :--- | :--- |
1618
- | :[] | sub vector selection |
1629
+ | :[] | sub-vector selection |
1619
1630
  | :@[] | concatenation operator |
1620
1631
  | :. | field selection |
1621
1632
 
@@ -1693,8 +1704,8 @@ The type puns include `to_bit`, `to_unsigned`, and `to_signed` that convert expr
1693
1704
  sig.to_bit <= _b01010011
1694
1705
  ```
1695
1706
 
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`.
1707
+ 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).
1708
+ These operators comprise the bit width conversions: `ljust`, `rjust`, `zext`, and `sext`.
1698
1709
 
1699
1710
  More precisely, the bit width conversions operate as follows:
1700
1711
 
@@ -1757,7 +1768,7 @@ Concatenation and selection are done using the `[]` operator as follows:
1757
1768
  #### Implicit conversions
1758
1769
  <a name="implicit"></a>
1759
1770
 
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:
1771
+ 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
1772
 
1762
1773
  - `operator` is the operator in use
1763
1774
  - `result width` is the width of the result's type
@@ -1854,7 +1865,7 @@ __Notes__:
1854
1865
  function :one { 1 }
1855
1866
  ```
1856
1867
 
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`:
1868
+ - 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
1869
 
1859
1870
  ```ruby
1860
1871
  function :apply do |*args, &code|
@@ -1862,7 +1873,7 @@ __Notes__:
1862
1873
  end
1863
1874
  ```
1864
1875
 
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`):
1876
+ 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
1877
  ```ruby
1867
1878
  apply(x,y,z) { |v| v <= sig }
1868
1879
  ```
@@ -1915,7 +1926,7 @@ As another example, the following function will add an alternative code that gen
1915
1926
 
1916
1927
  ```ruby
1917
1928
  def too_bad
1918
- helse { $rst <= 1 }
1929
+ helse { rst <= 1 }
1919
1930
  end
1920
1931
  ```
1921
1932
 
@@ -1936,6 +1947,308 @@ end
1936
1947
  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
1948
 
1938
1949
 
1950
+ ## Software code
1951
+
1952
+ 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:
1953
+
1954
+ * 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).
1955
+
1956
+ * The reading ports: bit-vector signals that can be read from a software function.
1957
+
1958
+ * The writing ports: bit-vector signals that can be written from a software function.
1959
+
1960
+ __Note:__
1961
+
1962
+ 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.
1963
+
1964
+ ### Declaring a software component
1965
+
1966
+ A software component is declared like a hardware process within a system. The syntax is the following:
1967
+
1968
+ ```ruby
1969
+ program(<programming language>, <function name>) do
1970
+ <location of the software files and description of its interface>
1971
+ end
1972
+ ```
1973
+
1974
+ In the code above, `programming language` is a symbol representing the programming language used for the software. For now, only two languages are supported:
1975
+
1976
+ * `:ruby`: for programs in Ruby.
1977
+
1978
+ * `:c`: for programs in C. However, for this case, any language that can be compiled to a shared library linkable with C is supported.
1979
+
1980
+ 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.
1981
+
1982
+ The `location of the software files and description of its interface` part can include the following declaration statements:
1983
+
1984
+ * `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.
1985
+
1986
+ * `inport <list of port names associated with a signal>`: for declaring the list of ports that the software code of the program can read.
1987
+
1988
+ * `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.
1989
+
1990
+ * `code <list of filenames>`: for declaring the source code files.
1991
+
1992
+ 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`:
1993
+
1994
+ ```ruby
1995
+ system :my_system do
1996
+ inner :req
1997
+ [8].inner :count, :val
1998
+
1999
+ ...
2000
+
2001
+ program(:ruby,'echo') do
2002
+ actport req.posedge
2003
+ inport inP: count
2004
+ outport outP: val
2005
+ code "echo.rb"
2006
+ end
2007
+ end
2008
+ ```
2009
+
2010
+
2011
+ __Note:__
2012
+
2013
+ 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.
2014
+
2015
+
2016
+
2017
+ ### About the software code used in HDLRuby programs
2018
+
2019
+ #### Location and format of the files
2020
+
2021
+ 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"`.
2022
+ 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:
2023
+
2024
+ ```ruby
2025
+ program(:c, :echo) do
2026
+ actport req.posedge
2027
+ inport inP: count
2028
+ outport outP: val
2029
+ code "echo"
2030
+ end
2031
+ ```
2032
+
2033
+ 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).
2034
+
2035
+ __Note:__
2036
+
2037
+ The same software file can be used for several different program constructs, however the functions it contains will be unique for the whole device.
2038
+
2039
+
2040
+ #### The hardware interface
2041
+
2042
+ 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.
2043
+
2044
+ ##### For Ruby
2045
+
2046
+ 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.
2047
+ For example, the following program reads on port `inP` and writes the results on port `outP`:
2048
+
2049
+ ```ruby
2050
+ require 'rubyHDL'
2051
+
2052
+ def echo
2053
+ val = RubyHDL.inP
2054
+ RubyHDL.outP = val
2055
+ end
2056
+ ```
2057
+
2058
+ __Note:__
2059
+
2060
+ 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.
2061
+
2062
+ ##### For C
2063
+
2064
+ 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:
2065
+
2066
+ ```bash
2067
+ hdrcc --ch <destination project>
2068
+ ```
2069
+
2070
+ In the command above, `<destination project>` is the directory where the C code is meant to be.
2071
+
2072
+
2073
+ Once generated, this file provides the three following C functions:
2074
+
2075
+ * `void* c_get_port(const char* name)`: returns a pointer to the port whose name is passed as argument.
2076
+
2077
+ * `int c_read_port(void* port)`: reads the port whose pointer is passed as argument and returns its value.
2078
+
2079
+ * `int c_write_port(void* port, int val)`: write the value `val` to the port passed as argument.
2080
+
2081
+ For example, the following program reads on port `inP` and writes the results on port `outP`:
2082
+
2083
+ ```c
2084
+ #include "cHDL.h"
2085
+
2086
+ void echo() {
2087
+ void* inP = c_get_port("inP");
2088
+ void* outP = c_get_port("outP");
2089
+ int val;
2090
+
2091
+ val = c_read_port(inP);
2092
+ c_write_port(outP,val);
2093
+ }
2094
+ ```
2095
+
2096
+ __Note:__
2097
+
2098
+ * 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).
2099
+
2100
+ * **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:
2101
+
2102
+ ```c
2103
+ #include "cHDL.h"
2104
+
2105
+ __declspec(dllexport) void echo() {
2106
+ void* inP = c_get_port("inP");
2107
+ void* outP = c_get_port("outP");
2108
+ int val;
2109
+
2110
+ val = c_read_port(inP);
2111
+ c_write_port(outP,val);
2112
+ }
2113
+ ```
2114
+
2115
+
2116
+
2117
+ #### Hardware-software co-simulation
2118
+
2119
+ 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.
2120
+
2121
+ ##### Compiling the C code
2122
+
2123
+ 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:
2124
+
2125
+ ```bash
2126
+ hdrcc --ch <destination project>
2127
+ ```
2128
+
2129
+ In the command above, `<destination project>` is both the directory where the C code is and the name of the resulting shared library.
2130
+
2131
+ For example, if you want to compile the code located in the directory `echo` you need first to execute:
2132
+
2133
+ ```bash
2134
+ hdrcc --ch echo
2135
+ ```
2136
+
2137
+ 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):
2138
+
2139
+ ```bash
2140
+ gcc -shared -fPIC -undefined dynamic_lookup -o c_program.so echo.c
2141
+ ```
2142
+
2143
+ The command above is for compiling a single file project on a Linux system.
2144
+
2145
+ Otherwise, it may be easier to use the Ruby environment by first installing `rake-compiler` as follows:
2146
+
2147
+ ```bash
2148
+ gem install rake-compiler
2149
+ ```
2150
+
2151
+ And simply type the following command (after entering the `echo` directory):
2152
+
2153
+ ```bash
2154
+ rake compile
2155
+ ```
2156
+
2157
+ The rake tool will take care of everything for performing the compiling whatever your system may be.
2158
+
2159
+
2160
+ #### Hardware generation
2161
+
2162
+ 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.
2163
+
2164
+ 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).
2165
+
2166
+
2167
+ ### Extended co-simulation
2168
+
2169
+ 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`.
2170
+
2171
+
2172
+
2173
+ ### Development board simulation graphical interface
2174
+
2175
+ 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:
2176
+
2177
+ ```ruby
2178
+ board(:<board name>,<server port>) do
2179
+ actport <event>
2180
+ <description of the GUI>
2181
+ end
2182
+ ```
2183
+
2184
+ 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.
2185
+
2186
+ 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:
2187
+
2188
+ ```ruby
2189
+ <element> <element name>: <HDLRuby signal>
2190
+ ```
2191
+
2192
+ The list of possible elements is as follows:
2193
+
2194
+ * `sw`: represents a set of slide switches, their number is set to match the bit-width of the attached signal.
2195
+
2196
+ * `bt`: represents a set of push buttons, their number is set to match the bit-width of the attached signal.
2197
+
2198
+ * `led`: represents a set of LEDs, their number is set to match the bit-width of the attached signal.
2199
+
2200
+ * `hexa`: represents a hexadecimal number display, its character width is set to match the width of the largest possible value of the attached signal.
2201
+
2202
+ * `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.
2203
+
2204
+ * `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.
2205
+
2206
+ * `row`: inserts a new line in the GUI.
2207
+
2208
+
2209
+ 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:
2210
+
2211
+ ```ruby
2212
+ system :adder_with_gui do
2213
+ [8].inner :x, :y, :z
2214
+
2215
+ z <= x + y
2216
+
2217
+ inner :gui_sync
2218
+
2219
+ board(:adder_gui) do
2220
+ actport gui_sync.posedge
2221
+ sw x: x
2222
+ sw y: y
2223
+ row
2224
+ led z_led: z
2225
+ digit z_digit: z
2226
+ row
2227
+ scope z_scope: z
2228
+ end
2229
+
2230
+ timed do
2231
+ clk <= 0
2232
+ repeat(10000) do
2233
+ !10.ns
2234
+ clk <= ~clk
2235
+ end
2236
+ end
2237
+ end
2238
+ ```
2239
+
2240
+ 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`.
2241
+
2242
+ 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:
2243
+
2244
+ ```bash
2245
+ hdrcc --sim --vcd my_adder.rb my_adder
2246
+ ```
2247
+
2248
+ 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.
2249
+
2250
+
2251
+
1939
2252
  ## Time
1940
2253
 
1941
2254
  ### Time values
@@ -1978,7 +2291,7 @@ There are two kinds of such statements:
1978
2291
  !10.ns
1979
2292
  ```
1980
2293
 
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:
2294
+ - 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
2295
 
1983
2296
  ```ruby
1984
2297
  repeat(10) do
@@ -2002,7 +2315,7 @@ sequential blocks. The execution semantic is the following:
2002
2315
 
2003
2316
  1. Statements are grouped in sequence until a time statement is met.
2004
2317
 
2005
- 2. The grouped sequence are executed in parallel.
2318
+ 2. The grouped sequences are executed in parallel.
2006
2319
 
2007
2320
  3. The time statement is executed.
2008
2321
 
@@ -2146,8 +2459,7 @@ In the code above, `some_sig` is a signal available in the current context. This
2146
2459
 
2147
2460
  #### Basics
2148
2461
 
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.
2462
+ 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
2463
 
2152
2464
  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
2465
 
@@ -2193,8 +2505,7 @@ __Note__:
2193
2505
 
2194
2506
  #### About inner signals and system instances
2195
2507
 
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`.
2508
+ 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
2509
 
2199
2510
  ```ruby
2200
2511
  system :exporter do
@@ -2356,7 +2667,7 @@ end
2356
2667
  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
2668
 
2358
2669
  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):
2670
+ 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
2671
 
2361
2672
  ```ruby
2362
2673
  typedef(:fixed) do |width|
@@ -2402,22 +2713,6 @@ Several enumerators are also provided for accessing the internals of the current
2402
2713
  | `each_statement` | statements of the current block |
2403
2714
  | `each_inner` | inner signals of the current block (or system if not within a block) |
2404
2715
 
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
2716
 
2422
2717
 
2423
2718
  ### Defining and executing Ruby methods within HDLRuby constructs
@@ -2497,7 +2792,7 @@ end
2497
2792
  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
2793
 
2499
2794
  ```ruby
2500
- def after(cycles,rst = $rst, &code)
2795
+ def after(cycles, rst, &code)
2501
2796
  sub do
2502
2797
  inner :count
2503
2798
  hif rst == 1 do
@@ -2517,34 +2812,28 @@ end
2517
2812
 
2518
2813
  In the code above:
2519
2814
 
2520
- - the default initialization of `rst` to `$rst` allows resetting the counter even if no such signal is provided as an argument.
2521
-
2522
2815
  - `sub` ensures that the `count` signal does not conflict with another signal with the same name.
2523
2816
 
2524
2817
  - the `instance_eval` keyword is a standard Ruby method that executes the block passed as an argument in context.
2525
2818
 
2526
- The following is an example that switches a LED on after 1000000 clock cycles using the previously defined `after` ruby method:
2819
+ The following is an example that switches an LED on after 1000000 clock cycles using the previously defined `after` ruby method:
2527
2820
 
2528
2821
  ```ruby
2529
2822
  system :led_after do
2530
2823
  output :led
2531
- input :clk
2824
+ input :clk, :rst
2532
2825
 
2533
2826
  par(clk.posedge) do
2534
- (led <= 0).hif($rst)
2535
- after(100000) { led <= 1 }
2827
+ (led <= 0).hif(rst)
2828
+ after(100000,rst) { led <= 1 }
2536
2829
  end
2537
2830
  end
2538
2831
  ```
2539
2832
 
2540
2833
  __Note__:
2541
2834
 
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
2835
+ - 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
2836
 
2547
- When describing a system, it is possible to disconnect or completely undefine a signal or an instance.
2548
2837
 
2549
2838
 
2550
2839
  ## Extending HDLRuby
@@ -2582,11 +2871,12 @@ The following table gives the class of each construct of HDLRuby.
2582
2871
  | transmit | Transmit |
2583
2872
  | hif | If |
2584
2873
  | hcase | Case |
2874
+ | program | Program |
2585
2875
 
2586
2876
 
2587
2877
  ### Extending HDLRuby constructs locally
2588
2878
 
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`:
2879
+ 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
2880
 
2591
2881
  ```ruby
2592
2882
  dff.singleton_class.class_eval do
@@ -2691,7 +2981,7 @@ After the libraries are loaded, the module `Std` must be included as follows:
2691
2981
  include HDLRuby::High::Std
2692
2982
  ```
2693
2983
 
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:
2984
+ > 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
2985
 
2696
2986
  - `std/clocks.rb`
2697
2987
 
@@ -2746,7 +3036,7 @@ Where:
2746
3036
  * `<clock>` is the clock to use, this argument can be omitted.
2747
3037
  * `<reset>` is the signal used to reset the counter used for waiting, this argument can be omitted.
2748
3038
 
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.
3039
+ 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
3040
 
2751
3041
  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
3042
 
@@ -2792,7 +3082,7 @@ A finite state machine can be declared anywhere in a system provided it is outsi
2792
3082
  fsm(<event>,<reset>,<mode>) <block>
2793
3083
  ```
2794
3084
 
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).
3085
+ 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
3086
 
2797
3087
  The states of an FSM are described as follows:
2798
3088
 
@@ -2800,12 +3090,12 @@ The states of an FSM are described as follows:
2800
3090
  <kind>(<name>) <block>
2801
3091
  ```
2802
3092
 
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:
3093
+ 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
3094
 
2805
3095
  * 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.
3096
+ * state: the default kind of state, will be synchronous if the FSM is synchronous or asynchronous otherwise.
3097
+ * sync: the synchronous kind of state, will be synchronous whatever the kind of FSM is used.
3098
+ * async: the asynchronous kind of state, will be asynchronous whatever the kind of FSM is used.
2809
3099
 
2810
3100
  In addition, it is possible to define a default action that will be executed whatever the state is using the following statement:
2811
3101
 
@@ -2853,7 +3143,7 @@ fsm(clk.posedge,rst,:sync) do
2853
3143
  end
2854
3144
  ```
2855
3145
 
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:
3146
+ __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
3147
 
2858
3148
  ```ruby
2859
3149
  state(:st_0) do
@@ -3010,11 +3300,11 @@ The enumerators can be controlled using the following methods:
3010
3300
 
3011
3301
  - `type`: returns the type of the elements accessed by the enumerator.
3012
3302
 
3013
- - `seach`: returns the current enumerator. If a block is given, performs the iteration instead of returning an enumerator.
3303
+ - `seach`: returns the current enumerator. If a block is given, it performs the iteration instead of returning an enumerator.
3014
3304
 
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.
3305
+ - `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
3306
 
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.
3307
+ - `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
3308
 
3019
3309
  - `with_index`: identical to `seach_with_index`.
3020
3310
 
@@ -3036,7 +3326,7 @@ It is also possible to define a custom enumerator using the following command:
3036
3326
  <enum> = senumerator(<typ>,<size>) <block>
3037
3327
  ```
3038
3328
 
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:
3329
+ 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
3330
 
3041
3331
  ```ruby
3042
3332
  bit[8][-8].inner mem: [ _h01, _h02, _h03, _h04, _h30, _h30, _h30, _h30 ]
@@ -3135,7 +3425,7 @@ With this basis, several algorithms have been implemented using enumerators and
3135
3425
 
3136
3426
  #### Shared signals
3137
3427
 
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.
3428
+ 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
3429
 
3140
3430
  The shared signals are declared like the other kind of signals from their type. The syntax is the following:
3141
3431
 
@@ -3149,14 +3439,14 @@ They can also have an initial (and default) value when declared as follows:
3149
3439
  <type>.shared <list of names with initialization>
3150
3440
  ```
3151
3441
 
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`:
3442
+ 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
3443
 
3154
3444
  ```ruby
3155
3445
  [8].shared :x, :y
3156
3446
  signed[8].shared u: 0, v: 0
3157
3447
  ```
3158
3448
 
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:
3449
+ 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
3450
 
3161
3451
  ```ruby
3162
3452
  input :clk, :start
@@ -3191,7 +3481,7 @@ This default behavior of shared signal avoids race competition but is not very u
3191
3481
  <shared signal>.select
3192
3482
  ```
3193
3483
 
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:
3484
+ 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
3485
 
3196
3486
  ```ruby
3197
3487
  x.select <= 1
@@ -3203,12 +3493,12 @@ This value can be changed at runtime too. For example, instead of setting the se
3203
3493
  par(clk.posedge) { x.select <= x.select + 1 }
3204
3494
  ```
3205
3495
 
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.
3496
+ __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
3497
 
3208
3498
 
3209
3499
  #### Arbiters
3210
3500
 
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:
3501
+ 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
3502
 
3213
3503
  ```ruby
3214
3504
  arbiter(:<name>).(<list of shared signal>)
@@ -3247,7 +3537,7 @@ end
3247
3537
  In the example, both sequencers require access to signals `x` and `y` before accessing them and then releasing the access.
3248
3538
 
3249
3539
  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:
3540
+ 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
3541
 
3252
3542
  ```ruby
3253
3543
  hif(ctrl_xy.acquired) { x <= x + 1 }
@@ -3259,7 +3549,7 @@ The policy of an arbiter can be changed using command policy. You can either pro
3259
3549
  ctrl_xy.policy([1,0])
3260
3550
  ```
3261
3551
 
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:
3552
+ 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
3553
 
3264
3554
  ```ruby
3265
3555
  inner priority_xy: 0
@@ -3282,7 +3572,7 @@ ctrl_xy.policy do |acq|
3282
3572
  end
3283
3573
  ```
3284
3574
 
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.
3575
+ 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
3576
 
3287
3577
 
3288
3578
  #### Monitors
@@ -3295,7 +3585,7 @@ The monitor component is instantiated like the arbiters as follows:
3295
3585
  monitor(:<name>).(<list of shared signals>)
3296
3586
  ```
3297
3587
 
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:
3588
+ 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
3589
 
3300
3590
  ```ruby
3301
3591
  monitor(:ctrl_xy).(x,y)
@@ -3331,7 +3621,7 @@ end
3331
3621
 
3332
3622
  ### Sequencer-specific function: `std/sequencer_func.rb`
3333
3623
 
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.
3624
+ 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
3625
 
3336
3626
  However, it is possible to define functions that do support the sequencer constructs using `sdef` instead of `hdef` as follows:
3337
3627
 
@@ -3354,7 +3644,7 @@ end
3354
3644
 
3355
3645
  As seen in the code above, a new construct `sreturn` can be used for returning a value from anywhere inside the function.
3356
3646
 
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:
3647
+ 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
3648
 
3359
3649
  ```ruby
3360
3650
  sdef(:fact,32) do |n|
@@ -3633,7 +3923,7 @@ The naming convention of the samples is the following:
3633
3923
  * `<name>.rb`: default type of sample.
3634
3924
  * `<name>_gen.rb`: generic parameters are required for processing the sample.
3635
3925
  * `<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.
3926
+ * `with_<name>.rb`: sample illustrating a single aspect of HDLRuby or one of its libraries, usually includes a benchmark.
3637
3927
 
3638
3928
 
3639
3929
  # Contributing