origen_sim 0.5.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.
data/lib/origen_sim.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'origen'
2
+ require_relative '../config/application.rb'
3
+ require 'origen_testers'
4
+ require 'origen_sim/origen_testers/api'
5
+ require 'origen_sim/origen/pins/pin'
6
+ require 'origen_sim/origen/top_level'
7
+ module OrigenSim
8
+ # THIS FILE SHOULD ONLY BE USED TO LOAD RUNTIME DEPENDENCIES
9
+ # If this plugin has any development dependencies (e.g. dummy DUT or other models that are only used
10
+ # for testing), then these should be loaded from config/boot.rb
11
+
12
+ # Example of how to explicitly require a file
13
+ # require "origen_sim/my_file"
14
+
15
+ autoload :Simulator, 'origen_sim/simulator'
16
+ autoload :Tester, 'origen_sim/tester'
17
+ autoload :Generator, 'origen_sim/generator'
18
+
19
+ def self.__instantiate_simulator__
20
+ @simulator ||= Simulator.new
21
+ end
22
+
23
+ def self.simulator
24
+ @simulator
25
+ end
26
+ end
27
+ OrigenSim.__instantiate_simulator__
@@ -0,0 +1,101 @@
1
+ module OrigenSimDev
2
+ class DUT
3
+ include Origen::TopLevel
4
+ include OrigenJTAG
5
+
6
+ JTAG_CONFIG = {
7
+ tclk_format: :rl
8
+ }
9
+
10
+ def initialize(options = {})
11
+ add_pin :tck, reset: :drive_lo
12
+ add_pin :tdi, reset: :drive_lo
13
+ add_pin :tdo
14
+ add_pin :tms, reset: :drive_lo
15
+ add_pin :rstn, reset: :drive_lo
16
+ add_pin :trstn, reset: :drive_lo
17
+ add_pin_alias :tclk, :tck
18
+ add_pin :dout, size: 32
19
+ add_pin :din_port, size: 32, rtl_name: 'din', reset: :drive_lo
20
+ add_pin :p1, tie_off: 0
21
+ add_pin :p2, tie_off: 1
22
+ add_pin :p3, size: 4, tie_off: 0
23
+ add_pin :p4, size: 4, tie_off: 1
24
+ add_pin :v1, rtl_name: 'nc'
25
+ add_pin :v2, rtl_name: :nc
26
+
27
+ timeset :func do |t|
28
+ # Generate a clock pulse on TCK
29
+ t.wave :tck do |w|
30
+ w.drive 0, at: 0
31
+ w.drive :data, at: 'period / 2'
32
+ end
33
+ end
34
+
35
+ add_reg :dr, 0x0, size: 66 do |reg|
36
+ reg.bit 65, :rg_enable
37
+ reg.bit 64, :rg_read
38
+ reg.bits 63..32, :rg_addr
39
+ reg.bits 31..0, :rg_data
40
+ end
41
+
42
+ add_reg :ctrl, 0x0 do |reg|
43
+ reg.bit 0, :rg_enable
44
+ reg.bit 1, :rg_reset
45
+ end
46
+
47
+ add_reg :cmd, 0x4
48
+
49
+ add_reg :count, 0x8
50
+
51
+ add_reg :data_out, 0xC
52
+
53
+ add_reg :data_in, 0x10
54
+
55
+ add_reg :p, 0x14 do |reg|
56
+ reg.bits 0, :p1
57
+ reg.bits 1, :p2
58
+ reg.bits 5..2, :p3
59
+ reg.bits 9..6, :p4
60
+ end
61
+ end
62
+
63
+ def interactive_startup
64
+ if tester.sim?
65
+ tester.start
66
+ startup
67
+ end
68
+ end
69
+
70
+ def startup(options = {})
71
+ tester.set_timeset('func', 100)
72
+
73
+ dut.pin(:rstn).drive!(1)
74
+ 10.cycles
75
+ dut.pin(:tck).drive!(1)
76
+ 10.cycles
77
+ dut.pin(:trstn).drive!(1)
78
+ 10.cycles
79
+ end
80
+
81
+ def write_register(reg, options = {})
82
+ jtag.write_ir(0x8, size: 4)
83
+ dr.rg_enable.write(1)
84
+ dr.rg_read.write(0)
85
+ dr.rg_addr.write(reg.address)
86
+ dr.rg_data.write(reg.data)
87
+ jtag.write_dr(dr)
88
+ end
89
+
90
+ def read_register(reg, options = {})
91
+ jtag.write_ir(0x8, size: 4)
92
+ dr.rg_enable.write(1)
93
+ dr.rg_read.write(1)
94
+ dr.rg_addr.write(reg.address)
95
+ jtag.write_dr(dr)
96
+ dr.rg_enable.write(0)
97
+ dr.rg_data.copy_all(reg)
98
+ jtag.read_dr(dr)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,6 @@
1
+ # You can define any Rake tasks to support your application here (or in any file
2
+ # ending in .rake in this directory).
3
+ #
4
+ # Rake (Ruby Make) is very useful for creating build scripts, see this short video
5
+ # for a quick introduction:
6
+ # http://railscasts.com/episodes/66-custom-rake-tasks
data/pattern/test.rb ADDED
@@ -0,0 +1,84 @@
1
+ Pattern.create do
2
+ IDCODE = 0b0010
3
+ DEBUG = 0b1000
4
+
5
+ ss "Some basic shift operations to verify functionality"
6
+ dut.jtag.write_ir(0x0, size: 4)
7
+ dut.jtag.read_ir(0x0, size: 4)
8
+ dut.jtag.write_ir(0xA, size: 4)
9
+ dut.jtag.read_ir(0xA, size: 4)
10
+ dut.jtag.write_ir(0xE, size: 4)
11
+ dut.jtag.read_ir(0xE, size: 4)
12
+
13
+ ss "Switch to slower timeset"
14
+ tester.set_timeset("func", 200)
15
+
16
+ dut.jtag.write_ir(0x5, size: 4)
17
+ dut.jtag.read_ir(0x5, size: 4)
18
+
19
+ ss "Read the IDCODE value"
20
+ dut.jtag.write_ir(IDCODE, size: 4)
21
+ dut.jtag.read_dr(0x149511C3, size: 32)
22
+
23
+ ss "Now try and shift in an out of the device DR"
24
+ dut.jtag.write_ir(0x0, size: 4)
25
+ dut.jtag.write_dr(0x1111_2222_3333_4444, size: 66)
26
+ # Should not have been applied when not selected
27
+ dut.jtag.read_dr(0, size: 66)
28
+
29
+ dut.jtag.write_ir(DEBUG, size: 4)
30
+ dut.jtag.write_dr(0x1111_2222_3333_4444, size: 66)
31
+ dut.jtag.read_dr(0x1111_2222_3333_4444, size: 66)
32
+
33
+ ss "Now try and read and write a register"
34
+ dut.cmd.write!(0x1234_5678)
35
+ dut.cmd.read!(0x1234_5678)
36
+
37
+ tester.simulator.poke("dut.cmd", 0x1122_3344)
38
+ dut.cmd.read!(0x1122_3344)
39
+
40
+ ss "Test storing a register"
41
+ dut.cmd.write!(0x2244_6688)
42
+ dut.cmd.store!
43
+
44
+ capture_value = tester.simulator.peek("origen.pins.tdo.memory")
45
+ unless capture_value == 0x11662244 # 0x2244_6688 reversed
46
+ if capture_value
47
+ fail "Captured #{capture_value.to_hex} instead of 0x11662244!"
48
+ else
49
+ fail "Nothing captured instead of 0x11662244!"
50
+ end
51
+ end
52
+
53
+ ss "Test sync of a register"
54
+ dut.cmd.write(0) # Make Origen forget the actual value
55
+ dut.cmd.sync
56
+ unless dut.cmd.data == 0x2244_6688
57
+ fail "CMD register did not sync from simulation"
58
+ end
59
+
60
+ ss "Do some operations with the counter, just for fun"
61
+ dut.ctrl.write!(0b11) # Reset the counter
62
+ dut.count.read!(0x0)
63
+ dut.ctrl.write!(0b1) # Start counting
64
+ 100.cycles
65
+ dut.ctrl.write!(0b0) # Stop counting
66
+ dut.count.read!(0xAB)
67
+
68
+ ss "Verify that pin group read/write works"
69
+ dut.pins(:din_port).drive!(0x1234_5678)
70
+ dut.data_in.read!(0x1234_5678)
71
+
72
+ dut.data_out.write!(0)
73
+ dut.pins(:dout).assert!(0)
74
+ dut.pins(:dout).dont_care
75
+ dut.data_out.write!(0x5555_AAAA)
76
+ dut.pins(:dout).assert!(0x5555_AAAA)
77
+ dut.pins(:dout).dont_care
78
+
79
+ ss "Verify that tying off pins works"
80
+ dut.p.p1.assert!(0)
81
+ dut.p.p2.assert!(1)
82
+ dut.p.p3.assert!(0)
83
+ dut.p.p4.assert!(0xF)
84
+ end
data/program/p1.rb ADDED
@@ -0,0 +1,10 @@
1
+ Flow.create do
2
+
3
+ test :test
4
+
5
+ test :test
6
+
7
+ test :test
8
+
9
+ test :test
10
+ end
@@ -0,0 +1,100 @@
1
+ #
2
+ # Preferences
3
+ #
4
+ preferences set plugin-enable-svdatabrowser-new 1
5
+ preferences set toolbar-SimControl-WaveWindow {
6
+ usual
7
+ position -row 1 -pos 4 -anchor e
8
+ }
9
+ preferences set plugin-enable-groupscope 0
10
+ preferences set sb-display-values 1
11
+ preferences set plugin-enable-interleaveandcompare 0
12
+ preferences set plugin-enable-waveformfrequencyplot 0
13
+ preferences set toolbar-WaveZoom-WaveWindow {
14
+ usual
15
+ position -row 1 -pos 3 -anchor w
16
+ }
17
+ preferences set whats-new-dont-show-at-startup 1
18
+ #
19
+ # Groups
20
+ #
21
+ catch {group new -name Debug -overlay 0}
22
+ catch {group new -name {Group 2} -overlay 0}
23
+ catch {group new -name DUT -overlay 0}
24
+ group using Debug
25
+ group set -overlay 0
26
+ group set -comment {}
27
+ group clear 0 end
28
+
29
+ group insert \
30
+ [subst {[format {origen.debug.pattern[1023:0]}]} ] \
31
+ [subst {[format {origen.debug.comments[1023:0]}]} ] \
32
+ [subst {[format {origen.debug.errors[31:0]}]} ]
33
+ group using {Group 2}
34
+ group set -overlay 0
35
+ group set -comment {}
36
+ group clear 0 end
37
+
38
+ group using DUT
39
+ group set -overlay 0
40
+ group set -comment {}
41
+ group clear 0 end
42
+
43
+
44
+ #
45
+ # Mnemonic Maps
46
+ #
47
+ mmap new -reuse -name {Boolean as Logic} -radix %b -contents {{%c=FALSE -edgepriority 1 -shape low}
48
+ {%c=TRUE -edgepriority 1 -shape high}}
49
+ mmap new -reuse -name {Example Map} -radix %x -contents {{%b=11???? -bgcolor orange -label REG:%x -linecolor yellow -shape bus}
50
+ {%x=1F -bgcolor red -label ERROR -linecolor white -shape EVENT}
51
+ {%x=2C -bgcolor red -label ERROR -linecolor white -shape EVENT}
52
+ {%x=* -label %x -linecolor gray -shape bus}}
53
+
54
+ #
55
+ # Waveform windows
56
+ #
57
+ if {[catch {window new WaveWindow -name "Waveform 1" -geometry 1604x996+38+65}] != ""} {
58
+ window geometry "Waveform 1" 1604x996+38+65
59
+ }
60
+ window target "Waveform 1" on
61
+ waveform using {Waveform 1}
62
+ waveform sidebar select designbrowser
63
+ waveform set \
64
+ -primarycursor TimeA \
65
+ -signalnames name \
66
+ -signalwidth 175 \
67
+ -units ns \
68
+ -valuewidth 75
69
+ waveform baseline set -time 0
70
+
71
+
72
+ set groupId0 [waveform add -groups Debug]
73
+ set gpGlist0 [waveform hierarchy contents $groupId0]
74
+ set gpID0 [lindex $gpGlist0 0]
75
+ foreach {name attrs} [subst {
76
+ {[format {origen.debug.pattern[1023:0]}]} {-radix %a}
77
+ {[format {origen.debug.comments[1023:0]}]} {-radix %a}
78
+ {[format {origen.debug.errors[31:0]}]} {}
79
+ }] childcmds {
80
+ {}
81
+ {}
82
+ {}
83
+ } {
84
+ set expected [ join [waveform signals -format path $gpID0] ]
85
+ if {[string equal $name $expected] || $name == "cdivider"} {
86
+ if {$attrs != ""} {
87
+ eval waveform format $gpID0 $attrs
88
+ }
89
+ if { $childcmds != ""} {
90
+ eval $childcmds
91
+ }
92
+ }
93
+ set gpGlist0 [lrange $gpGlist0 1 end]
94
+ set gpID0 [lindex $gpGlist0 0]
95
+ }
96
+
97
+
98
+ set groupId0 [waveform add -groups DUT]
99
+
100
+
@@ -0,0 +1,15 @@
1
+ database -open waves -into <%= options[:dir] %> -default -event
2
+ probe -create -shm origen -depth all -database waves
3
+ #probe -create -assertions -transaction origen -depth all -database waves
4
+
5
+ % Hash(options[:force]).each do |net, value|
6
+ % net = net.to_s.strip.sub(/^(origen\.|origen\.dut\.|\.)/, '')
7
+ force origen.dut.<%= net %> <%= value %>
8
+ % end
9
+
10
+ % (options[:setup] || '').split("\n").each do |line|
11
+ <%= line.strip.gsub(" dut", " origen.dut") %>
12
+ % end
13
+
14
+ run
15
+ exit
@@ -0,0 +1,194 @@
1
+ %#`include "<%= options[:top] %>"
2
+
3
+ `timescale 1ns/1ns
4
+
5
+ // 0 - Data
6
+ // 1 - Reserved
7
+ //
8
+ // 0 - Drive
9
+ //
10
+ // 0 - Compare
11
+ //
12
+ // 0 - Force data 0
13
+ // 1 - Force data 1
14
+ module pin_driver(error, pin, sync);
15
+ parameter init_drive = 2; // Which means don't drive initially, set to 0 or 1 to drive
16
+
17
+ output reg error;
18
+ inout pin;
19
+ input sync;
20
+
21
+ reg [1:0] data = 0;
22
+ reg [1:0] force_data = 0;
23
+ reg compare = 0;
24
+ reg drive = 0;
25
+ reg capture = 0;
26
+ //reg [1023:0] memory = 0;
27
+ reg [127:0] memory = 0;
28
+ reg [127:0] memory_reversed = 0;
29
+ reg [127:0] sync_memory = 0;
30
+
31
+ wire drive_data = force_data[0] ? 0 : (force_data[1] ? 1 : data[0]);
32
+
33
+ assign pin = drive ? drive_data : 1'bz;
34
+
35
+ // Debug signal to show the expected data in the waves
36
+ wire expect_data = compare ? data[0] : 1'bz;
37
+
38
+ always @(*) begin
39
+ error = (compare && !capture) ? (pin == data[0] ? 0 : 1) : 0;
40
+ end
41
+
42
+ always @(posedge capture) begin
43
+ if (sync == 1) begin
44
+ sync_memory[127:1] <= sync_memory[126:0];
45
+ sync_memory[0] <= pin;
46
+ end else begin
47
+ memory[127:1] <= memory[126:0];
48
+ memory[0] <= pin;
49
+ memory_reversed[126:0] <= memory_reversed[127:1];
50
+ memory_reversed[127] <= pin;
51
+ end
52
+ end
53
+
54
+ initial begin
55
+ if (init_drive == 1) begin
56
+ drive = 1;
57
+ data[0] = 1;
58
+ end else if (init_drive == 0) begin
59
+ drive = 1;
60
+ data[0] = 0;
61
+ end
62
+ end
63
+
64
+ endmodule
65
+
66
+ module pin_drivers(errors, <%= dut.rtl_pins.map { |n, p, o| "#{p.id}_o" unless p.tie_off }.compact.join(', ') %>);
67
+
68
+ % dut.rtl_pins.each do |name, pin, options|
69
+ % unless pin.tie_off
70
+ output <%= pin.id %>_o;
71
+ % end
72
+ % end
73
+
74
+ % dut.rtl_pins.each do |name, pin, options|
75
+ % unless pin.tie_off
76
+ wire <%= pin.id %>_err;
77
+ % end
78
+ % end
79
+
80
+ output reg [31:0] errors = 0;
81
+ reg sync = 0;
82
+
83
+ always @(
84
+
85
+ % dut.rtl_pins.each_with_index do |(name, pin, options), i|
86
+ % unless pin.tie_off
87
+ % if i == 0
88
+ posedge <%= pin.id %>_err
89
+ % else
90
+ or posedge <%= pin.id %>_err
91
+ % end
92
+ % end
93
+ % end
94
+ ) begin
95
+ errors[31:0] = errors[31:0] + 1;
96
+ end
97
+
98
+ % dut.rtl_pins.each do |name, pin, options|
99
+ % unless pin.tie_off
100
+ pin_driver <%= pin.driving? ? "#(#{pin.value}) " : '' %><%= pin.id %>(.pin(<%= pin.id %>_o), .error(<%= pin.id %>_err), .sync(sync));
101
+ % end
102
+ % end
103
+
104
+ endmodule
105
+
106
+
107
+ module debug(errors);
108
+
109
+ input [31:0] errors;
110
+
111
+ reg [1023:0] pattern = 0;
112
+ reg [1023:0] comments = 0;
113
+
114
+ reg handshake;
115
+
116
+ endmodule
117
+
118
+ module origen;
119
+
120
+ reg finish = 0;
121
+
122
+ % dut.rtl_pins.each do |name, pin, options|
123
+ % unless pin.tie_off
124
+ wire <%= pin.id %>;
125
+ % end
126
+ % end
127
+
128
+ wire [31:0] errors;
129
+
130
+ pin_drivers pins (
131
+ % dut.rtl_pins.each_with_index do |(name, pin, options), i|
132
+ % unless pin.tie_off
133
+ .<%= pin.id %>_o(<%= pin.id %>),
134
+ % end
135
+ % end
136
+ .errors(errors)
137
+ );
138
+
139
+ // Create wires to tie off DUT signals, initially this was done by hardcoded values when instantiating
140
+ // below, however the simulator didn't like that if the target pin was defined as an inout
141
+ % dut.rtl_pins.each do |name, pin, options|
142
+ % if options[:group]
143
+ % if pin.group_index == 0
144
+ % if pin.primary_group.tie_off
145
+ wire [<%= pin.primary_group.size - 1 %>:0] <%= pin.rtl_name %>;
146
+ assign <%= pin.rtl_name %> = <%= "#{pin.primary_group.size}'b#{pin.tie_off.to_s * pin.primary_group.size}" %>;
147
+ % end
148
+ % end
149
+ % else
150
+ % if pin.tie_off
151
+ wire <%= pin.rtl_name %>;
152
+ assign <%= pin.rtl_name %> = 1'b<%= pin.tie_off %>;
153
+ % end
154
+ % end
155
+ % end
156
+
157
+
158
+ // Instantiate the DUT
159
+ <%= options[:top].sub(/\..*/, '') %> dut (
160
+ % dut.rtl_pins.each_with_index do |(name, pin, options), i|
161
+ % if options[:group]
162
+ % if pin.group_index == 0
163
+ % if pin.primary_group.tie_off
164
+ .<%= pin.rtl_name %>(<%= pin.rtl_name %>)<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %>
165
+ % else
166
+ .<%= pin.rtl_name %>({
167
+ % pin.primary_group.each_with_index do |pin, i|
168
+ <%= pin.id %><%= i == (pin.primary_group.size - 1) ? '' : ',' %>
169
+ % end
170
+ })<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %>
171
+ % end
172
+ % end
173
+ % else
174
+ .<%= pin.rtl_name %>(<%= pin.tie_off ? pin.rtl_name : pin.id %>)<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %>
175
+ % end
176
+ % end
177
+ );
178
+
179
+ debug debug (
180
+ .errors(errors)
181
+ );
182
+
183
+ % if options[:vendor] == :icarus
184
+ initial
185
+ begin
186
+ $dumpfile("dut.vcd");
187
+ $dumpvars(0,origen);
188
+ end
189
+ % end
190
+
191
+ always @(posedge finish) begin
192
+ $finish(2);
193
+ end
194
+ endmodule
@@ -0,0 +1,37 @@
1
+ % render "layouts/basic.html" do
2
+
3
+ %# HTML tags can be embedded in mark down files if you want to do specific custom
4
+ %# formatting like this, but in most cases that is not required.
5
+ <h1><%= Origen.app.namespace %> <span style="font-size: 14px">(<%= Origen.app.version %>)</span></h1>
6
+
7
+ ### Purpose
8
+
9
+ This plugin...
10
+
11
+ ### How To Install
12
+
13
+ In your Gemfile add:
14
+
15
+ ~~~ruby
16
+ gem "<%= Origen.app.name %>"
17
+ ~~~
18
+
19
+ or if your application is a plugin, then add this to your <code>.gemspec</code>
20
+
21
+ ~~~ruby
22
+ spec.add_runtime_dependency "<%= Origen.app.name %>", ">= <%= Origen.app.version %>"
23
+ ~~~
24
+
25
+ __NOTE:__ In the case of a plugin, you will also need to <code>require '<%= Origen.app.name %>'</code> somewhere in your environment.
26
+
27
+
28
+ ### How To Use
29
+
30
+ Add quickstart documentation here...
31
+
32
+
33
+ ### How To Setup a Development Environment
34
+
35
+ Describe how a developer would setup a new workspace for this plugin...
36
+
37
+ % end
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: <%= options[:title] || Origen.config.name %>
3
+ ---
4
+ <%= render "partials/navbar.html", tab: options[:tab] %>
5
+
6
+ <div class="row">
7
+ %# The markdown attribute is important if you are going to include content written
8
+ %# in markdown, without this is will be included verbatim
9
+ <div class="span12" markdown="1">
10
+ <%= yield %>
11
+
12
+ </div>
13
+ </div>
@@ -0,0 +1,20 @@
1
+ <nav class="navbar navbar-inverse navbar-fixed-top">
2
+ <div class="container">
3
+ <div class="navbar-header">
4
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
5
+ <span class="sr-only">Toggle navigation</span>
6
+ <span class="icon-bar"></span>
7
+ <span class="icon-bar"></span>
8
+ <span class="icon-bar"></span>
9
+ </button>
10
+ <a class="navbar-brand" href="<%= path "/" %>">Home</a>
11
+ </div>
12
+ <div id="navbar" class="collapse navbar-collapse">
13
+ <ul class="nav navbar-nav">
14
+ <li class="<%= options[:tab] == :api ? 'active' : '' %>"><a href="<%= path "/api/" %>">API</a></li>
15
+ <li class="<%= options[:tab] == :release ? 'active' : '' %>"><a href="<%= path "/release_notes" %>">Release Notes</a></li>
16
+ </ul>
17
+ <%= import "origen/web/logo.html" %>
18
+ </div><!--/.nav-collapse -->
19
+ </div>
20
+ </nav>
@@ -0,0 +1,5 @@
1
+ % render "layouts/basic.html", tab: :release do
2
+
3
+ <%= render "#{Origen.root}/doc/history" %>
4
+
5
+ % end