origen_sim 0.12.0 → 0.13.0

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.
Files changed (35) hide show
  1. checksums.yaml +5 -5
  2. data/config/application.rb +17 -2
  3. data/config/shared_commands.rb +7 -0
  4. data/config/version.rb +1 -1
  5. data/ext/bridge.c +13 -3
  6. data/lib/origen_sim.rb +10 -0
  7. data/lib/origen_sim/artifacts.rb +101 -0
  8. data/lib/origen_sim/commands/build.rb +41 -9
  9. data/lib/origen_sim/heartbeat.rb +13 -1
  10. data/lib/origen_sim/origen_testers/api.rb +90 -7
  11. data/lib/origen_sim/simulation.rb +49 -4
  12. data/lib/origen_sim/simulator.rb +171 -19
  13. data/lib/origen_sim/stderr_reader.rb +19 -13
  14. data/lib/origen_sim/stdout_reader.rb +22 -16
  15. data/lib/origen_sim/tester.rb +110 -1
  16. data/lib/origen_sim_dev/dut.rb +5 -0
  17. data/pattern/test.rb +143 -0
  18. data/templates/empty.gtkw +19 -1
  19. data/templates/empty.rc +86 -0
  20. data/templates/empty.svcf +79 -9
  21. data/templates/empty.tcl +37 -9
  22. data/templates/origen_guides/simulation/app.md.erb +131 -0
  23. data/templates/origen_guides/simulation/artifacts.md.erb +115 -0
  24. data/templates/origen_guides/simulation/compiling.md.erb +190 -0
  25. data/templates/origen_guides/simulation/debugging.md.erb +135 -0
  26. data/templates/origen_guides/simulation/environment.md.erb +217 -0
  27. data/templates/origen_guides/simulation/flows.md.erb +69 -0
  28. data/templates/origen_guides/simulation/howitworks.md.erb +64 -0
  29. data/templates/origen_guides/simulation/introduction.md.erb +35 -0
  30. data/templates/origen_guides/simulation/log.md.erb +118 -0
  31. data/templates/origen_guides/simulation/patterns.md.erb +193 -0
  32. data/templates/probe.tcl.erb +3 -0
  33. data/templates/rtl_v/origen.v.erb +19 -3
  34. data/templates/web/layouts/_guides.html.erb +15 -0
  35. metadata +18 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c34ffd12e0b7df9632e5bad4dcb933cb46f88460
4
- data.tar.gz: 6690aac5bb4335ac2de29b1757249eba1be026c0
2
+ SHA256:
3
+ metadata.gz: 6b34633d6530aedd5b581ff1bda44c6e727d72b76a3288dbde6f17c272c9b4a9
4
+ data.tar.gz: 82a82bdc494d1f39e6a3e8a46361d2a21352543e0839fb96dcb4488615de5a1d
5
5
  SHA512:
6
- metadata.gz: 71a090ebaa9f1440d3052773b0823187ada5fc10aab7786081b0c8274e079c78b6aab0866d85c90e7f6193c5a243d3c98012cf99e9d13b7078a4924510e3dda2
7
- data.tar.gz: a617b1e824ef7b9c36583df618440115f35aac94462b1d9a9601f917444360729d81a26235d72bc5dd2aa91f90e398d1d240233feec2ec0d07e568ae38219d47
6
+ metadata.gz: 6af3ed9ca21d9ed459ba26e0d4f7e1c3cbb491a26563376b8151bb51dce20f8d4ec21ff0cf058f5aa349e52d058aab09ee5b81e5203b08cdda1cb1a350eaefd3
7
+ data.tar.gz: 2282439c82a90b725d3191d5ed7c61d1b1c1ade3db935f16beae43a60c202b62e78fa099d3614da5a68cfc1c5c8454e62dc05ee5aeb3fef0c9cf75e2c15f6626
@@ -28,8 +28,23 @@ class OrigenSimApplication < Origen::Application
28
28
  #:patterns => "pattern",
29
29
  #:templates => "templates",
30
30
  #:programs => "program",
