rvvm 0.9.2 → 0.9.4

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: bfe48fe0908436378978c1f713512eef964526caa955f0c20d6c63b866d5bcac
4
- data.tar.gz: 6d197fb0b236b3a8bde5c058db531593e551b97a6c8b71429c7aa302061d5d68
3
+ metadata.gz: 23fecb22e1dceb684c808440d5d88e14e288e3001287a50435acfa57baedad5c
4
+ data.tar.gz: 88b6836f137f99529ba872045ab934cc618fcf71420e674117a0856b225dce63
5
5
  SHA512:
6
- metadata.gz: ec6fe8c155ffa528e13b0c443e8361b648fb5ab94e3230e6257fad0c10a16fa338e53cbda53b57b83186902fcb9aa03c486609e73a04fc4d8b51a5ab86542fa9
7
- data.tar.gz: bd555309f858e5bb274b03cdd929bbbbbac26042e634e9812a8f974c524d82a603cd735bfc9d4e01a2dd468d9245eab7534be4ce749833e84e7918929369bb8f
6
+ metadata.gz: 3197267e3a5f1f713167837ed16ff1410d7aea0429e031c60a78cd3f85b4aea88b200c0bcbe5bd2174de75182119fff227d08bc79eaff720c73654d2f095e6ae
7
+ data.tar.gz: 36f3c3f230eb785626b16f8b6200bd0277fe7635eec3982f6ef1fe2bf0ee7346fa531b7ee740cd987f8428c5cda7c2d73bc25370b0ef19ea014797b1fca4cdd9
data/CHANGELOG.md CHANGED
@@ -47,16 +47,70 @@
47
47
 
48
48
  1. Test list parsing and batch simulation
49
49
  2. Unit tests
50
- 3. CLI log graphics
50
+ 3. CLI log graphic
51
51
 
52
52
  ## [0.9.1] - 2024-09-16
53
53
 
54
- ### Fixes
54
+ ### Fixes:
55
55
 
56
- 1. Fixed rvvm exacutable being excluded by gemspec
56
+ 1. Fixed `rvvm` exacutable being excluded by gemspec
57
57
 
58
58
  ## [0.9.2] - 2024-09-16
59
59
 
60
- ### Fixes
60
+ ### Fixes:
61
+
62
+ 1. `rvvm` executable still missing after 0.9.1 update
63
+
64
+ ### TBI:
65
+
66
+ 1. Test list parsing and batch simulation
67
+ 2. Tests
68
+ 3. CLI log graphic
69
+ 4. Project config load failure handling/error message when parsing invalid json
70
+ 5. Template file generation in pwd
71
+ 6. Elaboration and simulation custom waveform trace dump file
72
+
73
+ ## [0.9.3] - 2024-09-16
74
+
75
+ ### Added:
76
+
77
+ 1. Test list parsing and batch simulation
78
+ 2. Tests
79
+ 3. Updated gitlab pipeline
80
+ 4. `sandbox` script to play with during development
81
+ 5. Code documentation
82
+
83
+ ### Fixed:
84
+
85
+ 1. Hash key conversion to symbols when parsing config json
86
+
87
+ ### TBI:
88
+
89
+ 1. CLI log graphic
90
+ 2. Project config load failure handling/error message when parsing invalid json
91
+ 3. Template file generation in pwd
92
+ 4. Elaboration and simulation custom waveform trace dump file
93
+ 5. Project template files regeneration/restoration to default
94
+ 6. Rescue on script crash due to creating a project dir that already exists
95
+
96
+ ## [0.9.4] - 2024-09-17
97
+
98
+ ### Added:
99
+
100
+ 1. More tests
101
+ 2. Cleaned up code documentation
102
+ 3. JSON::ParserError handling when loading an invalid config json
103
+ 4. Promt to overwrite an existing directory while creating project
104
+ 5. Project creation error handling
105
+
106
+ ### Fixed:
107
+
108
+ 1. Script crash due to loading invalid json config
109
+ 2. Script crash due to creating a project dir that already exists
110
+
111
+ ### TBI:
61
112
 
