switchboard-hw 0.3.0__cp314-cp314-macosx_10_15_x86_64.whl

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 (99) hide show
  1. _switchboard.cpython-314-darwin.so +0 -0
  2. switchboard/__init__.py +24 -0
  3. switchboard/ams.py +668 -0
  4. switchboard/apb.py +278 -0
  5. switchboard/autowrap.py +1000 -0
  6. switchboard/axi.py +571 -0
  7. switchboard/axil.py +348 -0
  8. switchboard/bitvector.py +112 -0
  9. switchboard/cmdline.py +142 -0
  10. switchboard/cpp/Makefile +13 -0
  11. switchboard/cpp/bitutil.h +39 -0
  12. switchboard/cpp/pagemap.h +91 -0
  13. switchboard/cpp/pciedev.h +86 -0
  14. switchboard/cpp/router.cc +89 -0
  15. switchboard/cpp/spsc_queue.h +267 -0
  16. switchboard/cpp/switchboard.hpp +257 -0
  17. switchboard/cpp/switchboard_pcie.hpp +234 -0
  18. switchboard/cpp/switchboard_tlm.hpp +98 -0
  19. switchboard/cpp/umilib.h +144 -0
  20. switchboard/cpp/umilib.hpp +113 -0
  21. switchboard/cpp/umisb.hpp +364 -0
  22. switchboard/cpp/xyce.hpp +90 -0
  23. switchboard/deps/__init__.py +0 -0
  24. switchboard/deps/verilog_axi.py +23 -0
  25. switchboard/dpi/__init__.py +0 -0
  26. switchboard/dpi/switchboard_dpi.cc +119 -0
  27. switchboard/dpi/switchboard_dpi.py +13 -0
  28. switchboard/dpi/xyce_dpi.cc +43 -0
  29. switchboard/gpio.py +108 -0
  30. switchboard/icarus.py +85 -0
  31. switchboard/loopback.py +157 -0
  32. switchboard/network.py +714 -0
  33. switchboard/pytest_plugin.py +11 -0
  34. switchboard/sbdesign.py +55 -0
  35. switchboard/sbdut.py +744 -0
  36. switchboard/sbtcp.py +345 -0
  37. switchboard/sc/__init__.py +0 -0
  38. switchboard/sc/morty/__init__.py +0 -0
  39. switchboard/sc/morty/uniquify.py +67 -0
  40. switchboard/sc/sed/__init__.py +0 -0
  41. switchboard/sc/sed/sed_remove.py +47 -0
  42. switchboard/sc/standalone_netlist_flow.py +25 -0
  43. switchboard/switchboard.py +53 -0
  44. switchboard/test_util.py +46 -0
  45. switchboard/uart_xactor.py +66 -0
  46. switchboard/umi.py +793 -0
  47. switchboard/util.py +131 -0
  48. switchboard/verilator/__init__.py +0 -0
  49. switchboard/verilator/config.vlt +13 -0
  50. switchboard/verilator/testbench.cc +143 -0
  51. switchboard/verilator/verilator.py +13 -0
  52. switchboard/verilator_run.py +31 -0
  53. switchboard/verilog/__init__.py +0 -0
  54. switchboard/verilog/common/__init__.py +0 -0
  55. switchboard/verilog/common/common.py +26 -0
  56. switchboard/verilog/common/switchboard.vh +429 -0
  57. switchboard/verilog/common/uart_xactor.sv +247 -0
  58. switchboard/verilog/common/umi_gpio.v +236 -0
  59. switchboard/verilog/fpga/__init__.py +0 -0
  60. switchboard/verilog/fpga/axi_reader.sv +82 -0
  61. switchboard/verilog/fpga/axi_writer.sv +111 -0
  62. switchboard/verilog/fpga/config_registers.sv +249 -0
  63. switchboard/verilog/fpga/fpga.py +21 -0
  64. switchboard/verilog/fpga/include/sb_queue_regmap.vh +21 -0
  65. switchboard/verilog/fpga/include/spsc_queue.vh +7 -0
  66. switchboard/verilog/fpga/memory_fault.sv +40 -0
  67. switchboard/verilog/fpga/sb_fpga_queues.sv +416 -0
  68. switchboard/verilog/fpga/sb_rx_fpga.sv +303 -0
  69. switchboard/verilog/fpga/sb_tx_fpga.sv +294 -0
  70. switchboard/verilog/fpga/umi_fpga_queues.sv +146 -0
  71. switchboard/verilog/sim/__init__.py +0 -0
  72. switchboard/verilog/sim/auto_stop_sim.sv +25 -0
  73. switchboard/verilog/sim/perf_meas_sim.sv +97 -0
  74. switchboard/verilog/sim/queue_to_sb_sim.sv +176 -0
  75. switchboard/verilog/sim/queue_to_umi_sim.sv +66 -0
  76. switchboard/verilog/sim/sb_apb_m.sv +146 -0
  77. switchboard/verilog/sim/sb_axi_m.sv +199 -0
  78. switchboard/verilog/sim/sb_axil_m.sv +180 -0
  79. switchboard/verilog/sim/sb_axil_s.sv +180 -0
  80. switchboard/verilog/sim/sb_clk_gen.sv +89 -0
  81. switchboard/verilog/sim/sb_jtag_rbb_sim.sv +148 -0
  82. switchboard/verilog/sim/sb_rx_sim.sv +55 -0
  83. switchboard/verilog/sim/sb_to_queue_sim.sv +196 -0
  84. switchboard/verilog/sim/sb_tx_sim.sv +55 -0
  85. switchboard/verilog/sim/switchboard_sim.py +49 -0
  86. switchboard/verilog/sim/umi_rx_sim.sv +61 -0
  87. switchboard/verilog/sim/umi_to_queue_sim.sv +66 -0
  88. switchboard/verilog/sim/umi_tx_sim.sv +61 -0
  89. switchboard/verilog/sim/xyce_intf.sv +67 -0
  90. switchboard/vpi/switchboard_vpi.cc +431 -0
  91. switchboard/vpi/xyce_vpi.cc +200 -0
  92. switchboard/warn.py +14 -0
  93. switchboard/xyce.py +27 -0
  94. switchboard_hw-0.3.0.dist-info/METADATA +303 -0
  95. switchboard_hw-0.3.0.dist-info/RECORD +99 -0
  96. switchboard_hw-0.3.0.dist-info/WHEEL +6 -0
  97. switchboard_hw-0.3.0.dist-info/entry_points.txt +6 -0
  98. switchboard_hw-0.3.0.dist-info/licenses/LICENSE +190 -0
  99. switchboard_hw-0.3.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,294 @@
