diff options
Diffstat (limited to 'rtl/perf/perf_link.sv')
| -rw-r--r-- | rtl/perf/perf_link.sv | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/rtl/perf/perf_link.sv b/rtl/perf/perf_link.sv new file mode 100644 index 0000000..323af45 --- /dev/null +++ b/rtl/perf/perf_link.sv @@ -0,0 +1,181 @@ +`include "cache/defs.sv" + +module perf_link +( + input logic clk, + rst_n, + + input logic in_left_valid, + input ring_req in_left, + output logic in_left_ready, + + input logic in_right_valid, + input ring_req in_right, + input logic in_right_ready, + + input logic out_left_ready, + output ring_req out_left, + output logic out_left_valid, + + input line_ptr local_address, + input logic local_read, + local_write, + input line local_writedata, + input line_be local_byteenable, + output logic local_waitrequest, + output line local_readdata, + + input logic mem_waitrequest, + input line mem_readdata, + output word mem_address, + output logic mem_read, + mem_write, + output line mem_writedata, + output line_be mem_byteenable, + + input logic clear, + input logic[3:0] address, + output word readdata +); + + logic snoop_left_ready, snoop_left_valid, snoop_right_ready, snoop_right_valid, + snoop_read, snoop_write, snoop_waitrequest, cached; + + addr_bits snoop_addr_bits; + perf_sample snoop_left, snoop_right; + + word reads, writes, ring_reads, ring_invals, ring_read_invals, ring_replies, ring_forwards, + io_reads, io_writes, snoop_address; + + hword mem_cycles, mem_cycles_hold, ring_cycles, min_ring_cycles, max_ring_cycles, + min_read_cycles, max_read_cycles, min_write_cycles, max_write_cycles; + + perf_snoop snoop + ( + .* + ); + + assign cached = snoop_addr_bits.io == `IO_CACHED; + assign mem_cycles = mem_cycles_hold + 1; + assign snoop_addr_bits = snoop_address; + + always_comb + if (!address[3]) unique case (address[2:0]) + 3'b000: readdata = reads; + 3'b001: readdata = writes; + 3'b010: readdata = {max_read_cycles, min_read_cycles}; + 3'b011: readdata = {max_write_cycles, min_write_cycles}; + 3'b100: readdata = ring_reads; + 3'b101: readdata = ring_invals; + 3'b110: readdata = ring_read_invals; + 3'b111: readdata = ring_replies; + endcase else unique case (address[1:0]) + 2'b00: readdata = ring_forwards; + 2'b01: readdata = {max_ring_cycles, min_ring_cycles}; + 2'b10: readdata = io_reads; + 2'b11: readdata = io_writes; + endcase + + always @(posedge clk or negedge rst_n) + if (!rst_n) begin + reads <= 0; + writes <= 0; + io_reads <= 0; + io_writes <= 0; + + min_ring_cycles <= 0; + max_ring_cycles <= 0; + min_read_cycles <= 0; + max_read_cycles <= 0; + min_write_cycles <= 0; + max_write_cycles <= 0; + + ring_reads <= 0; + ring_invals <= 0; + ring_replies <= 0; + ring_forwards <= 0; + ring_read_invals <= 0; + + mem_cycles_hold <= 0; + end else begin + ring_cycles <= ring_cycles + 1; + + if (mem_read || mem_write) + mem_cycles_hold <= mem_cycles; + + if ((mem_read || mem_write) && !mem_waitrequest) begin + mem_cycles_hold <= 0; + + if (!cached) begin + if (mem_write) + io_writes <= io_writes + 1; + else + io_reads <= io_reads + 1; + end else if (mem_write) begin + writes <= writes + 1; + + if (min_write_cycles == 0 || mem_cycles_hold < min_write_cycles) + min_write_cycles <= mem_cycles; + + if (mem_cycles_hold >= max_write_cycles) + max_write_cycles <= mem_cycles; + end else begin + reads <= reads + 1; + + if (min_read_cycles == 0 || mem_cycles_hold < min_read_cycles) + min_read_cycles <= mem_cycles; + + if (mem_cycles_hold >= max_read_cycles) + max_read_cycles <= mem_cycles; + end + end + + if (snoop_left_valid && snoop_left_ready && snoop_left.ttl == `TTL_END) begin + if (snoop_left.reply) + ring_replies <= ring_replies + 1; + + if (min_ring_cycles == 0 || ring_cycles < min_ring_cycles) + min_ring_cycles <= ring_cycles; + + if (ring_cycles > max_ring_cycles) + max_ring_cycles <= ring_cycles; + end + + if (snoop_right_valid && snoop_right_ready) begin + if (snoop_right.ttl == `TTL_MAX) begin + ring_cycles <= 1; + + if (snoop_right.read && !snoop_right.inval) + ring_reads <= ring_reads + 1; + + if (!snoop_right.read && snoop_right.inval) + ring_invals <= ring_invals + 1; + + if (snoop_right.read && snoop_right.inval) + ring_read_invals <= ring_read_invals + 1; + end else + ring_forwards <= ring_forwards + 1; + end + + if (clear) begin + reads <= 0; + writes <= 0; + io_reads <= 0; + io_writes <= 0; + + min_ring_cycles <= 0; + max_ring_cycles <= 0; + min_read_cycles <= 0; + max_read_cycles <= 0; + min_write_cycles <= 0; + max_write_cycles <= 0; + + ring_reads <= 0; + ring_invals <= 0; + ring_replies <= 0; + ring_forwards <= 0; + ring_read_invals <= 0; + end + end + +endmodule |