62
- 1. rvvm executable still missing after 0.9.1 update
113
+ 1. CLI log graphic
114
+ 2. Template file generation in pwd
115
+ 3. Elaboration and simulation custom waveform trace dump file
116
+ 4. Project template files regeneration/restoration to default
data/bin/sandbox ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # just a sandbox to play with ruby during development
5
+
6
+ require "json"
7
+
8
+ json = %(
9
+ {
10
+ "sizmaj": "bit"
11
+ "akafuka" : {
12
+ "siz": 1,
13
+ "maj": 2,
14
+ "bit": 3
15
+ }
16
+ }
17
+ )
18
+
19
+ def json_parse(data)
20
+ parsed = JSON.parse(data)
21
+ puts parsed
22
+ rescue JSON::ParserError => e
23
+ puts "Invalid JSON!\nError #{e.message}"
24
+ end
25
+
26
+ json_parse(json)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Module containing template hashes for rvvm.
3
4
  module Templates
4
5
  @templates = {}
5
6
 
@@ -49,7 +50,7 @@ module Templates
49
50
  "verbosity": "LOW",
50
51
  "defTest": " ",
51
52
  "batch": 0,
52
- "testList": " ",
53
+ "testlist": [" "],
53
54
  "args": " "
54
55
  }
55
56
  })
@@ -245,6 +246,11 @@ endpackage
245
246
  )
246
247
  }
247
248
 
249
+ # Loads template hashes.
250
+ #
251
+ # @return [Hash] template hashes
252
+ #
253
+ # @since 0.8.0
248
254
  def self.load
249
255
  @templates
250
256
  end
data/lib/rvvm/utils.rb CHANGED
@@ -1,12 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Utils module providing utilities and helper methods to rvvm.
4
+ #
5
+ # Mainly used to generate files and templates.
6
+ #
7
+ # @since 0.1.0
3
8
  module Utils
4
- def self.interpret(string, hash)
9
+ # Interpolates string.
10
+ #
11
+ # Replaces named keys `${example_key}` with provided values based on a hash.
12
+ #
13
+ # @param string [String] string to be interpolated
14
+ # @param hash [Hash] Hash to provide values to replace instead of the named keys
15
+ #
16
+ # @return [string] interpolated string
17
+ #
18
+ # @since 0.1.0
19
+ def self.interpolate(string, hash)
5
20
  string.gsub(/\$\{([^}]+)\}/) do |match|
6
21
  hash[Regexp.last_match(1).to_sym] || match
7
22
  end
8
23
  end
9
24
 
25
+ # Generates a file with a provided content.
26
+ #
27
+ # @param path [String] path of the file to be generated
28
+ # @param content [String] content of the file to be generated
29
+ #
30
+ # @return [void]
31
+ #
32
+ # @since 0.8.0
10
33
  def self.gen_file(path, content)
11
34
  File.open(path, "w") do |file|
12
35
  file.write(content)
@@ -15,16 +38,36 @@ module Utils
15
38
  puts "\nFailed to create a file!\nError #{e.message}"
16
39
  end
17
40
 
41
+ # Generates a file based on a template.
42
+ #
43
+ # @param template [Hash] hash with the template content
44
+ # @param name [String] name of the file to be generated
45
+ # @param config [Hash] template config hash for content interpolation
46
+ # @param path [String] path of the template file to be generated (excluding file name)
47
+ #
48
+ # @return [void]
49
+ #
50
+ # @since 0.8.0
18
51
  def self.gen_template(template, name = nil, config = nil, path = nil)
19
52
  temp_config = config || template[:config]
20
- content = interpret(template[:content], temp_config)
53
+ content = interpolate(template[:content], temp_config)
21
54
  filename = name || template[:file][:name]
22
55
  filepath = path || template[:file][:path]
23
56
 
24
- puts "Generating: #{filepath}/#{filename}"
57
+ puts " Generating: #{filepath}/#{filename}"
25
58
  gen_file("#{filepath}/#{filename}", content)
26
59
  end
27
60
 
