HDLRuby 3.9.5 → 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.
@@ -1562,10 +1562,14 @@ module HDLRuby::Low
1562
1562
  # Converts the system to Verilog code.
1563
1563
  def to_verilog
1564
1564
  # if self.base.name.to_s != "bit"
1565
+ first = self.range.first
1566
+ first = first.to_verilog if first.is_a?(Expression)
1567
+ last = self.range.last
1568
+ last = last.to_verilog if last.is_a?(Expression)
1565
1569
  if VERILOG_BASE_TYPES.include?(self.base.name.to_s)
1566
- return " #{self.base.name.to_s}[#{self.range.first}:#{self.range.last}]"
1570
+ return " #{self.base.name.to_s}[#{first}:#{last}]"
1567
1571
  end
1568
- return " [#{self.range.first}:#{self.range.last}]"
1572
+ return " [#{first}:#{last}]"
1569
1573
  end
1570
1574
  end
1571
1575
 
@@ -1630,9 +1634,9 @@ module HDLRuby::Low
1630
1634
  res = ""
1631
1635
  sels = self.select.to_verilog
1632
1636
  @choices[0..-2].each_with_index do |choice,i|
1633
- res << "#{sels} == #{i} ? #{choice.to_verilog} : "
1637
+ res << "(#{sels} == #{i} ? #{choice.to_verilog} : "
1634
1638
  end
1635
- res << @choices[-1].to_verilog
1639
+ res << @choices[-1].to_verilog + (")" * @choices[0..-2].size)
1636
1640
  return res
1637
1641
  end
1638
1642
  end
@@ -1676,6 +1680,9 @@ module HDLRuby::Low
1676
1680
  # return "#{self.type.width}'b#{str}"
1677
1681
  else
1678
1682
  str = self.content.to_verilog
1683
+ if str.length > self.type.width then
1684
+ str = str[str.length-self.type.width..-1]
1685
+ end
1679
1686
  if self.content.negative? then
1680
1687
  return "#{str.length}'sb#{str}"
1681
1688
  else
@@ -1738,7 +1745,11 @@ module HDLRuby::Low
1738
1745
 
1739
1746
  result = " " * spc # Indented based on space_count.
1740
1747
 
1741
- result << "case(#{self.value.to_verilog})\n"
1748
+ if @mode == :casez then
1749
+ result << "casez(#{self.value.to_verilog})\n"
1750
+ else
1751
+ result << "case(#{self.value.to_verilog})\n"
1752
+ end
1742
1753
 
1743
1754
  # n the case statement, each branch is partitioned by when. Process each time when.
1744
1755
  self.each_when do |whens|
@@ -2150,7 +2161,7 @@ module HDLRuby::Low
2150
2161
  inout = self.each_inout.to_a
2151
2162
 
2152
2163
  # Spelling necessary for simulation.
2153
- code = "`timescale 1ps/1ps\n\n"
2164
+ code = "`timescale 10ps/1ps\n\n"
2154
2165
 
2155
2166
  # self.properties[:verilog_name] = vname
2156
2167
  # Output the module name.
@@ -131,10 +131,10 @@ module HDLRuby::High::Std
131
131
  format = format.to_s
132
132
  width = format.size
133
133
  # For that purpose create the regular expression used to process it.
134
- prs = "([0-1]+)|(a+)|(b+)|(c+)|(d+)|(e+)|(g+)|(h+)|(i+)|(j+)|(k+)|(l+)|(m+)|(n+)|(o+)|(p+)|(q+)|(r+)|(s+)|(t+)|(u+)|(v+)|(w+)|(x+)|(y+)|(z+)"
134
+ prs = "([0-1]+)|(a+)|(b+)|(c+)|(d+)|(e+)|(f+)|(g+)|(h+)|(i+)|(j+)|(k+)|(l+)|(m+)|(n+)|(o+)|(p+)|(q+)|(r+)|(s+)|(t+)|(u+)|(v+)|(w+)|(x+)|(y+)|(z+)"
135
135
  # Check if the format is compatible with it.
136
136
  unless format =~ Regexp.new("^(#{prs})+$") then
137
- raise AnyError("Invalid format for a field: #{format}")
137
+ raise AnyError, "Invalid format for a field: #{format}"
138
138
  end
139
139
  # Split the format in fields.
140
140
  format = format.split(Regexp.new(prs)).select {|str| !str.empty?}
@@ -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
@@ -889,6 +889,34 @@ module VerilogTools
889
889
  state.indent = indent
890
890
  state.level = level
891
891
  return case_txt