31
- :command_launcher => "config/shared_commands.rb",
32
- :global_launcher => "config/global_commands.rb"
31
+ command_launcher: "config/shared_commands.rb",
32
+ global_launcher: "config/global_commands.rb",
33
+ origen_guides: "templates/origen_guides",
34
+ origen_guides_index: -> (index) do
35
+ index.section :simulation, heading: "Simulation", after: :program do |section|
36
+ section.page :introduction, heading: "Introduction"
37
+ section.page :howitworks, heading: "How It Works"
38
+ section.page :compiling, heading: "Compiling the DUT"
39
+ section.page :environment, heading: "Environment Setup"
40
+ section.page :app, heading: "Application Setup"
41
+ section.page :patterns, heading: "Simulating Patterns"
42
+ section.page :flows, heading: "Simulating Flows"
43
+ section.page :log, heading: "Simulator Log Output"
44
+ section.page :artifacts, heading: "Artifacts"
45
+ section.page :debugging, heading: "Interactive Debugging"
46
+ end
47
+ end
33
48
  }
34
49
 
35
50
  config.remotes = [
@@ -11,6 +11,13 @@ when 'generate'
11
11
 
12
12
  @application_options << ["--flow NAME", "Simulate multiple patterns back-back within a single simulation with the given name", ->(options, name) { OrigenSim.flow = name }]
13
13
 
14
+ @application_options << ["--socket_dir PATH", "Specify the directory to be used for creating the Origen -> simulator communication socket (/tmp by default) ", ->(options, path) {
15
+ FileUtils.mkdir_p(path) unless File.exist?(path)
16
+ path = Pathname.new(path)
17
+ path = path.realpath.to_s
18
+ OrigenSim.socket_dir = path
19
+ }]
20
+
14
21
  when "sim:ci", "origen_sim:ci"
15
22
  require "#{Origen.root!}/lib/origen_sim/commands/ci"
16
23
  exit 0
@@ -1,6 +1,6 @@
1
1
  module OrigenSim
2
2
  MAJOR = 0
3
- MINOR = 12
3
+ MINOR = 13
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -538,6 +538,7 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
538
538
  UNUSED(data);
539
539
  int max_msg_len = 1024;
540
540
  char msg[max_msg_len];
541
+ char comment[128];
541
542
  int err;
542
543
  char *opcode, *arg1, *arg2, *arg3, *arg4;
543
544
  vpiHandle handle;
@@ -706,13 +707,18 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
706
707
  }
707
708
  break;
708
709
  // Set Comment
709
- // c^Some comment about the pattern
710
+ // c^0^Some comment about the pattern
710
711
  case 'c' :
711
- handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("debug.comments"), NULL);
712
712
  arg1 = strtok(NULL, "^");
713
+ arg2 = strtok(NULL, "^");
714
+
715
+ strcpy(comment, ORIGEN_SIM_TESTBENCH_CAT("debug.comments"));
716
+ strcat(comment, arg1);
717
+
718
+ handle = vpi_handle_by_name(comment, NULL);
713
719
 
714
720
  v.format = vpiStringVal;
715
- v.value.str = arg1;
721
+ v.value.str = arg2;
716
722
  vpi_put_value(handle, &v, NULL, vpiNoDelay);
717
723
  break;
718
724
  // Log all messages
@@ -757,6 +763,10 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
757
763
  case 'i' :
758
764
  client_put(ORIGEN_SIM_VERSION"\n");
759
765
  break;
766
+ // Flush
767
+ case 'j' :
768
+ vpi_flush();
769
+ break;
760
770
  default :
761
771
  vpi_printf("ERROR: Illegal message received from Origen: %s\n", orig_msg);
762
772
  runtime_errors += 1;
@@ -6,6 +6,8 @@ require 'origen_sim/origen/pins/pin'
6
6
  require 'origen_sim/origen/top_level'
7
7
  require 'origen_sim/origen/application/runner'
8
8
  module OrigenSim
9
+ NUMBER_OF_COMMENT_LINES = 10
10
+
9
11
  # THIS FILE SHOULD ONLY BE USED TO LOAD RUNTIME DEPENDENCIES
10
12
  # If this plugin has any development dependencies (e.g. dummy DUT or other models that are only used
11
13
  # for testing), then these should be loaded from config/boot.rb
@@ -58,6 +60,14 @@ module OrigenSim
58
60
  @flow
59
61
  end
60
62
 
63
+ def self.socket_dir=(val)
64
+ @socket_dir = val
65
+ end
66
+
67
+ def self.socket_dir
68
+ @socket_dir
69
+ end
70
+
61
71
  def self.error_strings
62
72
  @error_strings ||= ['ERROR']
63
73
  end