61
+ # Recursively searches provided directory for a file.
62
+ #
63
+ # @param filename [String] name of the file to look for
64
+ # @param path [String] path to start search on
65
+ #
66
+ # @return [String] path of the first occurence of the file
67
+ # or
68
+ # @return [nil] if file not found
69
+ #
70
+ # @since 0.8.0
28
71
  def self.find_file_dir(filename, path)
29
72
  Dir.foreach(path) do |file|
30
73
  next if file == "."
@@ -42,6 +85,11 @@ module Utils
42
85
  nil
43
86
  end
44
87
 
88
+ # Extracts git username using git config system call.
89
+ #
90
+ # @return [String] git username
91
+ #
92
+ # @since 0.9.0
45
93
  def self.git_userame
46
94
  username = nil
47
95
  IO.popen("git config --get user.name") do |handle|
@@ -52,6 +100,15 @@ module Utils
52
100
  username
53
101
  end
54
102
 
103
+ # Checks if hash contains keys provided from an array.
104
+ #
105
+ # @param hash [Hash] hash to analyze
106
+ # @param arra [Array] array of keys to look for in the hash
107
+ #
108
+ # @return [Bolean] true if all provided keys from a hash return nil
109
+ # @return [Boolean] false if a provided key is found in the hash
110
+ #
111
+ # @since 0.9.0
55
112
  def self.all_nil?(hash, array)
56
113
  array.each do |key|
57
114
  return false if hash[key]
data/lib/rvvm/version.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Module holding current rvvm version.
3
4
  module Rvvm
4
- VERSION = "0.9.2"
5
+ # Current rvvm module version.
6
+ VERSION = "0.9.4"
5
7
  end
data/lib/rvvm.rb CHANGED
@@ -8,13 +8,28 @@ require "optparse"
8
8
  require "fileutils"
9
9
  require "json"
10
10
 
11
+ # Top level module of the rvvm cli meta tool.
12
+ #
13
+ # Handles argument parsing, project creation, template file
14
+ # generation and all interaction with Xilinx Vivado tools.
15
+ #
16
+ # Argument parsing runs on `require`, rest is run using run
17
+ #
18
+ # @example
19
+ # require "rvvm"
20
+ #
21
+ # Rvvm.run
22
+ #
23
+ # @since 0.1.0
11
24
  module Rvvm
12
25
  class Error < StandardError; end
13
26
 
27
+ # Module instance variables to hold tempaltes and project config
14
28
  @templates = Templates.load
15
29
  @config_path = nil
16
30
  @config = nil
17
31
 
32
+ # Instance variables to hold parsed args and required arg symbol list
18
33
  @args = {}
19
34
  @required_args = %i[
20
35
  version
@@ -34,6 +49,8 @@ module Rvvm
34
49
  covreport
35
50
  ]
36
51
 
52
+ # Script argument parsing block.
53
+ # Runs on loading the module using require.
37
54
  OptionParser.new do |args|
38
55
  args.on("-h", "--help", "Shows this help") do
39
56
  puts "\nRVvM - Ruby Vivado Manager\n\n"
@@ -44,16 +61,11 @@ module Rvvm
44
61
  @current_time = Time.now
45
62
  @formatted_time = @current_time.strftime("%Y-%m-%d %H:%M:%S")
46
63
 
47
-
48
64
  req_args = String.new
49
65
  @required_args.each do |arg|
50
66
  req_args << "--#{arg} "
51
67
  end
52
68
  puts "\nRequired args (at least one): #{req_args}\n\n"
53
- # puts "\nRequired args (at least one):"
54
- # @required_args.each do |arg|
55
- # puts "\t--#{arg}"
56
- # end
57
69
  exit(0)
58
70
  end
59
71
  args.on("-v", "--version", "Displays RVvM gem version") do
@@ -66,7 +78,6 @@ module Rvvm
66
78
  args.on("--pkg NAME", "Creates a SystemVerilog package template (default path: <prj dir>/design/pkg)")
67
79
  args.on("--itf NAME", "Creates a SystemVerilog interface template (default path: <prj dir>/design/itf)")