892
+ when :casez
893
+ # Saves the state.
894
+ indent = state.indent
895
+ level = state.level
896
+ # Generate the hcase.
897
+ state.indent += " "
898
+ case_txt = indent + "hcasez(" + ast[1].to_HDLRuby(state) + ")\n"
899
+ # Generate the case items.
900
+ case_txt += ast[2].map do |item|
901
+ res_txt = ""
902
+ if item[0] != "default" then
903
+ # hwhen case.
904
+ res_txt += indent + "hwhen("
905
+ res_txt += item[0].map {|e| e.to_HDLRuby(state) }.join(",")
906
+ res_txt += ") do\n"
907
+ res_txt += item[1].to_HDLRuby(state)
908
+ res_txt += indent + "end\n"
909
+ else
910
+ # helse case.
911
+ res_txt += indent + "helse do\n"
912
+ res_txt += item[1].to_HDLRuby(state) + indent + "end\n"
913
+ end
914
+ res_txt
915
+ end.join
916
+ # Restore the state and return the result.
917
+ state.indent = indent
918
+ state.level = level
919
+ return case_txt
892
920
  when :blocking_assignment, :non_blocking_assignment
893
921
  return ast[0].to_HDLRuby(state)
894
922
  when :statement
@@ -1094,6 +1122,8 @@ module VerilogTools
1094
1122
  base = ast[1] ? ast[1].to_HDLRuby(state) : ""
1095
1123
  # Get the second number if any.
1096
1124
  number1 = ast[2] ? ast[2].to_HDLRuby(state) : ""
1125
+ # In HDLRuby, for now, wildcards work like z.
1126
+ number1 = number1.gsub("?","z")
1097
1127
  # Depending on the base.
1098
1128
  case base
1099
1129
  when "'b"
@@ -1220,7 +1220,7 @@ module VerilogTools
1220
1220
  CLOSE_BRA_COLON_TOKS = [ "\\" + CLOSE_BRA_TOK, COLON_TOK ]
1221
1221
  CLOSE_BRA_COLON_REX = /\G#{S}(#{CLOSE_BRA_COLON_TOKS.join("|")})/
1222
1222
 
1223
- STATEMENT_TOKS = [ IF_TOK, CASE_TOK, CASEZ_TOK, CASEX_TOK,
1223
+ STATEMENT_TOKS = [ IF_TOK, CASEZ_TOK, CASEX_TOK, CASE_TOK,
1224
1224
  FOREVER_TOK, REPEAT_TOK, WHILE_TOK, FOR_TOK,
1225
1225
  WAIT_TOK, RIGHT_ARROW_TOK, DISABLE_TOK,
1226
1226
  ASSIGN_TOK, FORCE_TOK, DEASSIGN_TOK, RELEASE_TOK ]
@@ -1,3 +1,3 @@
1
1
  module HDLRuby
2
- VERSION = "3.9.5"
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.5
4
+ version: 3.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lovic Gauthier
@@ -193,11 +193,14 @@ files:
193
193
  - lib/HDLRuby/hdr_samples/tuple.rb
194
194
  - lib/HDLRuby/hdr_samples/type_minmax_bench.rb
195
195
  - lib/HDLRuby/hdr_samples/verilog_parser_bench.rb
196
+ - lib/HDLRuby/hdr_samples/with_assign_to_slice.rb
197
+ - lib/HDLRuby/hdr_samples/with_auto_connect.rb
196
198
  - lib/HDLRuby/hdr_samples/with_board.rb
197
199
  - lib/HDLRuby/hdr_samples/with_board_sequencer.rb
198
200
  - lib/HDLRuby/hdr_samples/with_bram.rb
199
201
  - lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb
200
202
  - lib/HDLRuby/hdr_samples/with_bram_stack.rb
203
+ - lib/HDLRuby/hdr_samples/with_casez.rb
201
204
  - lib/HDLRuby/hdr_samples/with_casts.rb
202
205
  - lib/HDLRuby/hdr_samples/with_channel.rb
203
206
  - lib/HDLRuby/hdr_samples/with_channel_other.rb
@@ -210,12 +213,15 @@ files:
210
213
  - lib/HDLRuby/hdr_samples/with_def.rb
211
214
  - lib/HDLRuby/hdr_samples/with_define_operator.rb
212
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
213
218
  - lib/HDLRuby/hdr_samples/with_fixpoint.rb
214
219
  - lib/HDLRuby/hdr_samples/with_fixpoint_adv.rb
215
220
  - lib/HDLRuby/hdr_samples/with_fsm.rb
216
221
  - lib/HDLRuby/hdr_samples/with_function_generator.rb
217
222
  - lib/HDLRuby/hdr_samples/with_generic_in_generic.rb
218
223
  - lib/HDLRuby/hdr_samples/with_handshake.rb
224
+ - lib/HDLRuby/hdr_samples/with_hbreak.rb
219
225
  - lib/HDLRuby/hdr_samples/with_henumerable.rb
220
226
  - lib/HDLRuby/hdr_samples/with_init.rb
221
227
  - lib/HDLRuby/hdr_samples/with_instance.rb
@@ -502,7 +508,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
502
508
  - !ruby/object:Gem::Version
503
509
  version: '0'
504
510
  requirements: []
505
- rubygems_version: 4.0.14
511
+ rubygems_version: 4.0.20
506
512
  specification_version: 4
507
513
  summary: HDLRuby is a library for describing and simulating digital electronic systems.
508
514
  test_files: []