summaryrefslogtreecommitdiff
path: root/rtl/perf/link.sv
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2023-10-05 16:26:26 -0600
committerAlejandro Soto <alejandro@34project.org>2023-10-05 17:16:55 -0600
commitd406720cecd7328f595255e65b6fd6b6814cefe4 (patch)
treec085f1b4a2d30df0c08cd1efcbf3503ee40c5354 /rtl/perf/link.sv
parentdc705df98037bfd9db8efded025651b676e87754 (diff)
rtl/perf: implement performance unit
Diffstat (limited to 'rtl/perf/link.sv')
-rw-r--r--rtl/perf/link.sv181
1 files changed, 181 insertions, 0 deletions
diff --git a/rtl/perf/link.sv b/rtl/perf/link.sv
new file mode 100644
index 0000000..0899399
--- /dev/null
+++ b/rtl/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,
+ output 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