Skip to content

Commit b62d7b9

Browse files
authored
Merge pull request #217 from pulp-platform/monitor
axi_sim_mem: Add monitoring interface
2 parents 1c63fdd + c56f54f commit b62d7b9

File tree

2 files changed

+139
-6
lines changed

2 files changed

+139
-6
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
88
## Unreleased
99

1010
### Added
11+
- `axi_sim_mem`: Add monitoring interface to observe the point of coherency between the write and
12+
the read channel.
1113

1214
### Changed
1315

src/axi_sim_mem.sv

+137-6
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,39 @@ module axi_sim_mem #(
4646
/// AXI4 request struct
4747
input axi_req_t axi_req_i,
4848
/// AXI4 response struct
49-
output axi_rsp_t axi_rsp_o
49+
output axi_rsp_t axi_rsp_o,
50+
/// Memory monitor write valid. All `mon_w_*` outputs are only valid if this signal is high.
51+
/// A write to the memory is visible on the `mon_w_*` outputs in the clock cycle after it has
52+
/// happened.
53+
output logic mon_w_valid_o,
54+
/// Memory monitor write address
55+
output logic [AddrWidth-1:0] mon_w_addr_o,
56+
/// Memory monitor write data
57+
output logic [DataWidth-1:0] mon_w_data_o,
58+
/// Memory monitor write ID
59+
output logic [IdWidth-1:0] mon_w_id_o,
60+
/// Memory monitor write user
61+
output logic [UserWidth-1:0] mon_w_user_o,
62+
/// Memory monitor write beat count
63+
output axi_pkg::len_t mon_w_beat_count_o,
64+
/// Memory monitor write last
65+
output logic mon_w_last_o,
66+
/// Memory monitor read valid. All `mon_r_*` outputs are only valid if this signal is high.
67+
/// A read from the memory is visible on the `mon_w_*` outputs in the clock cycle after it has
68+
/// happened.
69+
output logic mon_r_valid_o,
70+
/// Memory monitor read address
71+
output logic [AddrWidth-1:0] mon_r_addr_o,
72+
/// Memory monitor read data
73+
output logic [DataWidth-1:0] mon_r_data_o,
74+
/// Memory monitor read ID
75+
output logic [IdWidth-1:0] mon_r_id_o,
76+
/// Memory monitor read user
77+
output logic [UserWidth-1:0] mon_r_user_o,
78+
/// Memory monitor read beat count
79+
output axi_pkg::len_t mon_r_beat_count_o,
80+
/// Memory monitor read last
81+
output logic mon_r_last_o
5082
);
5183

5284
localparam int unsigned StrbWidth = DataWidth / 8;
@@ -61,6 +93,17 @@ module axi_sim_mem #(
6193
`AXI_TYPEDEF_AR_CHAN_T(ar_t, addr_t, id_t, user_t)
6294
`AXI_TYPEDEF_R_CHAN_T(r_t, data_t, id_t, user_t)
6395

96+
typedef struct packed {
97+
logic valid;
98+
logic [AddrWidth-1:0] addr;
99+
logic [DataWidth-1:0] data;
100+
logic [IdWidth-1:0] id;
101+
logic [UserWidth-1:0] user;
102+
axi_pkg::len_t beat_count;
103+
logic last;
104+
} monitor_t;
105+
106+
monitor_t mon_w, mon_r;
64107
logic [7:0] mem[addr_t];
65108