1
+ // Copyright (c) 2024 Zero ASIC Corporation
2
+ // This code is licensed under Apache License 2.0 (see LICENSE for details)
3
+
4
+ `default_nettype none
5
+
6
+ module sb_tx_fpga #(
7
+ parameter ID_WIDTH = 16,
8
+ // must be <= 448 (512-64)
9
+ parameter DW = 416
10
+ ) (
11
+ input wire clk,
12
+ input wire en,
13
+ input wire reset,
14
+
15
+ input wire [DW-1:0] data,
16
+ input wire [31:0] dest,
17
+ input wire last,
18
+ output wire ready,
19
+ input wire valid,
20
+
21
+ input wire [63:0] cfg_base_addr,
22
+ input wire [31:0] cfg_capacity,
23
+
24
+ output wire status_idle,
25
+
26
+ output wire [ID_WIDTH-1:0] m_axi_awid,
27
+ output wire [63:0] m_axi_awaddr,
28
+ output wire [7:0] m_axi_awlen,
29
+ output wire [2:0] m_axi_awsize,
30
+ output wire m_axi_awvalid,
31
+ input wire m_axi_awready,
32
+
33
+ output wire [511:0] m_axi_wdata,
34
+ output wire [63:0] m_axi_wstrb,
35
+ output wire m_axi_wlast,
36
+ output wire m_axi_wvalid,
37
+ input wire m_axi_wready,
38
+
39
+ input wire [ID_WIDTH-1:0] m_axi_bid,
40
+ input wire [1:0] m_axi_bresp,
41
+ input wire m_axi_bvalid,
42
+ output wire m_axi_bready,
43
+
44
+ output wire [ID_WIDTH-1:0] m_axi_arid,
45
+ output wire [63:0] m_axi_araddr,
46
+ output wire [7:0] m_axi_arlen,
47
+ output wire [2:0] m_axi_arsize,
48
+ output wire m_axi_arvalid,
49
+ input wire m_axi_arready,
50
+
51
+ input wire [ID_WIDTH-1:0] m_axi_rid,
52
+ input wire [511:0] m_axi_rdata,
53
+ input wire [1:0] m_axi_rresp,
54
+ input wire m_axi_rlast,
55
+ input wire m_axi_rvalid,
56
+ output wire m_axi_rready
57
+ );
58
+
59
+ `include "spsc_queue.vh"
60
+
61
+ /*
62
+ * Main state machine
63
+ */
64
+
65
+ localparam [2:0] STATE_IDLE = 3'd0;
66
+ localparam [2:0] STATE_RD_TAIL = 3'd1;
67
+ localparam [2:0] STATE_WR_PACKET = 3'd2;
68
+ localparam [2:0] STATE_WR_HEAD = 3'd3;
69
+ localparam [2:0] STATE_FAULT = 3'd4;
70
+
71
+ wire wvalid;
72
+ reg [63:0] waddr;
73
+ reg [63:0] wstrb;
74
+ reg [511:0] wdata;
75
+ wire wready;
76
+
77
+ wire rvalid;
78
+ reg [63:0] raddr;
79
+ wire rready;
80
+ wire [511:0] rdata;
81
+
82
+ wire full;
83
+ wire fault;
84
+
85
+ reg [511:0] packet_to_write;
86
+
87
+ reg [2:0] state = STATE_IDLE;
88
+ reg [2:0] state_next;
89
+
90
+ always @(*) begin
91
+ state_next = state;
92
+ case (state)
93
+ STATE_IDLE: begin
94
+ if (valid && en) begin
95
+ if (!full) begin
96
+ state_next = STATE_WR_PACKET;
97
+ end else begin
98
+ state_next = STATE_RD_TAIL;
99
+ end
100
+ end
101
+ end
102
+
103
+ STATE_RD_TAIL: begin
104
+ if (rready && !en) begin
105
+ state_next = STATE_IDLE;
106
+ end else if (!full) begin
107
+ state_next = STATE_WR_PACKET;
108
+ end
109
+ end
110
+
111
+ STATE_WR_PACKET: begin
112
+ // This state doesn't force a transition to IDLE on !en, since
113
+ // we always need to write the head after writing the packet.
114
+ if (wready) begin
115
+ state_next = STATE_WR_HEAD;
116
+ end
117
+ end
118
+
119
+ STATE_WR_HEAD: begin
120
+ if (wready) begin
121
+ state_next = STATE_IDLE;
122
+ end
123
+ end
124
+
125
+ STATE_FAULT: begin
126
+ state_next = STATE_FAULT;
127
+ end
128
+
129
+ // Shouldn't reach here
130
+ default: state_next = 3'bXXX;
131
+ endcase
132
+ end
133
+
134
+ always @(posedge clk) begin
135
+ if (reset) begin
136
+ state <= STATE_IDLE;
137
+ end else if (fault) begin
138
+ state <= STATE_FAULT;
139
+ end else begin
140
+ state <= state_next;
141
+ end
142
+ end
143
+
144
+ /*
145
+ * Queue state logic
146
+ */
147
+
148
+ reg [31:0] head = 32'd0;
149
+ reg [31:0] tail = 32'd0;
150
+ wire [31:0] head_next;
151
+ wire [31:0] tail_next;
152
+ wire [31:0] head_incr;
153
+
154
+ assign head_incr = (head + 32'd1 == cfg_capacity) ? 32'd0 : (head + 32'd1);
155
+ assign head_next = (state == STATE_WR_PACKET && wready) ? head_incr : head;
156
+
157
+ assign tail_next = (state == STATE_RD_TAIL && rready) ? rdata[31:0] : tail;
158
+
159
+ always @(posedge clk) begin
160
+ if (reset) begin
161
+ head <= 32'd0;
162
+ tail <= 32'd0;
163
+ end else begin
164
+ head <= head_next;
165
+ tail <= tail_next;
166
+ end
167
+ end
168
+
169
+ // Use *_next signals here to speed up state machine transitions.
170
+ assign full = (head_incr == tail_next);
171
+
172
+ // Addresses within queue
173
+ wire [63:0] head_addr;
174
+ wire [63:0] tail_addr;
175
+ assign head_addr = cfg_base_addr + HEAD_OFFSET;
176
+ assign tail_addr = cfg_base_addr + TAIL_OFFSET;
177
+
178
+ wire wvalid_checked;
179
+ wire [63:0] fault_addr;
180
+ memory_fault write_checker(
181
+ .clk(clk),
182
+ .reset(reset),
183
+
184
+ .access_valid_in(wvalid),
185
+ .access_addr(waddr),
186
+ .access_valid_out(wvalid_checked),
187
+
188
+ .base_legal_addr(cfg_base_addr),
189
+ .legal_length(cfg_capacity * PACKET_SIZE + PACKET_OFFSET),
190
+
191
+ .fault(fault),
192
+ .fault_addr(fault_addr)
193
+ );
194
+
195
+ /*
196
+ * Simple W/R interface to AXI bus
197
+ */
198
+
199
+ axi_writer #(
200
+ .ID_WIDTH(ID_WIDTH)
201
+ ) writer (
202
+ .wvalid(wvalid_checked),
203
+ .*
204
+ );
205
+
206
+ axi_reader #(
207
+ .ID_WIDTH(ID_WIDTH)
208
+ ) reader (
209
+ .*
210
+ );
211
+
212
+ assign wvalid = (state == STATE_WR_HEAD) || (state == STATE_WR_PACKET);
213
+ always @(*) begin
214
+ waddr = 64'd0;
215
+ wstrb = 64'd0;
216
+ wdata = 512'd0;
217
+ if (state == STATE_WR_HEAD) begin
218
+ waddr = head_addr;
219
+ wstrb = 64'hff;
220
+ wdata = {480'd0, head};
221
+ end else if (state == STATE_WR_PACKET) begin
222
+ waddr = cfg_base_addr + PACKET_OFFSET + (head * PACKET_SIZE);
223
+ wstrb = {{((512-64-DW)/8){1'b0}}, {((DW+64)/8){1'b1}}};
224
+ wdata = packet_to_write;
225
+ end
226
+ end
227
+ assign rvalid = (state == STATE_RD_TAIL);
228
+ always @(*) begin
229
+ raddr = 64'd0;
230
+ if (state == STATE_RD_TAIL) begin
231
+ raddr = tail_addr;
232
+ end
233
+ end
234
+
235
+ /*
236
+ * SB handshaking
237
+ */
238
+
239
+ always @(posedge clk) begin
240
+ if (reset) begin
241
+ packet_to_write <= 512'd0;
242
+ end else if (valid && ready) begin
243
+ packet_to_write <= {{(512-64-DW){1'b0}}, data, 31'd0, last, dest};
244
+ end
245
+ end
246
+ assign ready = (state == STATE_IDLE) && en;
247
+
248
+ assign status_idle = state == STATE_IDLE;
249
+
250
+ `ifdef DEBUG
251
+ ila_0 ILA_RD (
252
+ .clk (clk),
253
+ .probe0 (m_axi_arvalid),
254
+ .probe1 (m_axi_araddr),
255
+ .probe2 (m_axi_arready),
256
+ .probe3 (m_axi_rvalid),
257
+ .probe4 (m_axi_rdata[63:0]),
258
+ .probe5 (m_axi_rready)
259
+ );
260
+
261
+ ila_0 ILA_WR (
262
+ .clk (clk),
263
+ .probe0 (m_axi_awvalid),
264
+ .probe1 (m_axi_awaddr),
265
+ .probe2 (m_axi_awready),
266
+ .probe3 (m_axi_wvalid),
267
+ .probe4 (m_axi_wdata[63:0]),
268
+ .probe5 (m_axi_wready)
269
+ );
270
+
271
+ ila_0 ILA_STATE (
272
+ .clk (clk),
273
+ .probe0 (en),
274
+ .probe1 ({head, tail}),
275
+ .probe2 (valid),
276
+ .probe3 (ready),
277
+ .probe4 ({state, head_incr}),
278
+ .probe5 (full)
279
+ );
280
+
281
+ ila_0 ILA_FAULT (
282
+ .clk (clk),
283
+ .probe0 (fault),
284
+ .probe1 (fault_addr),
285
+ .probe2 (),
286
+ .probe3 (),
287
+ .probe4 (),
288
+ .probe5 ()
289
+ );
290
+ `endif
291
+
292
+ endmodule
293
+
294
+ `default_nettype wire
@@ -0,0 +1,146 @@
1
+ // Copyright (c) 2024 Zero ASIC Corporation
2
+ // This code is licensed under Apache License 2.0 (see LICENSE for details)
3
+
4
+ `default_nettype none
5
+
6
+ module umi_fpga_queues #(
7
+ parameter NUM_RX_QUEUES = 1,
8
+ parameter NUM_TX_QUEUES = 1,
9
+ parameter NUM_USER_REGS = 1,
10
+
11
+ parameter integer DW=256,
12
+ parameter integer AW=64,
13
+ parameter integer CW=32
14
+ ) (
15
+ input wire clk,
16
+ input wire nreset,
17
+
18
+ // UMI interfaces
19
+ output wire [NUM_RX_QUEUES*DW-1:0] rx_data,
20
+ output wire [NUM_RX_QUEUES*AW-1:0] rx_srcaddr,
21
+ output wire [NUM_RX_QUEUES*AW-1:0] rx_dstaddr,
22
+ output wire [NUM_RX_QUEUES*CW-1:0] rx_cmd,
23
+ input wire [NUM_RX_QUEUES-1:0] rx_ready,
24
+ output wire [NUM_RX_QUEUES-1:0] rx_valid,
25
+
26
+ input wire [NUM_TX_QUEUES*DW-1:0] tx_data,
27
+ input wire [NUM_TX_QUEUES*AW-1:0] tx_srcaddr,
28
+ input wire [NUM_TX_QUEUES*AW-1:0] tx_dstaddr,
29
+ input wire [NUM_TX_QUEUES*CW-1:0] tx_cmd,
30
+ output wire [NUM_TX_QUEUES-1:0] tx_ready,
31
+ input wire [NUM_TX_QUEUES-1:0] tx_valid,
32
+
33
+ output wire [(NUM_USER_REGS > 0 ? NUM_USER_REGS : 1)*32-1:0] cfg_user,
34
+
35
+ // AXI manager interface for memory access
36
+ output wire [15:0] m_axi_awid,
37
+ output wire [63:0] m_axi_awaddr,
38
+ output wire [7:0] m_axi_awlen,
39
+ output wire [2:0] m_axi_awsize,
40
+ output wire [18:0] m_axi_awuser,
41
+ output wire m_axi_awvalid,
42
+ input wire m_axi_awready,
43
+
44
+ output wire [511:0] m_axi_wdata,
45
+ output wire [63:0] m_axi_wstrb,
46
+ output wire m_axi_wlast,
47
+ output wire m_axi_wvalid,
48
+ input wire m_axi_wready,
49
+
50
+ input wire [15:0] m_axi_bid,
51
+ input wire [1:0] m_axi_bresp,
52
+ input wire m_axi_bvalid,
53
+ output wire m_axi_bready,
54
+
55
+ output wire [15:0] m_axi_arid,
56
+ output wire [63:0] m_axi_araddr,
57
+ output wire [7:0] m_axi_arlen,
58
+ output wire [2:0] m_axi_arsize,
59
+ output wire [18:0] m_axi_aruser,
60
+ output wire m_axi_arvalid,
61
+ input wire m_axi_arready,
62
+
63
+ input wire [15:0] m_axi_rid,
64
+ input wire [511:0] m_axi_rdata,
65
+ input wire [1:0] m_axi_rresp,
66
+ input wire m_axi_rlast,
67
+ input wire m_axi_rvalid,
68
+ output wire m_axi_rready,
69
+
70
+ // AXIL subordinate interface for config registers
71
+ input wire s_axil_awvalid,
72
+ input wire [31:0] s_axil_awaddr,
73
+ output wire s_axil_awready,
74
+
75
+ input wire s_axil_wvalid,
76
+ input wire [31:0] s_axil_wdata,
77
+ input wire [3:0] s_axil_wstrb,
78
+ output wire s_axil_wready,
79
+
80
+ output wire s_axil_bvalid,
81
+ output wire [1:0] s_axil_bresp,
82
+ input wire s_axil_bready,
83
+
84
+ input wire s_axil_arvalid,
85
+ input wire [31:0] s_axil_araddr,
86
+ output wire s_axil_arready,
87
+
88
+ output wire s_axil_rvalid,
89
+ output wire [31:0] s_axil_rdata,
90
+ output wire [1:0] s_axil_rresp,
91
+ input wire s_axil_rready
92
+ );
93
+
94
+ localparam SB_DW = DW + AW + AW + CW;
95
+
96
+ // Pack/unpack UMI signals to/from Switchboard packets
97
+
98
+ genvar i;
99
+ wire [NUM_RX_QUEUES*SB_DW-1:0] sb_rx_data;
100
+ for (i = 0; i < NUM_RX_QUEUES; i = i + 1) begin
101
+ assign rx_cmd[i*CW+:CW] = sb_rx_data[i*SB_DW + CW-1:i*SB_DW];
102
+ assign rx_dstaddr[i*AW+:AW] = sb_rx_data[i*SB_DW + AW+CW-1:i*SB_DW + CW];
103
+ assign rx_srcaddr[i*AW+:AW] = sb_rx_data[i*SB_DW + AW+AW+CW-1:i*SB_DW + AW+CW];
104
+ assign rx_data[i*DW+:DW] = sb_rx_data[i*SB_DW + DW+AW+AW+CW-1:i*SB_DW + AW+AW+CW];
105
+ end
106
+
107
+ wire [NUM_TX_QUEUES*SB_DW-1:0] sb_tx_data;
108
+ wire [NUM_TX_QUEUES*32-1:0] sb_tx_dest;
109
+ wire [NUM_TX_QUEUES-1:0] sb_tx_last;
110
+ for (i = 0; i < NUM_TX_QUEUES; i = i + 1) begin
111
+ assign sb_tx_data[i*SB_DW+:SB_DW] = {
112
+ tx_data[i*DW+:DW], tx_srcaddr[i*AW+:AW], tx_dstaddr[i*AW+:AW], tx_cmd[i*CW+:CW]
113
+ };
114
+ assign sb_tx_dest[i*32+:32] = {16'h0000, tx_dstaddr[i*AW+55:i*AW+40]};
115
+ assign sb_tx_last[i] = tx_cmd[(i*CW)+22];
116
+ end
117
+
118
+ sb_fpga_queues #(
119
+ .NUM_RX_QUEUES(NUM_RX_QUEUES),
120
+ .NUM_TX_QUEUES(NUM_TX_QUEUES),
121
+ .NUM_USER_REGS(NUM_USER_REGS),
122
+
123
+ .DW(SB_DW)
124
+ ) sb_fpga_queues_i (
125
+ .clk(clk),
126
+ .nreset(nreset),
127
+
128
+ .rx_data(sb_rx_data),
129
+ .rx_dest(),
130
+ .rx_last(),
131
+ .rx_ready(rx_ready),
132
+ .rx_valid(rx_valid),
133
+
134
+ .tx_data(sb_tx_data),
135
+ .tx_dest(sb_tx_dest),
136
+ .tx_last(sb_tx_last),
137
+ .tx_ready(tx_ready),
138
+ .tx_valid(tx_valid),
139
+
140
+ // Pass thru AXI ports implicitly
141
+ .*
142
+ );
143
+
144
+ endmodule
145
+
146
+ `default_nettype wire
File without changes
@@ -0,0 +1,25 @@
1
+ // Copyright (c) 2024 Zero ASIC Corporation
2
+ // This code is licensed under Apache License 2.0 (see LICENSE for details)
3
+
4
+ `default_nettype none
5
+
6
+ module auto_stop_sim #(
7
+ parameter CYCLES=50000000
8
+ ) (
9
+ input clk
10
+ );
11
+
12
+ integer i=0;
13
+
14
+ always @(posedge clk) begin
15
+ if (i >= CYCLES) begin
16
+ $display("STOPPING SIMULATION");
17
+ $finish;
18
+ end else begin
19
+ i <= i + 1;
20
+ end
21
+ end
22
+
23
+ endmodule
24
+
25
+ `default_nettype wire
@@ -0,0 +1,97 @@
1
+ // Copyright (c) 2024 Zero ASIC Corporation
2
+ // This code is licensed under Apache License 2.0 (see LICENSE for details)
3
+
4
+ `default_nettype none
5
+
6
+ module perf_meas_sim #(
7
+ // verilog_lint: waive-start parameter-name-style
8
+ parameter integer default_cycles_per_meas=0,
9
+ parameter real max_report_time=3.0,
10
+ parameter real min_report_time=0.3,
11
+ parameter integer search_factor=2
12
+ // verilog_lint: waive-stop parameter-name-style
13
+ ) (
14
+ input clk
15
+ );
16
+ `ifdef __ICARUS__
17
+ `define SB_EXT_FUNC(x) $``x``
18
+ `define SB_START_FUNC task
19
+ `define SB_END_FUNC endtask
20
+ `else
21
+ `define SB_EXT_FUNC(x) x
22
+ `define SB_START_FUNC function automatic void
23
+ `define SB_END_FUNC endfunction
24
+
25
+ import "DPI-C" function void pi_time_taken(output real t);
26
+ `endif
27
+
28
+ // internal signals
29
+ real t;
30
+ real sim_rate;
31
+ integer cycles_per_meas=default_cycles_per_meas;
32
+ integer total_clock_cycles=0;
33
+ string sim_name;
34
+
35
+ `SB_START_FUNC init(input integer n, input string name="");
36
+ cycles_per_meas = n;
37
+ sim_name = name;
38
+ /* verilator lint_off IGNOREDRETURN */
39
+ `SB_EXT_FUNC(pi_time_taken)(t);
40
+ /* verilator lint_on IGNOREDRETURN */
41
+ `SB_END_FUNC
42
+
43
+ initial begin
44
+ /* verilator lint_off IGNOREDRETURN */
45
+ `SB_EXT_FUNC(pi_time_taken)(t); // discard first result since it is invalid
46
+ /* verilator lint_on IGNOREDRETURN */
47
+ end
48
+
49
+ always @(posedge clk) begin
50
+ if (cycles_per_meas == 0) begin
51
+ // do nothing...
52
+ end else if (total_clock_cycles >= cycles_per_meas) begin
53
+ /* verilator lint_off IGNOREDRETURN */
54
+ `SB_EXT_FUNC(pi_time_taken)(t);
55
+ /* verilator lint_on IGNOREDRETURN */
56
+ if (sim_name != "") begin
57
+ $write("%s: ", sim_name);
58
+ end
59
+ sim_rate = (1.0*total_clock_cycles)/t;
60
+ if (sim_rate < 1.0e3) begin
61
+ $display("Simulation rate: %0.3f Hz", sim_rate);
62
+ end else if (sim_rate < 1.0e6) begin
63
+ $display("Simulation rate: %0.3f kHz", 1e-3*sim_rate);
64
+ end else begin
65
+ $display("Simulation rate: %0.3f MHz", 1e-6*sim_rate);
66
+ end
67
+ total_clock_cycles <= 0;
68
+
69
+ // update number of cycles in between updates appropriately
70
+ if (t < min_report_time) begin
71
+ // reporting in too frequent, increase cycles_per_meas
72
+ // to report less frequently
73
+ cycles_per_meas = cycles_per_meas * search_factor;
74
+ end else if (t > max_report_time) begin
75
+ // reporting in too infrequent, decrease cycles_per_meas
76
+ // to report more frequently
77
+ cycles_per_meas = cycles_per_meas / search_factor;
78
+ if (cycles_per_meas == 0) begin
79
+ // but don't let cycles_per_meas drop to zero,
80
+ // since that disables performance measurement
81
+ cycles_per_meas = 1;
82
+ end
83
+ end
84
+ end else begin
85
+ total_clock_cycles <= total_clock_cycles + 1;
86
+ end
87
+ end
88
+
89
+ // clean up macros
90
+
91
+ `undef SB_EXT_FUNC
92
+ `undef SB_START_FUNC
93
+ `undef SB_END_FUNC
94
+
95
+ endmodule
96
+
97
+ `default_nettype wire