@@ -0,0 +1,101 @@
1
+ module OrigenSim
2
+ module Artifacts
3
+ class Artifacts
4
+ include Origen::Componentable
5
+
6
+ # Disable accessors on the simulator. Artifact retrieval must use simulator.artifact[name]
7
+ COMPONENTABLE_ADDS_ACCESSORS = false
8
+
9
+ # Clean up the names a bit. Componentable assumes the class name is the singleton name, but we're doing the opposite here.
10
+ COMPONENTABLE_SINGLETON_NAME = 'artifact'
11
+ COMPONENTABLE_PLURAL_NAME = 'artifacts'
12
+
13
+ def initialize
14
+ # Don't need the full extent of Origen::Mdoel, so we'll just init the includer class directly.
15
+ Origen::Componentable.init_includer_class(self)
16
+ end
17
+
18
+ # Force the class to be an OrigenSim::Artifacts::Artifact
19
+ def add(name, options = {}, &block)
20
+ instances = _split_by_instances(name, options, &block)
21
+ return_instances = []
22
+ instances.each do |n, opts|
23
+ opts[:class_name] = OrigenSim::Artifacts::Artifact
24
+ return_instances << _add(n, opts)
25
+ end
26
+
27
+ return_instances.size == 1 ? return_instances.first : return_instances
28
+ end
29
+
30
+ def populate
31
+ artifacts.each do |name, artifact|
32
+ Origen.log.info "Populating artifact: #{artifact.target}"
33
+ Origen.log.info " to: #{artifact.run_target}"
34
+ artifact.populate
35
+ end
36
+ true
37
+ end
38
+
39
+ def clean
40
+ artifacts.each do |name, artifact|
41
+ Origen.log.info "Cleaning artifact: #{artifact.run_target}"
42
+ artifact.clean
43
+ end
44
+ true
45
+ end
46
+ end
47
+
48
+ class Artifact
49
+ attr_reader :name
50
+ attr_reader :parent
51
+
52
+ def initialize(options)
53
+ @name = options.delete(:name)
54
+ @parent = options.delete(:parent)
55
+ @options = options
56
+ end
57
+
58
+ def target
59
+ Pathname(@options[:target] || parent.artifact_dir)
60
+ end
61
+
62
+ def run_target
63
+ run_target = Pathname(@options[:run_target] || parent.artifact_run_dir)
64
+ if run_target.absolute?
65
+ run_target.join(target.basename)
66
+ else
67
+ parent.artifact_run_dir.join(run_target).join(target.basename)
68
+ end
69
+ end
70
+
71
+ def populate_method
72
+ @options[:populate_method] || parent.artifact_populate_method
73
+ end
74
+ alias_method :pop_method, :populate_method
75
+
76
+ def populate
77
+ if populate_method == :symlink
78
+ File.symlink(target, run_target)
79
+ elsif populate_method == :copy
80
+ FileUtils.cp(target, run_target)
81
+ else
82
+ Origen.app.fail! "Cannot populate artifact :#{name} with populate method #{populate_method}!"
83
+ end
84
+ end
85
+
86
+ def clean
87
+ if File.exist?(run_target)
88
+ if File.symlink?(run_target)
89
+ File.unlink(run_target)
90
+ else
91
+ FileUtils.rm_r(run_target)
92
+ end
93
+ end
94
+ end
95
+
96
+ def reconfigure(options)
97
+ @options = options
98
+ end
99
+ end
100
+ end
101
+ end
@@ -107,14 +107,6 @@ else
107
107
 
108
108
  puts
109
109
  puts
110
- puts 'Testbench and VPI extension created!'
111
- puts
112
- puts 'This file can be imported into an Origen top-level DUT model to define the pins:'
113
- puts
114
- puts " #{output_directory}/#{rtl_top_module}.rb"
115
- puts
116
- puts 'See below for what to do now to create an Origen-enabled simulation object for your particular simulator:'
117
- puts
118
110
  puts '-----------------------------------------------------------'
119
111
  puts 'Cadence Incisive (irun)'
120
112
  puts '-----------------------------------------------------------'
@@ -145,7 +137,7 @@ else
145
137
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
146
138
  puts
147
139
  puts " #{output_directory}/origen.v \\"
148
- puts " #{output_directory}/brdige.c \\"
140
+ puts " #{output_directory}/bridge.c \\"
149
141
  puts " #{output_directory}/client.c \\"
150
142
  puts ' -CFLAGS "-std=c99" \\'
151
143
  puts ' +vpi \\'
@@ -187,5 +179,45 @@ else
187
179
  puts " #{output_directory}/origen.vpi"
188
180
  puts ' origen.vvp'
189
181
  puts
182
+ puts '-----------------------------------------------------------'
183
+ puts 'Verdi w/ Synopsys VCS'
184
+ puts '-----------------------------------------------------------'
190
185
  puts