68
80
  args.on("--svfile NAME", "Creates a generic SystemVerilog file template (default path: <prj dir>/design/src)")
69
- # args.on("--here", "Speciies pwd as a path when creating a file template")
70
81
  args.on("--path PATH", "Specifies a path relative to <prj dir> when creating a file template")
71
82
  args.on("-c", "--comp", "Compile SystemVerilog sources")
72
83
  args.on("-e", "--elab", "Elaborates project")
@@ -97,22 +108,31 @@ module Rvvm
97
108
  args.on("--debug", "Script debug")
98
109
  end.parse!(into: @args)
99
110
 
100
- def self.pass_config(config)
101
- @config = config
102
- end
103
-
111
+ # Simple argument check.
112
+ #
113
+ # @return [void]
114
+ #
115
+ # @since 0.8.0
104
116
  def self.check_args
105
117
  if @args[:all]
106
118
  @args[:comp] = 1
107
119
  @args[:elab] = 1
108
120
  @args[:run] = 1
109
121
  end
122
+
123
+ # Check if a required arg is provided
110
124
  if Utils.all_nil?(@args, @required_args)
111
125
  puts "\nNo required options provided!\nFor more info use -h or --help\n"
112
- exit
126
+ exit(1)
113
127
  end
114
128
  end
115
129
 
130
+ # Argument collision handling and additional settings for
131
+ # batch simulation and dpi compilation.
132
+ #
133
+ # @return [void]
134
+ #
135
+ # @since 0.8.0
116
136
  def self.handle_args
117
137
  @args[:dpi] = 1 if @args[:all] && @config[:dpi][:dpilib] == 1
118
138
 
@@ -127,6 +147,16 @@ module Rvvm
127
147
  end
128
148
  end
129
149
 
150
+ # Shell command with debug printout.
151
+ #
152
+ # If --debug arg provided instead of calling `system`
153
+ # prints the input command.
154
+ #
155
+ # @param command [String] command to be called/printed
156
+ #
157
+ # @return [void]
158
+ #
159
+ # @since 0.8.0
130
160
  def self.execute(command)
131
161
  if @args[:debug]
132
162
  puts command
@@ -135,9 +165,28 @@ module Rvvm
135
165
  end
136
166
  end
137
167
 
168
+ # Creates a new RVvM project template in pwd with a given name.
169
+ #
170
+ # @param name [String] project name
171
+ #
172
+ # @return [void]
173
+ #
174
+ # @since 0.8.0
138
175
  def self.create_new_project(name)
139
176
  puts "\nRVvM: Generating new project: #{name} ...\n"
140
177
 
178
+ if File.exist?(name)
179
+ print " Directory #{name} already exists. Do you want to overwrite it? [y/n] "
180
+ input = gets.chomp
181
+ puts " "
182
+
183
+ if input == "y"
184
+ FileUtils.rm_rf(name)
185
+ else
186
+ exit(0)
187
+ end
188
+ end
189
+
141
190
  FileUtils.mkdir(name)
142
191
  Dir.chdir(name)
143
192
 
@@ -187,15 +236,25 @@ module Rvvm
187
236
  temp_conf[:PRJNAME] = name.upcase
188
237
  Utils.gen_template(@templates[:tbtop], "#{name}_tb_top.sv", temp_conf)
189
238
 
239
+ puts " "
190
240
  system("git init")
191
241
  system("git add .")
192
242
  system('git commit -am "Initial commit"')
193
243
 
194
- puts "\nRVvM: New project generated. ^^"
244
+ puts "\nRVvM: New project generated. ^^\n\n"
195
245
 
196
246
  exit(0)
247
+ rescue StandardError => e
248
+ puts "RVvM: Failed to create project...\n #{e.message}\n"
249
+ exit(1)
197
250
  end
198
251
 
252
+ # Loads and parses rvvmconf.json config file from
253
+ # an RVvM project rvvm directory.
254
+ #
255
+ # @return [void]
256
+ #
257
+ # @since 0.8.0
199
258
  def self.load_config
