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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00a784914e79391b0aa065086641989892907de384b64b3b43b221587076fcf4
4
- data.tar.gz: b53f9aa4f668cd8a736f476b4c8b86572ec8572f00f09ba85bfd484e67ff3fc6
3
+ metadata.gz: d8c62653a5b0c4fa2e8a42e0c1198d3a0e714be890e4caf80058532150117b51
4
+ data.tar.gz: 6ec87f18f390bebb88d19bffce01a6ab7420d9f82777685d4ec330d0b5f2be34
5
5
  SHA512:
6
- metadata.gz: 0e35ec948e04837424e7a2992a9f06aa15d580305c68688bdf22270b73b762f759bb7c76785f3866dd2abc25a1eaf6835005e622467458e2b9ad04134839ab62
7
- data.tar.gz: 3a3a557df353dff6b0203dcbc28fc3231d76fd6a7b7b29853061ac5451dc9a375f272f46adbb8b9ad4a838992f27097c443f0817c19d565103c2ffb0a0d343bf
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
- mmediate 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.
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
- These behave the same way as their Ruby counterparts.
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 instruction decoders.
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
@@ -75,5 +75,8 @@ system :with_values do
75
75
  !10.ns
76
76
  v8 <= _CST
77
77
  !10.ns
78
+ v8 <= _8b1
79
+ v16 <= _16hx
80
+ !10.ns
78
81
  end
79
82
  end
@@ -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", "z", "Z", "o", "d", "h"].include?(type) then
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)
@@ -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
@@ -1,3 +1,3 @@
1
1
  module HDLRuby
2
- VERSION = "3.9.6"
2
+ VERSION = "3.9.7"
3
3
  end
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.6
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.18
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: []