186
+ puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
187
+ puts
188
+ puts " #{output_directory}/origen.v \\"
189
+ puts " #{output_directory}/brdige.c \\"
190
+ puts " #{output_directory}/client.c \\"
191
+ puts ' -CFLAGS "-std=c99" \\'
192
+ puts ' +vpi \\'
193
+ puts " #{output_directory}/origen.c \\"
194
+ puts ' +define+ORIGEN_FSDB=1 \\'
195
+ puts ' -debug_access+all \\'
196
+ puts ' +lint=all,noVCDE,noIWU,noVNGS,noCAWM-L,noPORTFRC,noZERO,noNS \\'
197
+ puts ' -PP \\'
198
+ puts ' -timescale=1ns/100ps \\'
199
+ puts ' -full64 \\'
200
+ puts ' -lca \\'
201
+ puts ' -kdb \\'
202
+ puts
203
+ puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
204
+ puts
205
+ puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c +define+ORIGEN_FSDB=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all +lint=all,noVCDE,noIWU,noVNGS,noCAWM-L,noPORTFRC,noZERO,noNS -PP -timescale=1ns/100ps -full64 -lca -kdb"
206
+ puts
207
+ puts 'Copy the following files (produced by vcs) to simulation/<target>/verdi/. within your Origen application:'
208
+ puts
209
+ puts ' simv'
210
+ puts ' simv.daidir'
211
+ puts
212
+ puts '-----------------------------------------------------------'
213
+ puts
214
+ puts 'Testbench and VPI extension created!'
215
+ puts
216
+ puts 'This file can be imported into an Origen top-level DUT model to define the pins:'
217
+ puts
218
+ puts " #{output_directory}/#{rtl_top_module}.rb"
219
+ puts
220
+ puts 'See above for what to do now to create an Origen-enabled simulation object for your particular simulator.'
221
+ puts
222
+
191
223
  end
@@ -3,12 +3,24 @@ module OrigenSim
3
3
  class Heartbeat < Thread
4
4
  attr_reader :socket
5
5
 
6
+ # Can't use this with threads currently because Byebug pauses the sleep,
7
+ # during a breakpoint, which means that the simulator is killed.
8
+ # Currently working around via a forked process implementation instead
9
+ # whenever this is set to false.
10
+ THREADSAFE = false
11
+
6
12
  def initialize(socket)
7
13
  @socket = socket
8
14
  @continue = true
9
15
  super do
10
16
  while @continue
11
- socket.write("OK\n")
17
+ begin
18
+ socket.write("OK\n")
19
+ rescue Errno::EPIPE => e
20
+ Origen.log.error 'Communication with the simulation monitor has been lost!'
21
+ sleep 2
22
+ exit 1
23
+ end
12
24
  sleep 5
13
25
  end
14
26
  end
@@ -8,17 +8,83 @@ module OrigenTesters
8
8
  end
9
9
  alias_method :simulator?, :sim?
10
10
 
11
+ def sim_delay(id, options = {}, &block)
12
+ if sim? && dut_version <= '0.12.0'
13
+ OrigenSim.error "Use of sim_delay requires a DUT model compiled with OrigenSim version > 0.12.0, the current dut was compiled with #{dut_version}"
14
+ end
15
+ orig_id = id
16
+ id = "delay_#{id}".to_sym # Just to make sure it is unique from the sim_capture IDs
17
+ if @sim_capture || @sim_delay
18
+ fail 'Nesting of sim_capture and/or sim_delay blocks is not yet supported!'
19
+ end
20
+ Origen::OrgFile.open(id) do |org_file|
21
+ @org_file = org_file
22
+ if update_capture?
23
+ @sim_delay = true
24
+ # This enables errors to be captured in a separate variable so that they don't affect
25
+ # the overall simulation result
26
+ start_cycle = cycle_count
27
+ delay = 0
28
+ simulator.match_loop do
29
+ if options[:resolution]
30
+ if options[:resolution].is_a?(Hash)
31
+ resolution_in_cycles = time_to_cycles(options[:resolution])
32
+ else
33
+ resolution_in_cycles = options[:resolution]
34
+ end
35
+ end
36
+ timeout_in_cycles = time_to_cycles(options)
37
+ e = -1
38
+ until (e == simulator.match_errors) || (timeout_in_cycles > 0 ? delay > timeout_in_cycles : false)
39
+ delay = cycle_count - start_cycle
40
+ e = simulator.match_errors
41
+ pre_block_cycle = cycle_count
42
+ block.call
43
+ if resolution_in_cycles
44
+ remaining = resolution_in_cycles - (cycle_count - pre_block_cycle)
45
+ remaining.cycles if remaining > 0
46
+ else
47
+ # Make sure time is advancing, the block does not necessarily have to advance time
48
+ 1.cycle if pre_block_cycle == cycle_count
49
+ end
50
+ end
51
+ end
52
+ Origen.log.debug "sim_delay #{orig_id} resolved after #{delay} cycles"
53
+ # We now know how long it took before the block could pass, now record that information
54
+ # to the org file for next time
55
+ org_file.record('tester', 'cycle')
56
+ org_file.file # Need to call this since we are bypassing the regular capture API here
57
+ Origen::OrgFile.cycle(delay)
58
+ else
59
+ unless org_file.exist?
60
+ fail "The simulation delay \"#{orig_id}\" has not been simulated yet, re-run this pattern with a simulation target first!"
61
+ end
62
+ org_file.read_line do |operations, cycles|
63
+ cycles.cycles
64
+ end
65
+ end
66
+ end
67
+ # Finally execute the block after waiting
68
+ if options[:padding]
69
+ time_to_cycles(options[:padding]).cycles
70
+ end
71
+ block.call
72
+ @sim_delay = nil
73
+ end
74
+
11
75
  def sim_capture(id, *pins)