200
259
  puts "\nRVvM: Loading RVvM project config..."
201
260
 
@@ -210,14 +269,27 @@ module Rvvm
210
269
 
211
270
  @config = JSON.parse(json_file) if json_file
212
271
  @config = @config.transform_values do |v|
213
- v.transform_keys(&:to_sym)
272
+ v.is_a?(Hash) ? v.transform_keys(&:to_sym) : v
214
273
  end.transform_keys(&:to_sym)
274
+ rescue JSON::ParserError => e
275
+ puts " Invalid config json!\n\n#{e.message}"
276
+ exit(1)
215
277
  end
216
278
 
279
+ # Navigates to project top (rvvm directory of the RVvM project).
280
+ #
281
+ # @return [void]
282
+ #
283
+ # @since 0.8.0
217
284
  def self.prj_top
218
285
  Dir.chdir(@config_path)
219
286
  end
220
287
 
288
+ # Compiles project SystemVerilog sources using xvlog.
289
+ #
290
+ # @return [void]
291
+ #
292
+ # @since 0.8.0
221
293
  def self.compile
222
294
  cmd_args = @config[:compilation][:args]
223
295
  logname = @args[:complog] || File.join([@config[:project][:logDir], @config[:compilation][:logDir], @config[:compilation][:log]])
@@ -229,6 +301,12 @@ module Rvvm
229
301
  execute(cmd)
230
302
  end
231
303
 
304
+ # Compiles C/C++ sources into a shared library to use during
305
+ # elaboration and simulation using DPI-C.
306
+ #
307
+ # @return [void]
308
+ #
309
+ # @Since 0.9.0
232
310
  def self.dpi_c
233
311
  cmd_args = @config[:dpi][:args]
234
312
  dpilist = @args[:dpilist] || @config[:dpi][:list]
@@ -239,6 +317,11 @@ module Rvvm
239
317
  execute(cmd)
240
318
  end
241
319
 
320
+ # Elaborates project into a testbench snapshot using xelab.
321
+ #
322
+ # @return [void]
323
+ #
324
+ # @since 0.8.0
242
325
  def self.elaborate
243
326
  cmd_args = @config[:elaboration][:args]
244
327
  cmd_args << " -sv_lib dpi" if @args[:dpi] || @args[:dpilib] || @config[:dpi][:dpilib] == 1
@@ -256,6 +339,11 @@ module Rvvm
256
339
  execute(cmd)
257
340
  end
258
341
 
342
+ # Runs UVM test simulation on an elaborated testbench snapshot using xrun.
343
+ #
344
+ # @return [void]
345
+ #
346
+ # @since 0.8.0
259
347
  def self.run_sim
260
348
  cmd_args = @config[:simulation][:args]
261
349
  if @args[:wave]
@@ -263,10 +351,12 @@ module Rvvm
263
351
  else
264
352
  cmd_args << "-R"
265
353
  end
266
-
354
+
355
+ # Run simulaton on an array of tests.
356
+ # If in not running in batch mode testlist is an array with a single test
267
357
  test = @args[:test] || @config[:simulation][:defTest]
268
- # TODO: parse test list
269
358
  testlist = [test]
359
+ testlist = @args[:testlist] || @config[:simulation][:testlist] if @args[:batch] || @config[:simulation][:batch] == 1
270
360
 
271
361
  tb = @args[:simtb] || @args[:tb] || @config[:elaboration][:tb]
272
362
 
@@ -276,7 +366,7 @@ module Rvvm
276
366
  puts "RVvM: Running test #{i + 1}/#{testlist.size}: #{simtest}"
277
367
 
278
368
  logname = File.join([@config[:project][:logDir], @config[:simulation][:logDir], @config[:simulation][:log]])
279
- logname = Utils.interpret(logname, { testname: simtest })
369
+ logname = Utils.interpolate(logname, { testname: simtest })
280
370
 
281
371
  verb = "UVM_#{@args[:verb] || @config[:simulation][:verbosity]}"
282
372
 
@@ -285,6 +375,11 @@ module Rvvm
285
375
  end
