HDLRuby 3.9.6 → 3.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +156 -7
- data/lib/HDLRuby/hdr_samples/with_auto_connect.rb +40 -0
- data/lib/HDLRuby/hdr_samples/with_expr_decoder.rb +38 -0
- data/lib/HDLRuby/hdr_samples/with_expr_hif.rb +34 -0
- data/lib/HDLRuby/hdr_samples/with_hbreak.rb +42 -0
- data/lib/HDLRuby/hdr_samples/with_values.rb +3 -0
- data/lib/HDLRuby/hruby_high.rb +116 -3
- data/lib/HDLRuby/std/decoder.rb +75 -0
- data/lib/HDLRuby/std/hruby_enum.rb +103 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d8c62653a5b0c4fa2e8a42e0c1198d3a0e714be890e4caf80058532150117b51
|
|
4
|
+
data.tar.gz: 6ec87f18f390bebb88d19bffce01a6ab7420d9f82777685d4ec330d0b5f2be34
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4f88b4dea7c80c6fda808d63c718f64af2a1e2e8d6371b68ef50757347dc4d5b3232741151494e74f76251a451e03ed498fb2bb1ff85281f524a23ebf4494000
|
|
7
|
+
data.tar.gz: 49bb526022624a3654097d032ba6314b0725e7a6cbc9d4d82b71996058ba392196152c74e71d64c05a7ab5381866b95a9a357af21de3c447a3505526b6a95e4c
|
data/README.md
CHANGED
|
@@ -71,6 +71,24 @@ hdrcc --get-tuto
|
|
|
71
71
|
|
|
72
72
|
__What's New__
|
|
73
73
|
|
|
74
|
+
For HDLRuby version 3.9.6/3.9.7:
|
|
75
|
+
|
|
76
|
+
* Added the bit-level decoder and the expression decoder.
|
|
77
|
+
|
|
78
|
+
* Added `auto_connect` for letting HDLRuby looking for the signals to connect to the instances.
|
|
79
|
+
|
|
80
|
+
* Now, `hbreak` allows end of process if present in the top hif.
|
|
81
|
+
|
|
82
|
+
* Added bit extension in literals.
|
|
83
|
+
|
|
84
|
+
* Added the expression hif.
|
|
85
|
+
|
|
86
|
+
* Added the unary logic operators for bit reduction.
|
|
87
|
+
|
|
88
|
+
* Removed 'nxor' and added 'eq' instead.
|
|
89
|
+
|
|
90
|
+
* Various bug fixes.
|
|
91
|
+
|
|
74
92
|
For HDLRuby version 3.9.3/3.9.4/3.9.5:
|
|
75
93
|
|
|
76
94
|
* Improved the graphical representation of the RTL code in SVG format for faster generation and better rendering. The tool is still experimental though.
|
|
@@ -473,7 +491,7 @@ Conditional statements, common in RTL languages, are also supported in HDLRuby.
|
|
|
473
491
|
|
|
474
492
|
These include:
|
|
475
493
|
|
|
476
|
-
* `hif` / `helsif` / `helse` for `if`-like conditionals
|
|
494
|
+
* `hif` / `helsif` / `helse` for `if`-like conditionals statements and expression.
|
|
477
495
|
|
|
478
496
|
* `hcase` / `hcasez` / `hwhen` / `helse` for `case`-like conditionals
|
|
479
497
|
|
|
@@ -501,6 +519,29 @@ The conditional logic above can also be written more compactly using the `mux` e
|
|
|
501
519
|
[cout,z] <= x.as(bit[8..0]) + mux(addbsub, y, ~y + 1)
|
|
502
520
|
```
|
|
503
521
|
|
|
522
|
+
Or alternatively, the expression `hif` can be used too:
|
|
523
|
+
|
|
524
|
+
```ruby
|
|
525
|
+
[cout,z} <= x.as(bit[8..0] + hif(addbsub,~y + 1, y)
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
__Note__
|
|
529
|
+
|
|
530
|
+
* The `mux` expression orders its choices by selection value, whereas the `hif` expression puts the true case first, as expected for an if condition.
|
|
531
|
+
|
|
532
|
+
* The `hif` expressions can be cascades using the dot `.` operator.
|
|
533
|
+
For example the following code can be rewritten by a simple statement as given in the next code:
|
|
534
|
+
|
|
535
|
+
```ruby
|
|
536
|
+
hif(x<a) { z <= 1 }
|
|
537
|
+
helsif(x<b) { z <= 2 }
|
|
538
|
+
helsif(x<c) { z <= 3 }
|
|
539
|
+
helse { z <= 0 }
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
```ruby
|
|
543
|
+
z <= hif(x<a,1).(x<b,2).(x<c,3,0)
|
|
544
|
+
```
|
|
504
545
|
|
|
505
546
|
---
|
|
506
547
|
|
|
@@ -532,6 +573,43 @@ In this example:
|
|
|
532
573
|
|
|
533
574
|
It is also possible to connect only a subset of the ports at instantiation time, and to reconnect or override ports later in the code.
|
|
534
575
|
|
|
576
|
+
Also, it is possible to let HDLRuby look for the signals to connect using `auto_connect` as shown in the following example:
|
|
577
|
+
|
|
578
|
+
```ruby
|
|
579
|
+
system :adder do
|
|
580
|
+
[8].input :x, :y
|
|
581
|
+
[8].output :z
|
|
582
|
+
|
|
583
|
+
z <= x + y
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
system :using_adder do
|
|
587
|
+
|
|
588
|
+
[8].inner :x, :y, :z
|
|
589
|
+
|
|
590
|
+
adder(:my_adder).auto_connect
|
|
591
|
+
end
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
In the example above, HDLRuby will connect automatically the signals `x`, `y`, and `z` from `using_adder` to the adder `my_adder`.
|
|
595
|
+
|
|
596
|
+
Alternatively, you can ask for auto connecting specific ports by giving the port name only. For example, the above auto connection can be described as follows for signal `x`, while connection of `y` and `z` are not automatic:
|
|
597
|
+
|
|
598
|
+
```ruby
|
|
599
|
+
system :using_adder do
|
|
600
|
+
|
|
601
|
+
[8].inner :x, :y0, :z0
|
|
602
|
+
|
|
603
|
+
adder(:my_adder).(x:, y: y0, z: z0)
|
|
604
|
+
end
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
__Notes__:
|
|
608
|
+
|
|
609
|
+
* Auto connection only works if the names of the signals match exactly those of the instance.
|
|
610
|
+
|
|
611
|
+
* Auto connection will ignore the signals whose connection is not found.
|
|
612
|
+
|
|
535
613
|
---
|
|
536
614
|
|
|
537
615
|
To simulate a circuit, you must write a test bench using `timed` constructs, which describe how signals evolve over time.
|
|
@@ -2001,7 +2079,7 @@ They include [immediate values](#immediate-values), [reference to signals](#refe
|
|
|
2001
2079
|
|
|
2002
2080
|
### Immediate values
|
|
2003
2081
|
|
|
2004
|
-
|
|
2082
|
+
Immediate values in HDLRuby can represent vectors of type `bit`, `unsigned`, or `signed`, as well as `integer` or `float` numbers. They are prefixed with an underscore (`_`) and include a header indicating the vector type and the numeric base, followed by the actual number.
|
|
2005
2083
|
|
|
2006
2084
|
By default, the bit width is inferred from the length of the numeral, but it can also be explicitly specified in the header. Underscores (`_`) can be inserted anywhere within the number to improve readability—they are ignored by the parser.
|
|
2007
2085
|
|
|
@@ -2030,6 +2108,7 @@ All the following immediate values represent the value `100`, using different ba
|
|
|
2030
2108
|
```ruby
|
|
2031
2109
|
_bb01100100
|
|
2032
2110
|
_b8b110_0100
|
|
2111
|
+
_8b1100100
|
|
2033
2112
|
_u8d100
|
|
2034
2113
|
_s8d100
|
|
2035
2114
|
_uh64
|
|
@@ -2045,6 +2124,10 @@ _o144
|
|
|
2045
2124
|
|
|
2046
2125
|
__Notes__:
|
|
2047
2126
|
|
|
2127
|
+
* If the bit width given in the header is smaller than the bit width inferred from the numeral, the upper bits will be truncated. For example, the value of `_2b101` is truncated to `_b01`, i.e., one.
|
|
2128
|
+
|
|
2129
|
+
* If the bit width given in the header is larger than the bit width inferred from the numeral, the numeral is extended by duplicating the most significant bit. For example, the value of `_4b1` is extended to `_b1111`, the value of `_8h1` is extended to `_b00000001` and the value of `_5ox` is extended to `_bxxxxx`.
|
|
2130
|
+
|
|
2048
2131
|
* The form `_01100100` was previously treated as equivalent to `_b01100100`, but due to compatibility issues with recent versions of Ruby, it is now deprecated.
|
|
2049
2132
|
|
|
2050
2133
|
* You may also use Ruby-style immediate values. Their bit width will be automatically adjusted to match the data type of the expression in which they are used. Note, however, that this adjustment may change the value. For example, in the following code, sig is assigned the value `4` (not `100`):
|
|
@@ -2137,8 +2220,13 @@ __Logic and Shift Operators:__
|
|
|
2137
2220
|
| :--- | :--- |
|
|
2138
2221
|
| `&` | Bitwise/logical AND |
|
|
2139
2222
|
| `|` | Bitwise/logical OR |
|
|
2223
|
+
| `^` | Bitwise/logical XOR |
|
|
2140
2224
|
| `~` | Bitwise/logical NOT |
|
|
2225
|
+
| `.&` | Bitwise/logical AND reduction (postfix) |
|
|
2226
|
+
| `.|` | Bitwise/logical OR reduction (postfix) |
|
|
2227
|
+
| `.^` | Bitwise/logical XOR reduction (postfix) |
|
|
2141
2228
|
| `mux` | Multiplex |
|
|
2229
|
+
| `hif` | Expression if |
|
|
2142
2230
|
| `<<`/`ls` | Left shift |
|
|
2143
2231
|
| `>>`/`rs` | Right shift |
|
|
2144
2232
|
| `lr` | Left rotate |
|
|
@@ -2174,7 +2262,7 @@ __Notes__:
|
|
|
2174
2262
|
|
|
2175
2263
|
* Ruby does not allow overriding of the `&&`, `||`, or `?:` (ternary) operators, so they are not available in HDLRuby.
|
|
2176
2264
|
|
|
2177
|
-
- Instead of the `?:` operator, HDLRuby provides the more general mux (multiplexer) operator.
|
|
2265
|
+
- Instead of the `?:` operator, HDLRuby provides the more general mux (multiplexer) operator or expression hif operator.
|
|
2178
2266
|
|
|
2179
2267
|
- HDLRuby does not provide replacements for `&&` and `||`; see the [Logic and Shift Operators](#logic-and-shift-operators) section for an explanation.
|
|
2180
2268
|
|
|
@@ -2213,7 +2301,11 @@ In HDLRuby, all logic operators are bitwise. To perform Boolean logic operations
|
|
|
2213
2301
|
|
|
2214
2302
|
* Unary: `~`
|
|
2215
2303
|
|
|
2216
|
-
|
|
2304
|
+
* Unary Postfix: `.&`, `.|`, `.^`
|
|
2305
|
+
|
|
2306
|
+
The binary and unary operators behave the same way as their Ruby counterparts.
|
|
2307
|
+
|
|
2308
|
+
The unary postfix operators are specific to HDLRuby and perform the reduction of the bits of an expression using the indicated boolean operations. For example `_b101.|` results to `1` since `1 or 0 or 1=1`.
|
|
2217
2309
|
|
|
2218
2310
|
__Note__: There are no Boolean (`&&`, `||`) operators in HDLRuby for two reasons:
|
|
2219
2311
|
|
|
@@ -3759,9 +3851,11 @@ The second construct is the `before` statement that activates a block until a gi
|
|
|
3759
3851
|
|
|
3760
3852
|
## Decoder
|
|
3761
3853
|
|
|
3762
|
-
The decoder library provides a new set of control statements for easily describing
|
|
3854
|
+
The decoder library provides a new set of control statements for easily describing decoders circuits. There are three types of decoder descriptions: the procedural decoders, the bit-level decoders, and the expression decoders. They are detailed in the next sections.
|
|
3855
|
+
|
|
3856
|
+
### Procedural Decoder
|
|
3763
3857
|
|
|
3764
|
-
A decoder can be declared anywhere within a module definition using the `decoder` keyword, as shown below:
|
|
3858
|
+
A procedural decoder can be declared anywhere within a module definition using the `decoder` keyword, as shown below:
|
|
3765
3859
|
|
|
3766
3860
|
```ruby
|
|
3767
3861
|
decoder(<signal>) <block>
|
|
@@ -3802,6 +3896,38 @@ end
|
|
|
3802
3896
|
|
|
3803
3897
|
Note that field bits do not need to be contiguous. For example, field `z` in the second entry spans non-adjacent bits.
|
|
3804
3898
|
|
|
3899
|
+
### Bit-level Decoder
|
|
3900
|
+
|
|
3901
|
+
The bit-level decoder sets or resets individually a set of bit depending on the values of expressions. It takes as primary argument the list of expressions that are to be decoded, and then a cascade of arguments through the successive use of the `.()` operator as follows:
|
|
3902
|
+
|
|
3903
|
+
```ruby
|
|
3904
|
+
sig <= decoder(<list of expression>).(out0, vals0).(out1, vals1).(..)
|
|
3905
|
+
```
|
|
3906
|
+
|
|
3907
|
+
In the code above, `out0`, `out1`, and so, on are the signals whose value is to set or reset, and `vals0`, `vals1` are the corresponding sets of values that are compared to the primary arguments. If the values are equal, the corresponding signal is set, and it is reset otherwise. These values have to be given as an array of expressions, one per primary argument, but can be `nil` for indicating a don't care. For example, with the following code:
|
|
3908
|
+
|
|
3909
|
+
```ruby
|
|
3910
|
+
decoder(a,b,c).(x,[_b010]).(y,[_b110,nil,_b11]).(z,[_b100,_b01,_b11])
|
|
3911
|
+
```
|
|
3912
|
+
|
|
3913
|
+
`x` will be 1 if `a` is equal to `_b010`, and 0 otherwise; `y` will be 1 if `a` is equal to `_b110` and `c` is equal to `_b11`, and 0 otherwise; and `z` will be 1 if `a` is equal to `_b100`, `b` is equal to `_b01` and c is equal to `_b11`, and 0 otherwise.
|
|
3914
|
+
|
|
3915
|
+
It is also possible to change how the comparisons results are reduced by specifying the operator to use through the last primary argument. For example, the decoder of the previous example can be converted to one which will set the signals if any of the corresponding equalities holds as follows:
|
|
3916
|
+
|
|
3917
|
+
```ruby
|
|
3918
|
+
decoder(a,b,c,:|).(x,[_b010]).(y,[_b110,nil,_b11]).(z,[_b100,_b01,_b11])
|
|
3919
|
+
```
|
|
3920
|
+
|
|
3921
|
+
### Expression Decoder
|
|
3922
|
+
|
|
3923
|
+
The expression decoder is used as an expression and returns a bit-vector. It takes as argument a list of expressions whose first one is compared to each of the others. In case of equality, the corresponding bit of the result is set, otherwise it is reset. For example, with the following code:
|
|
3924
|
+
|
|
3925
|
+
```ruby
|
|
3926
|
+
sig <= decoder(x,5,8,9)
|
|
3927
|
+
```
|
|
3928
|
+
|
|
3929
|
+
`sig` will be `_b100` if `x` equals `5`, `_b010` if `x` equals `8`, `_b001` if `x` equals `9`, and `_b000` otherwise.
|
|
3930
|
+
|
|
3805
3931
|
|
|
3806
3932
|
## FSM
|
|
3807
3933
|
|
|
@@ -4018,7 +4144,30 @@ Parallel enumerators provide several control methods:
|
|
|
4018
4144
|
|
|
4019
4145
|
Additionaly, it is possible to exit an enumeration loop using the following command:
|
|
4020
4146
|
|
|
4021
|
-
* `hbreak`: Exits the current enumeration loop.
|
|
4147
|
+
* `hbreak`: Exits the current enumeration loop, or the current process if present in the top-level `hif` branch of a process when the condition is met. This second usage helps improve the readability of reset conditions, as shown in the following code:
|
|
4148
|
+
|
|
4149
|
+
```ruby
|
|
4150
|
+
par(clk.posedge) do
|
|
4151
|
+
hif(reset) do
|
|
4152
|
+
<do some reset work>
|
|
4153
|
+
hbreak
|
|
4154
|
+
end
|
|
4155
|
+
<normal execution>
|
|
4156
|
+
end
|
|
4157
|
+
```
|
|
4158
|
+
|
|
4159
|
+
The code above is equivalent to the following one, but it clearly shows that the reset is an exception.
|
|
4160
|
+
|
|
4161
|
+
```ruby
|
|
4162
|
+
par(clk.posdege) do
|
|
4163
|
+
hif(reset) do
|
|
4164
|
+
<do some reset work>
|
|
4165
|
+
end
|
|
4166
|
+
helse do
|
|
4167
|
+
<normanl execution>
|
|
4168
|
+
end
|
|
4169
|
+
end
|
|
4170
|
+
```
|
|
4022
4171
|
|
|
4023
4172
|
__Hardware Implementations of Enumerable Methods__
|
|
4024
4173
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# A test of auto connection.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
system :adder8 do
|
|
5
|
+
[8].input :x, :y
|
|
6
|
+
[8].output :z
|
|
7
|
+
|
|
8
|
+
z <= x + y
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
system :adder do |n|
|
|
12
|
+
[n].input :x, :y
|
|
13
|
+
[n].output :s
|
|
14
|
+
|
|
15
|
+
s <= x + y
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# A benchmark for testing the auto connection.
|
|
20
|
+
system :auto_connect_bench do
|
|
21
|
+
|
|
22
|
+
[8].inner :x, :y, :z #, :s # For checking non-existant signal
|
|
23
|
+
|
|
24
|
+
adder8(:my_adder8).auto_connect
|
|
25
|
+
adder(8).(:my_adder).auto_connect
|
|
26
|
+
|
|
27
|
+
timed do
|
|
28
|
+
x <= 0
|
|
29
|
+
y <= 0
|
|
30
|
+
!10.ns
|
|
31
|
+
x <= x + 1
|
|
32
|
+
!10.ns
|
|
33
|
+
y <= y + 1
|
|
34
|
+
!10.ns
|
|
35
|
+
x <= x + 1
|
|
36
|
+
!10.ns
|
|
37
|
+
y <= y + 1
|
|
38
|
+
!10.ns
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Test the expression decodor syntatic sugars.
|
|
2
|
+
|
|
3
|
+
# A benchmark for the expression decoder.
|
|
4
|
+
system :expr_decoder_bench do
|
|
5
|
+
[8].inner :x, :y, :z
|
|
6
|
+
inner :a,:b,:c, :u, :v, :w, :s
|
|
7
|
+
|
|
8
|
+
seq do
|
|
9
|
+
decoder(x,y,z).(u,[1,2,3]).(v,[1]).(w,[nil,nil,3])
|
|
10
|
+
[a,b,c] <= decoder(x,1,2,3)
|
|
11
|
+
decoder(x,y,z,:|).(s,[1,2,3])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
timed do
|
|
15
|
+
!10.ns
|
|
16
|
+
x <= 0
|
|
17
|
+
y <= 1
|
|
18
|
+
z <= 2
|
|
19
|
+
!10.ns
|
|
20
|
+
x <= 0
|
|
21
|
+
y <= 1
|
|
22
|
+
z <= 3
|
|
23
|
+
!10.ns
|
|
24
|
+
x <= 1
|
|
25
|
+
y <= 2
|
|
26
|
+
z <= 0
|
|
27
|
+
!10.ns
|
|
28
|
+
x <= 1
|
|
29
|
+
y <= 2
|
|
30
|
+
z <= 3
|
|
31
|
+
!10.ns
|
|
32
|
+
x <= 2
|
|
33
|
+
!10.ns
|
|
34
|
+
x <= 3
|
|
35
|
+
!10.ns
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Test the expression if syntatic sugars.
|
|
2
|
+
|
|
3
|
+
# A benchmark for the expression if.
|
|
4
|
+
system :expr_if_bench do
|
|
5
|
+
[8].inner :x, :y, :z, :a, :b, :c, :d, :u, :v, :w, :s
|
|
6
|
+
|
|
7
|
+
seq do
|
|
8
|
+
u <= hif(x < y, a, b)
|
|
9
|
+
v <= hif(x < y, a).(b)
|
|
10
|
+
w <= hif(x < y, a).(x < z, b, c)
|
|
11
|
+
s <= hif(x < y, a).(x < z, b).(y < z, c, d)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
timed do
|
|
15
|
+
!10.ns
|
|
16
|
+
a <= 1
|
|
17
|
+
b <= 2
|
|
18
|
+
c <= 3
|
|
19
|
+
d <= 4
|
|
20
|
+
x <= 0
|
|
21
|
+
y <= 1
|
|
22
|
+
z <= 2
|
|
23
|
+
!10.ns
|
|
24
|
+
x <= x + 1
|
|
25
|
+
!10.ns
|
|
26
|
+
x <= x + 1
|
|
27
|
+
!10.ns
|
|
28
|
+
x <= x + 1
|
|
29
|
+
!10.ns
|
|
30
|
+
y <= x
|
|
31
|
+
!10.ns
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
system :with_hbreak do
|
|
2
|
+
|
|
3
|
+
# The clock and reset
|
|
4
|
+
inner :clk, :rst
|
|
5
|
+
|
|
6
|
+
# A counter.
|
|
7
|
+
[8].inner :count
|
|
8
|
+
|
|
9
|
+
par(clk.posedge) do
|
|
10
|
+
hif(rst) do
|
|
11
|
+
count <= 0
|
|
12
|
+
hbreak
|
|
13
|
+
end
|
|
14
|
+
# helse { count <= count + 1 }
|
|
15
|
+
count <= count + 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
timed do
|
|
20
|
+
clk <= 0
|
|
21
|
+
rst <= 0
|
|
22
|
+
!10.ns
|
|
23
|
+
clk <= 1
|
|
24
|
+
!10.ns
|
|
25
|
+
clk <= 0
|
|
26
|
+
rst <= 1
|
|
27
|
+
!10.ns
|
|
28
|
+
clk <= 1
|
|
29
|
+
!10.ns
|
|
30
|
+
clk <= 0
|
|
31
|
+
rst <= 0
|
|
32
|
+
!10.ns
|
|
33
|
+
clk <= 1
|
|
34
|
+
!10.ns
|
|
35
|
+
64.times do
|
|
36
|
+
clk <= 0
|
|
37
|
+
!10.ns
|
|
38
|
+
clk <= 1
|
|
39
|
+
!10.ns
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/HDLRuby/hruby_high.rb
CHANGED
|
@@ -1431,7 +1431,15 @@ module HDLRuby::High
|
|
|
1431
1431
|
# NOTE:
|
|
1432
1432
|
# * the else part is defined through the helse method.
|
|
1433
1433
|
# * a behavior is created to enclose the hif.
|
|
1434
|
-
def hif(condition, mode = nil, &ruby_block)
|
|
1434
|
+
def hif(condition, mode = nil, other = nil, &ruby_block)
|
|
1435
|
+
if mode and !mode.is_a?(Symbol) then
|
|
1436
|
+
if ruby_block then
|
|
1437
|
+
raise AnyError, "Error: expression hif with a block."
|
|
1438
|
+
end
|
|
1439
|
+
# Expression hif case: 'mode' is interpreted as the
|
|
1440
|
+
# expression of the condition is true, 'other'if it is false.
|
|
1441
|
+
return EIfMaker.new(condition,mode,other)
|
|
1442
|
+
end
|
|
1435
1443
|
return if self.metaif(condition,&ruby_block)
|
|
1436
1444
|
# Ensure there is a block.
|
|
1437
1445
|
ruby_block = proc {} unless block_given?
|
|
@@ -2600,6 +2608,32 @@ module HDLRuby::High
|
|
|
2600
2608
|
end
|
|
2601
2609
|
end
|
|
2602
2610
|
end
|
|
2611
|
+
return self
|
|
2612
|
+
end
|
|
2613
|
+
|
|
2614
|
+
# Auto connects signals of the system instance.
|
|
2615
|
+
#
|
|
2616
|
+
# NOTE: the connections are looked for automatically by name in
|
|
2617
|
+
# the system the instance is placed.
|
|
2618
|
+
def auto_connect
|
|
2619
|
+
# Gather the names of the signals to connect.
|
|
2620
|
+
names = self.systemT.each_signal_with_included.map do |sig|
|
|
2621
|
+
sig.name
|
|
2622
|
+
end
|
|
2623
|
+
# Look for the right signals in the current context.
|
|
2624
|
+
signals = []
|
|
2625
|
+
High.top_user.instance_eval do
|
|
2626
|
+
names.dup.each_with_index do |name,i|
|
|
2627
|
+
begin
|
|
2628
|
+
signals << send(name)
|
|
2629
|
+
rescue NotDefinedError => e
|
|
2630
|
+
# Signal not found so no connection.
|
|
2631
|
+
names.delete(name)
|
|
2632
|
+
end
|
|
2633
|
+
end
|
|
2634
|
+
end
|
|
2635
|
+
# Do the connection.
|
|
2636
|
+
self.call(names.zip(signals).to_h)
|
|
2603
2637
|
end
|
|
2604
2638
|
|
|
2605
2639
|
# Gets an exported element (signal or system instance) by +name+.
|
|
@@ -3093,6 +3127,66 @@ module HDLRuby::High
|
|
|
3093
3127
|
|
|
3094
3128
|
|
|
3095
3129
|
|
|
3130
|
+
##
|
|
3131
|
+
# Class for building multiplexers from expression ifs.
|
|
3132
|
+
#
|
|
3133
|
+
# Note: expression if does not exist in HDLRuby, this is a syntactic
|
|
3134
|
+
# sugar.
|
|
3135
|
+
class EIfMaker
|
|
3136
|
+
# Create a new multiplexer generator from if expression with
|
|
3137
|
+
# +cond+ as boolean selection, +texpr+ the expression to use if
|
|
3138
|
+
# +cond+ is true +fexpr+ the expression to use if false.
|
|
3139
|
+
# Note: +fexpr+ can be false, it it is the case, the call operator
|
|
3140
|
+
# has to be used to give it.
|
|
3141
|
+
def initialize(cond,texpr,fexpr = nil)
|
|
3142
|
+
@cond = cond
|
|
3143
|
+
@texpr = texpr
|
|
3144
|
+
@fexpr = fexpr
|
|
3145
|
+
end
|
|
3146
|
+
|
|
3147
|
+
# Replace the expression (fexpr) to use if the condition is false.
|
|
3148
|
+
# If +epxr1+ is given, create an expression whose condition is expr0
|
|
3149
|
+
# otherwise, use expression as fexpr.
|
|
3150
|
+
def call(expr0,expr1 = nil,expr2 = nil)
|
|
3151
|
+
if @fexpr then
|
|
3152
|
+
if @fexpr.is_a?(EIfMaker) then
|
|
3153
|
+
# Complete the fexpr.
|
|
3154
|
+
@fexpr = @fexpr.call(expr0,expr1,expr2)
|
|
3155
|
+
else
|
|
3156
|
+
raise AnyError, "The expression to use if the condition is false is already set."
|
|
3157
|
+
end
|
|
3158
|
+
elsif expr1 then
|
|
3159
|
+
@fexpr = EIfMaker.new(expr0,expr1,expr2)
|
|
3160
|
+
else
|
|
3161
|
+
@fexpr = expr0
|
|
3162
|
+
end
|
|
3163
|
+
return self
|
|
3164
|
+
end
|
|
3165
|
+
|
|
3166
|
+
# Convert the expression if to an expression mux.
|
|
3167
|
+
def to_expr
|
|
3168
|
+
return HDLRuby::High.top_user.mux(@cond.to_expr == 0, @texpr.to_expr, @fexpr.to_expr)
|
|
3169
|
+
end
|
|
3170
|
+
|
|
3171
|
+
[:"-@",:"+@",:"~", :abs,
|
|
3172
|
+
:boolean, :bit, :signed, :unsigned].each do |operator|
|
|
3173
|
+
define_method(operator) do
|
|
3174
|
+
self.to_expr.send(operator)
|
|
3175
|
+
end
|
|
3176
|
+
end
|
|
3177
|
+
|
|
3178
|
+
[:"+",:"-",:"*",:"/",:"%",:"**",
|
|
3179
|
+
:"&",:"|",:"^",
|
|
3180
|
+
:"<<",:">>",# :ls,:rs,:lr,:rr, # ls, rs lr and rr are treated separately
|
|
3181
|
+
:"==",:"!=",:"<",:">",:"<=",:">="].each do |operator|
|
|
3182
|
+
define_method(operator) do |expr|
|
|
3183
|
+
self.to_expr.send(operator,expr)
|
|
3184
|
+
end
|
|
3185
|
+
end
|
|
3186
|
+
|
|
3187
|
+
end
|
|
3188
|
+
|
|
3189
|
+
|
|
3096
3190
|
##
|
|
3097
3191
|
# Module giving high-level expression properties
|
|
3098
3192
|
module HExpression
|
|
@@ -4615,7 +4709,15 @@ module HDLRuby::High
|
|
|
4615
4709
|
#
|
|
4616
4710
|
# NOTE: the else part is defined through the helse method.
|
|
4617
4711
|
# def hif(condition, mode = nil, &ruby_block)
|
|
4618
|
-
def hif(condition, mode = self.mode, &ruby_block)
|
|
4712
|
+
def hif(condition, mode = self.mode, other = nil, &ruby_block)
|
|
4713
|
+
if mode and !mode.is_a?(Symbol) then
|
|
4714
|
+
if ruby_block then
|
|
4715
|
+
raise AnyError, "Error: expression hif with a block."
|
|
4716
|
+
end
|
|
4717
|
+
# Expression hif case: 'mode' is interpreted as the
|
|
4718
|
+
# expression of the condition is true, 'other'if it is false.
|
|
4719
|
+
return EIfMaker.new(condition,mode,other)
|
|
4720
|
+
end
|
|
4619
4721
|
return if self.metaif(condition,&ruby_block)
|
|
4620
4722
|
# Ensure there is a block.
|
|
4621
4723
|
ruby_block = proc {} unless block_given?
|
|
@@ -5308,6 +5410,13 @@ module HDLRuby::High
|
|
|
5308
5410
|
end
|
|
5309
5411
|
end
|
|
5310
5412
|
|
|
5413
|
+
# Extends the NilClass to act as an empty statement.
|
|
5414
|
+
class ::NilClass
|
|
5415
|
+
# Does nothing.
|
|
5416
|
+
def hif(*args)
|
|
5417
|
+
end
|
|
5418
|
+
end
|
|
5419
|
+
|
|
5311
5420
|
# Extends the String class for computing conversion to expression.
|
|
5312
5421
|
class ::String
|
|
5313
5422
|
# # Converts to a new high-level expression.
|
|
@@ -5632,7 +5741,8 @@ module HDLRuby::High
|
|
|
5632
5741
|
# Get and check the type
|
|
5633
5742
|
# type = str[0]
|
|
5634
5743
|
type = str[1]
|
|
5635
|
-
if ["0", "1", "
|
|
5744
|
+
if ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
|
5745
|
+
"z", "Z", "o", "d", "h"].include?(type) then
|
|
5636
5746
|
# Default binary
|
|
5637
5747
|
type = "b"
|
|
5638
5748
|
else
|
|
@@ -5734,6 +5844,9 @@ module HDLRuby::High
|
|
|
5734
5844
|
# Unknown type
|
|
5735
5845
|
return nil
|
|
5736
5846
|
end
|
|
5847
|
+
# Extends by duplicating the upper bit if the width is too
|
|
5848
|
+
# large.
|
|
5849
|
+
value = value.rjust(width,value[0])
|
|
5737
5850
|
# puts "type.width=#{type.width}, value=#{value}"
|
|
5738
5851
|
# Create and return the value.
|
|
5739
5852
|
return Value.new(type,value)
|
data/lib/HDLRuby/std/decoder.rb
CHANGED
|
@@ -182,6 +182,76 @@ module HDLRuby::High::Std
|
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
|
|
185
|
+
##
|
|
186
|
+
# Class for building an expression decoder.
|
|
187
|
+
#
|
|
188
|
+
class EDecoderMaker
|
|
189
|
+
# Create a new decoder generator for input +sig+ that returns an
|
|
190
|
+
# array of bits for each value from +vals+ that matches given as
|
|
191
|
+
# subsequent arguments.
|
|
192
|
+
# Note: supports chaining using the call operator in wich case
|
|
193
|
+
# [sig,*value] is treated as a composite input signal and each set
|
|
194
|
+
# of values is given by the susequent call.
|
|
195
|
+
def initialize(sig,*values)
|
|
196
|
+
@sig = sig
|
|
197
|
+
@values = values
|
|
198
|
+
if @values.last.is_a?(::Symbol) then
|
|
199
|
+
@op = @values.pop
|
|
200
|
+
else
|
|
201
|
+
@op = :&
|
|
202
|
+
end
|
|
203
|
+
@targets = nil
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Add a decoder line in composite case.
|
|
207
|
+
# +target+ is the target bit and +set+ is the of values which sets
|
|
208
|
+
# the target
|
|
209
|
+
def call(target,set)
|
|
210
|
+
if @targets then
|
|
211
|
+
# Already composite, add the values.
|
|
212
|
+
@targets << target
|
|
213
|
+
@values << set
|
|
214
|
+
else
|
|
215
|
+
# Transform the decoder with composite values.
|
|
216
|
+
@sig = [ @sig, *@values ]
|
|
217
|
+
@targets = [ target ]
|
|
218
|
+
@values = [ set ]
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Generate the decode line.
|
|
222
|
+
target <= @sig.map.with_index do |sig,i|
|
|
223
|
+
set[i] ? (sig.to_expr == set[i]).as(HDLRuby::High.bit) : HDLRuby::High.top_user._b1
|
|
224
|
+
end.reduce(@op)
|
|
225
|
+
|
|
226
|
+
return self
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Convert the expression if to an expression mux.
|
|
230
|
+
def to_expr
|
|
231
|
+
raise "Not an expression decoder." if @targets
|
|
232
|
+
return @values.map do |set|
|
|
233
|
+
(@sig.to_expr == set).as(HDLRuby::High.bit)
|
|
234
|
+
end.to_expr
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
[:"-@",:"+@",:"~", :abs,
|
|
238
|
+
:boolean, :bit, :signed, :unsigned].each do |operator|
|
|
239
|
+
define_method(operator) do
|
|
240
|
+
self.to_expr.send(operator)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
[:"+",:"-",:"*",:"/",:"%",:"**",
|
|
245
|
+
:"&",:"|",:"^",
|
|
246
|
+
:"<<",:">>",# :ls,:rs,:lr,:rr, # ls, rs lr and rr are treated separately
|
|
247
|
+
:"==",:"!=",:"<",:">",:"<=",:">="].each do |operator|
|
|
248
|
+
define_method(operator) do |expr|
|
|
249
|
+
self.to_expr.send(operator,expr)
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
end
|
|
254
|
+
|
|
185
255
|
|
|
186
256
|
|
|
187
257
|
## Declare a new decoder.
|
|
@@ -192,6 +262,11 @@ module HDLRuby::High::Std
|
|
|
192
262
|
#
|
|
193
263
|
# If provided, +ruby_block+ the fsm is directly instantiated with it.
|
|
194
264
|
def decoder(*args, &ruby_block)
|
|
265
|
+
# Is it an expression decoder?
|
|
266
|
+
unless ruby_block then
|
|
267
|
+
# Yes.
|
|
268
|
+
return EDecoderMaker.new(*args)
|
|
269
|
+
end
|
|
195
270
|
# Sets the name if any
|
|
196
271
|
unless args[0].respond_to?(:to_expr) then
|
|
197
272
|
name = args.shift.to_sym
|
|
@@ -1261,4 +1261,107 @@ module HDLRuby::High::Std
|
|
|
1261
1261
|
end
|
|
1262
1262
|
end
|
|
1263
1263
|
|
|
1264
|
+
module BlockHBreak
|
|
1265
|
+
# Build the block by executing +ruby_block+.
|
|
1266
|
+
def build(&ruby_block)
|
|
1267
|
+
High.space_push(@namespace)
|
|
1268
|
+
cur_hbreak = true
|
|
1269
|
+
catch(:HDLRubyThrow) do
|
|
1270
|
+
@return_value = High.top_user.instance_eval(&ruby_block)
|
|
1271
|
+
cur_hbreak = false
|
|
1272
|
+
end
|
|
1273
|
+
@hbreak = true if cur_hbreak
|
|
1274
|
+
High.space_pop
|
|
1275
|
+
@return_value
|
|
1276
|
+
end
|
|
1277
|
+
|
|
1278
|
+
# # Creates and adds a new block executed in +mode+, with possible
|
|
1279
|
+
# # +name+ and built by executing +ruby_block+.
|
|
1280
|
+
# def add_block(mode = nil, name = :"", &ruby_block)
|
|
1281
|
+
# # Creates the block.
|
|
1282
|
+
# block = High.make_block(mode,name,&ruby_block)
|
|
1283
|
+
# # Adds it as a statement.
|
|
1284
|
+
# self.add_statement(block)
|
|
1285
|
+
# # Handle the breaks if any.
|
|
1286
|
+
# @hbreak = block.hbreak
|
|
1287
|
+
# # Use its return value.
|
|
1288
|
+
# return block.return_value
|
|
1289
|
+
# end
|
|
1290
|
+
|
|
1291
|
+
# Adds a +statement+.
|
|
1292
|
+
#
|
|
1293
|
+
# NOTE: TimeWait is not supported unless for TimeBlock objects.
|
|
1294
|
+
def add_statement(statement)
|
|
1295
|
+
res = super(statement)
|
|
1296
|
+
hbrk = statement.instance_variable_get(:@hbreak)
|
|
1297
|
+
@hbreak = hbrk if hbrk
|
|
1298
|
+
return res
|
|
1299
|
+
end
|
|
1300
|
+
end
|
|
1301
|
+
|
|
1302
|
+
HDLRuby::High::Block.prepend(BlockHBreak)
|
|
1303
|
+
|
|
1304
|
+
module IfHBreak
|
|
1305
|
+
# Creates a new if statement with a +condition+ that when met lead
|
|
1306
|
+
# to the execution of the block in +mode+ generated by the execution of
|
|
1307
|
+
# +ruby_block+.
|
|
1308
|
+
def initialize(condition, mode = nil, &ruby_block)
|
|
1309
|
+
super
|
|
1310
|
+
hbrk = yes.instance_variable_get(:@hbreak)
|
|
1311
|
+
@hbreak = hbrk if hbrk
|
|
1312
|
+
end
|
|
1313
|
+
|
|
1314
|
+
# Sets the no block.
|
|
1315
|
+
#
|
|
1316
|
+
# No shoud only be set once, but this is not checked here for
|
|
1317
|
+
# sake of flexibility.
|
|
1318
|
+
def no=(no)
|
|
1319
|
+
res = super(no)
|
|
1320
|
+
hbrk = no.instance_variable_get(:@hbreak)
|
|
1321
|
+
raise AnyError, "Invalid hbreak." if hbrk
|
|
1322
|
+
return res
|
|
1323
|
+
end
|
|
1324
|
+
|
|
1325
|
+
# Adds an alternative if statement (elsif) testing +next_cond+
|
|
1326
|
+
# and executing +next_yes+ when the condition is met.
|
|
1327
|
+
def add_noif(next_cond, next_yes)
|
|
1328
|
+
res = super(next_cond,next_yes)
|
|
1329
|
+
hbrk = next_yes.instance_variable_get(:@hbreak)
|
|
1330
|
+
raise AnyError, "Invalid hbreak." if hbrk
|
|
1331
|
+
return res
|
|
1332
|
+
end
|
|
1333
|
+
end
|
|
1334
|
+
|
|
1335
|
+
HDLRuby::High::If.prepend(IfHBreak)
|
|
1336
|
+
|
|
1337
|
+
module BehaviorHBreak
|
|
1338
|
+
# Creates a new behavior executing +block+ activated on a list of
|
|
1339
|
+
# +events+, possible name (of main block) +name+ and built by
|
|
1340
|
+
# executing +ruby_block+.
|
|
1341
|
+
# +mode+ can be either :seq or :par for respectively sequential or
|
|
1342
|
+
# parallel.
|
|
1343
|
+
def initialize(mode, *events, name: nil, &ruby_block)
|
|
1344
|
+
super(mode,*events, name: name, &ruby_block)
|
|
1345
|
+
if self.block.instance_variable_get(:@hbreak) then
|
|
1346
|
+
stmnt0 = self.block.each_statement.first
|
|
1347
|
+
unless stmnt0.is_a?(HDLRuby::High::If) then
|
|
1348
|
+
raise AnyError, "Unsuported usage of hbreak."
|
|
1349
|
+
end
|
|
1350
|
+
if stmnt0.no || stmnt0.each_noif.any? then
|
|
1351
|
+
raise AnyError, "Unsuported usage of hbreak."
|
|
1352
|
+
end
|
|
1353
|
+
# Extract the hif an put it as the single statement whose else
|
|
1354
|
+
# part is the current block.
|
|
1355
|
+
self.block.delete_statement!(stmnt0)
|
|
1356
|
+
self.block.parent = nil
|
|
1357
|
+
self.block.instance_variable_set(:@hbreak,false)
|
|
1358
|
+
stmnt0.no = self.block
|
|
1359
|
+
self.block = HDLRuby::High.make_block(self.block.mode) {}
|
|
1360
|
+
self.block.add_statement(stmnt0)
|
|
1361
|
+
end
|
|
1362
|
+
end
|
|
1363
|
+
end
|
|
1364
|
+
|
|
1365
|
+
HDLRuby::High::Behavior.prepend(BehaviorHBreak)
|
|
1366
|
+
|
|
1264
1367
|
end
|
data/lib/HDLRuby/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: HDLRuby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.9.
|
|
4
|
+
version: 3.9.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lovic Gauthier
|
|
@@ -194,6 +194,7 @@ files:
|
|
|
194
194
|
- lib/HDLRuby/hdr_samples/type_minmax_bench.rb
|
|
195
195
|
- lib/HDLRuby/hdr_samples/verilog_parser_bench.rb
|
|
196
196
|
- lib/HDLRuby/hdr_samples/with_assign_to_slice.rb
|
|
197
|
+
- lib/HDLRuby/hdr_samples/with_auto_connect.rb
|
|
197
198
|
- lib/HDLRuby/hdr_samples/with_board.rb
|
|
198
199
|
- lib/HDLRuby/hdr_samples/with_board_sequencer.rb
|
|
199
200
|
- lib/HDLRuby/hdr_samples/with_bram.rb
|
|
@@ -212,12 +213,15 @@ files:
|
|
|
212
213
|
- lib/HDLRuby/hdr_samples/with_def.rb
|
|
213
214
|
- lib/HDLRuby/hdr_samples/with_define_operator.rb
|
|
214
215
|
- lib/HDLRuby/hdr_samples/with_delay.rb
|
|
216
|
+
- lib/HDLRuby/hdr_samples/with_expr_decoder.rb
|
|
217
|
+
- lib/HDLRuby/hdr_samples/with_expr_hif.rb
|
|
215
218
|
- lib/HDLRuby/hdr_samples/with_fixpoint.rb
|
|
216
219
|
- lib/HDLRuby/hdr_samples/with_fixpoint_adv.rb
|
|
217
220
|
- lib/HDLRuby/hdr_samples/with_fsm.rb
|
|
218
221
|
- lib/HDLRuby/hdr_samples/with_function_generator.rb
|
|
219
222
|
- lib/HDLRuby/hdr_samples/with_generic_in_generic.rb
|
|
220
223
|
- lib/HDLRuby/hdr_samples/with_handshake.rb
|
|
224
|
+
- lib/HDLRuby/hdr_samples/with_hbreak.rb
|
|
221
225
|
- lib/HDLRuby/hdr_samples/with_henumerable.rb
|
|
222
226
|
- lib/HDLRuby/hdr_samples/with_init.rb
|
|
223
227
|
- lib/HDLRuby/hdr_samples/with_instance.rb
|
|
@@ -504,7 +508,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
504
508
|
- !ruby/object:Gem::Version
|
|
505
509
|
version: '0'
|
|
506
510
|
requirements: []
|
|
507
|
-
rubygems_version: 4.0.
|
|
511
|
+
rubygems_version: 4.0.20
|
|
508
512
|
specification_version: 4
|
|
509
513
|
summary: HDLRuby is a library for describing and simulating digital electronic systems.
|
|
510
514
|
test_files: []
|