12
- if @sim_capture
13
- fail 'Nesting of sim_capture blocks is not yet supported!'
76
+ if @sim_capture || @sim_delay
77
+ fail 'Nesting of sim_capture and/or sim_delay blocks is not yet supported!'
14
78
  end
79
+ @sim_capture_id = id
15
80
  options = pins.last.is_a?(Hash) ? pins.pop : {}
16
81
  pins = pins.map { |p| p.is_a?(String) || p.is_a?(Symbol) ? dut.pin(p) : p }
17
82
  pins.each(&:save)
18
83
  @sim_capture = pins.map { |p| [p, "origen.dut.#{p.rtl_name}"] }
19
84
  Origen::OrgFile.open(id) do |org_file|
20
85
  @org_file = org_file
21
- if update_capture?
86
+ @update_capture = update_capture?
87
+ if @update_capture
22
88
  @sim_capture.each { |pin, net| pin.record_to_org_file(only: :assert) }
23
89
  end
24
90
  yield
@@ -34,7 +100,7 @@ module OrigenTesters
34
100
  # really assume that it will be constant for all cycles covered by the repeat
35
101
  cycles = options.delete(:repeat) || 1
36
102
  cycles.times do
37
- if update_capture?
103
+ if @update_capture
38
104
  _origen_testers_cycle(options)
39
105
  @sim_capture.each do |pin, net|
40
106
  pin.assert(simulator.peek(net))
@@ -45,7 +111,7 @@ module OrigenTesters
45
111
  Origen::OrgFile.cycle
46
112
  else
47
113
  unless @org_file.exist?
48
- fail "The simulation capture \"#{id}\" has not been made yet, re-run this pattern with a simulation target first!"
114
+ fail "The simulation capture \"#{@sim_capture_id}\" has not been simulated yet, re-run this pattern with a simulation target first!"
49
115
  end
50
116
  apply_captured_data
51
117
  _origen_testers_cycle(options)
@@ -70,8 +136,25 @@ module OrigenTesters
70
136
  end
71
137
 
72
138
  def update_capture?
73
- return @update_capture if defined? @update_capture
74
- @update_capture = sim? && (!@org_file.exist? || Origen.app!.update_sim_captures)
139
+ sim? && (!@org_file.exist? || Origen.app!.update_sim_captures)
140
+ end
141
+
142
+ def time_to_cycles(options)
143
+ options = {
144
+ cycles: 0,
145
+ time_in_cycles: 0,
146
+ time_in_us: 0,
147
+ time_in_ns: 0,
148
+ time_in_ms: 0,
149
+ time_in_s: 0
150
+ }.merge(options)
151
+ cycles = 0
152
+ cycles += options[:cycles] + options[:time_in_cycles]
153
+ cycles += s_to_cycles(options[:time_in_s])
154
+ cycles += ms_to_cycles(options[:time_in_ms])
155
+ cycles += us_to_cycles(options[:time_in_us])
156
+ cycles += ns_to_cycles(options[:time_in_ns])
157
+ cycles
75
158
  end
76
159
  end
77
160
  end