286
376
  end
287
377
 
378
+ # Runs a pure SystemVerilog/Verilog simulation using xrun.
379
+ #
380
+ # @return [void]
381
+ #
382
+ # @since 0.9.0
288
383
  def self.run_sv
289
384
  cmd_args = @config[:simulation][:args]
290
385
  tb = @args[:simtb] || @args[:tb] || @config[:elaboration][:tb]
@@ -295,7 +390,12 @@ module Rvvm
295
390
  cmd = "xsim #{tb} -log #{logname} #{cmd_args}"
296
391
  execute(cmd)
297
392
  end
298
-
393
+
394
+ # Opens last generated waveform trace dump to inspect in Vivado GUI.
395
+ #
396
+ # @return [void]
397
+ #
398
+ # @since 0.9.0
299
399
  def self.gui
300
400
  dump = @args[:wavefile] || "#{@config[:elaboration][:tb]}.wdb"
301
401
 
@@ -303,16 +403,34 @@ module Rvvm
303
403
  execute(cmd)
304
404
  end
305
405
 
406
+ # Generates UVM test functional coverage report using xcrg.
407
+ #
408
+ # @return [void]
409
+ #
410
+ # @since 0.9.0
306
411
  def self.coverage
307
412
  cmd = "xcrg -report_format html -dir xsim.covdb"
308
413
  execute(cmd)
309
414
  end
310
415
 
416
+ # Opens last generated functional coverage report in a HTML dashboard.
417
+ #
418
+ # @return [void]
419
+ #
420
+ # @since 0.9.0
311
421
  def self.cov_report
312
422
  Dir.chdir("xcrg_func_cov_report")
313
423
  execute("./dashboard.html")
314
424
  end
315
425
 
426
+ # Generates a SystemVerilog module/interface template.
427
+ #
428
+ # @param type [String] specifies modudle/itf
429
+ # @param name [String] specifies module/itf name
430
+ #
431
+ # @return [void]
432
+ #
433
+ # @since 0.9.0
316
434
  def self.create_module(type, name)
317
435
  conf = @templates[:module][:conf]
318
436
  conf[:module] = name
@@ -330,6 +448,13 @@ module Rvvm
330
448
  exit(0)
331
449
  end
332
450
 
451
+ # Generates a SystemVerilog package template.
452
+ #
453
+ # @param name [String] specifies package name
454
+ #
455
+ # @return [void]
456
+ #
457
+ # @since 0.9.0
333
458
  def self.create_pkg(name)
334
459
  conf = @templates[:package][:conf]
335
460
  conf[:package] = name
@@ -346,6 +471,13 @@ module Rvvm
346
471
  exit(0)
347
472
  end
348
473
 
474
+ # Generates a generic SystemVerilog template file.
475
+ #
476
+ # @param name [String] specifies template name
477
+ #
478
+ # @return [void]
479
+ #
480
+ # @since 0.9.0
349
481
  def self.create_svfile(name)
350
482
  conf = @templates[:svfile][:conf]
351
483
  conf[:NAME] = name.upcase
@@ -361,6 +493,11 @@ module Rvvm
361
493
  exit(0)
362
494
  end
363
495
 
496
+ # Runs rvvm calling its methods based on provided script args.
497
+ #
498
+ # @return [void]
499
+ #
500
+ # @since 0.8.0
364
501
  def self.run
365
502
  create_new_project(@args[:new]) if @args[:new]
366
503
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rvvm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - mrbya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-16 00:00:00.000000000 Z
11
+ date: 2024-09-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: RVvM is a Ruby based meta tool to manage/compile/elaborate and run simulations
14
14
  on SystemVerilog and UVM based projects using Xilinx Vivado xvlog, xelab, xrun,
@@ -26,6 +26,7 @@ files:
26
26
  - LICENSE.txt
27
27
  - README.md
28
28
  - Rakefile
29
+ - bin/sandbox
29
30
  - exe/rvvm
30
31
  - lib/rvvm.rb
31
32
  - lib/rvvm/templates.rb