66109
initial begin
@@ -69,6 +112,9 @@ module axi_sim_mem #(
69112
automatic b_t b_queue[$];
70113
automatic shortint unsigned r_cnt = 0, w_cnt = 0;
71114
axi_rsp_o = '0;
115+
// Monitor interface
116+
mon_w = '0;
117+
mon_r = '0;
72118
wait (rst_ni);
73119
fork
74120
// AW
@@ -87,6 +133,7 @@ module axi_sim_mem #(
87133
@(posedge clk_i);
88134
#(ApplDelay);
89135
axi_rsp_o.w_ready = 1'b0;
136+
mon_w = '0;
90137
if (aw_queue.size() != 0) begin
91138
axi_rsp_o.w_ready = 1'b1;
92139
#(AcqDelay - ApplDelay);
@@ -96,6 +143,12 @@ module axi_sim_mem #(
96143
automatic axi_pkg::size_t size = aw_queue[0].size;
97144
automatic addr_t addr = axi_pkg::beat_addr(aw_queue[0].addr, size, len, burst,
98145
w_cnt);
146+
mon_w.valid = 1'b1;
147+
mon_w.addr = addr;
148+
mon_w.data = axi_req_i.w.data;
149+
mon_w.id = aw_queue[0].id;
150+
mon_w.user = aw_queue[0].user;
151+
mon_w.beat_count = w_cnt;
99152
for (shortint unsigned
100153
i_byte = axi_pkg::beat_lower_byte(addr, size, len, burst, StrbWidth, w_cnt);
101154
i_byte <= axi_pkg::beat_upper_byte(addr, size, len, burst, StrbWidth, w_cnt);
@@ -112,6 +165,7 @@ module axi_sim_mem #(
112165
b_beat.resp = axi_pkg::RESP_OKAY;
113166
b_queue.push_back(b_beat);
114167
w_cnt = 0;
168+
mon_w.last = 1'b1;
115169
void'(aw_queue.pop_front());
116170
end else begin
117171
assert (!axi_req_i.w.last) else $error("Did not expect last beat of W burst!");
@@ -150,6 +204,7 @@ module axi_sim_mem #(
150204
@(posedge clk_i);
151205
#(ApplDelay);
152206
axi_rsp_o.r_valid = 1'b0;
207+
mon_r = '0;
153208
if (ar_queue.size() != 0) begin
154209
automatic axi_pkg::burst_t burst = ar_queue[0].burst;
155210
automatic axi_pkg::len_t len = ar_queue[0].len;
@@ -176,13 +231,21 @@ module axi_sim_mem #(
176231
end
177232
if (r_cnt == ar_queue[0].len) begin
178233
r_beat.last = 1'b1;
234+
mon_r.last = 1'b1;
179235
end
180236
axi_rsp_o.r = r_beat;
181237
axi_rsp_o.r_valid = 1'b1;
238+
mon_r.valid = 1'b1;
239+
mon_r.addr = addr;
240+
mon_r.data = r_beat.data;
241+
mon_r.id = r_beat.id;
242+
mon_r.user = r_beat.user;
243+
mon_r.beat_count = r_cnt;
182244
#(AcqDelay - ApplDelay);
183245
while (!axi_req_i.r_ready) begin
184246
@(posedge clk_i);
185247
#(AcqDelay);
248+
mon_r = '0;
186249
end
187250
if (r_beat.last) begin
188251
r_cnt = 0;
@@ -195,6 +258,46 @@ module axi_sim_mem #(
195258
join
196259
end
197260

261+
// Assign the monitor output in the next clock cycle. Rationale: We only know whether we are
262+
// writing until after `AcqDelay`. This means we could only provide the monitoring output for
263+
// writes after `AcqDelay` in the same cycle, which is incompatible with ATI timing. Thus, we
264+
// provide the monitoring output for writes (and for uniformity also for reads) in the next clock
265+
// cycle.
266+
initial begin
267+
mon_w_valid_o = '0;
268+
mon_w_addr_o = '0;
269+
mon_w_data_o = '0;
270+
mon_w_id_o = '0;
271+
mon_w_user_o = '0;
272+
mon_w_beat_count_o = '0;
273+
mon_w_last_o = '0;
274+
mon_r_valid_o = '0;
275+
mon_r_addr_o = '0;
276+
mon_r_data_o = '0;
277+
mon_r_id_o = '0;
278+
mon_r_user_o = '0;
279+
mon_r_beat_count_o = '0;
280+
mon_r_last_o = '0;
281+
wait (rst_ni);
282+
forever begin
283+
@(posedge clk_i);
284+
mon_w_valid_o <= #(ApplDelay) mon_w.valid;
285+
mon_w_addr_o <= #(ApplDelay) mon_w.addr;
286+
mon_w_data_o <= #(ApplDelay) mon_w.data;
287+
mon_w_id_o <= #(ApplDelay) mon_w.id;
288+
mon_w_user_o <= #(ApplDelay) mon_w.user;
289+
mon_w_beat_count_o <= #(ApplDelay) mon_w.beat_count;
290+
mon_w_last_o <= #(ApplDelay) mon_w.last;
291+
mon_r_valid_o <= #(ApplDelay) mon_r.valid;
292+
mon_r_addr_o <= #(ApplDelay) mon_r.addr;
293+
mon_r_data_o <= #(ApplDelay) mon_r.data;
294+
mon_r_id_o <= #(ApplDelay) mon_r.id;
295+
mon_r_user_o <= #(ApplDelay) mon_r.user;
296+
mon_r_beat_count_o <= #(ApplDelay) mon_r.beat_count;
297+
mon_r_last_o <= #(ApplDelay) mon_r.last;
298+
end
299+
end
300+
198301
// Parameter Assertions
199302
initial begin
200303
assert (AddrWidth != 0) else $fatal("AddrWidth must be non-zero!", 1);
@@ -220,9 +323,23 @@ module axi_sim_mem_intf #(
220323
parameter time APPL_DELAY = 0ps,
221324
parameter time ACQ_DELAY = 0ps
222325
) (
223-
input logic clk_i,
224-
input logic rst_ni,
225-
AXI_BUS.Slave axi_slv
326+
input logic clk_i,
327+
input logic rst_ni,
328+
AXI_BUS.Slave axi_slv,
329+
output logic mon_w_valid_o,
330+
output logic [AXI_ADDR_WIDTH-1:0] mon_w_addr_o,
331+
output logic [AXI_DATA_WIDTH-1:0] mon_w_data_o,
332+
output logic [AXI_ID_WIDTH-1:0] mon_w_id_o,
333+
output logic [AXI_USER_WIDTH-1:0] mon_w_user_o,
334+
output axi_pkg::len_t mon_w_beat_count_o,
335+
output logic mon_w_last_o,
336+
output logic mon_r_valid_o,
337+
output logic [AXI_ADDR_WIDTH-1:0] mon_r_addr_o,
338+
output logic [AXI_DATA_WIDTH-1:0] mon_r_data_o,
339+
output logic [AXI_ID_WIDTH-1:0] mon_r_id_o,
340+
output logic [AXI_USER_WIDTH-1:0] mon_r_user_o,
341+
output axi_pkg::len_t mon_r_beat_count_o,
342+
output logic mon_r_last_o
226343
);
227344

228345
typedef logic [AXI_ADDR_WIDTH-1:0] axi_addr_t;
@@ -251,8 +368,22 @@ module axi_sim_mem_intf #(
251368
) i_sim_mem (
252369
.clk_i,
253370
.rst_ni,
254-
.axi_req_i (axi_req),
255-
.axi_rsp_o (axi_rsp)
371+
.axi_req_i (axi_req),
372+
.axi_rsp_o (axi_rsp),
373+
.mon_w_valid_o,
374+
.mon_w_addr_o,
375+
.mon_w_data_o,
376+
.mon_w_id_o,
377+
.mon_w_user_o,
378+
.mon_w_beat_count_o,
379+
.mon_w_last_o,
380+
.mon_r_valid_o,
381+
.mon_r_addr_o,
382+
.mon_r_data_o,
383+
.mon_r_id_o,
384+
.mon_r_user_o,
385+
.mon_r_beat_count_o,
386+
.mon_r_last_o
256387
);
257388

258389
endmodule

0 commit comments

Comments
 (0)