Skip to content

Commit 65ab2a8

Browse files
author
Andrea Belano
committed
[treewide] initial support for X Interface
1 parent 5b2fccd commit 65ab2a8

File tree

7 files changed

+211
-12
lines changed

7 files changed

+211
-12
lines changed

hw/snitch/src/snitch.sv

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
5151
parameter type acc_resp_t = logic,
5252
parameter type pa_t = logic,
5353
parameter type l0_pte_t = logic,
54+
// XIF parameters
55+
parameter int unsigned XifIdWidth = 4,
56+
// XIF port types
57+
parameter type x_issue_req_t = logic,
58+
parameter type x_issue_resp_t = logic,
59+
parameter type x_result_t = logic,
5460
parameter int unsigned NumIntOutstandingLoads = 0,
5561
parameter int unsigned NumIntOutstandingMem = 0,
5662
parameter int unsigned NumDTLBEntries = 0,
@@ -91,6 +97,15 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
9197
input acc_resp_t acc_prsp_i,
9298
input logic acc_pvalid_i,
9399
output logic acc_pready_o,
100+
// X Interface - Issue ports
101+
output x_issue_req_t x_issue_req_o,
102+
input x_issue_resp_t x_issue_resp_i,
103+
output logic x_issue_valid_o,
104+
input logic x_issue_ready_i,
105+
// X Interface - Result ports
106+
input x_result_t x_result_i,
107+
input logic x_result_valid_i,
108+
output logic x_result_ready_o,
94109
/// TCDM Data Interface
95110
/// Write transactions do not return data on the `P Channel`
96111
/// Transactions need to be handled strictly in-order.
@@ -148,15 +163,15 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
148163
assign simm = $signed({inst_data_i[31:25], inst_data_i[11:7]});
149164
/* verilator lint_on WIDTH */
150165

151-
logic [31:0] opa, opb;
166+
logic [31:0] opa, opb, opc;
152167
logic [32:0] adder_result;
153168
logic [31:0] alu_result;
154169

155-
logic [RegWidth-1:0] rd, rs1, rs2;
156-
logic stall, lsu_stall, acc_stall, nonacc_stall, fence_stall;
170+
logic [RegWidth-1:0] rd, rs1, rs2, rs3;
171+
logic stall, lsu_stall, acc_stall, nonacc_stall, fence_stall, x_stall;
157172
// Register connections
158-
logic [1:0][RegWidth-1:0] gpr_raddr;
159-
logic [1:0][31:0] gpr_rdata;
173+
logic [2:0][RegWidth-1:0] gpr_raddr;
174+
logic [2:0][31:0] gpr_rdata;
160175
logic [0:0][RegWidth-1:0] gpr_waddr;
161176
logic [0:0][31:0] gpr_wdata;
162177
logic [0:0] gpr_we;
@@ -209,6 +224,7 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
209224
logic retire_load; // retire a load instruction
210225
logic retire_i; // retire the rest of the base instruction set
211226
logic retire_acc; // retire an instruction we offloaded
227+
logic retire_x; // retire a XIF-offloaded instruction
212228

213229
logic valid_instr;
214230
logic exception;
@@ -227,7 +243,7 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
227243
typedef enum logic [3:0] {
228244
None, Reg, IImmediate, UImmediate, JImmediate, SImmediate, SFImmediate, PC, CSR, CSRImmmediate
229245
} op_select_e;
230-
op_select_e opa_select, opb_select;
246+
op_select_e opa_select, opb_select, opc_select;
231247

232248
logic write_rd; // write destination this cycle
233249
logic uses_rd;
@@ -338,6 +354,7 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
338354
`FFAR(sb_q, sb_d, '0, clk_i, rst_i)
339355
`FFAR(fcsr_q, fcsr_d, '0, clk_i, rst_i)
340356

357+
// TODO(abelano) Should we add a performance counter for the XIF?
341358
// performance counter
342359
`ifdef SNITCH_ENABLE_PERF
343360
logic [63:0] cycle_q;
@@ -374,6 +391,10 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
374391
// operand C is currently only used for load/store instructions
375392
assign acc_qreq_o.data_argc = ls_paddr;
376393

394+
// XIF ID counter
395+
logic [XifIdWidth-1:0] xif_offload_counter_q;
396+
`FFLAR(xif_offload_counter_q, xif_offload_counter_q + 1, x_issue_ready_i & x_issue_valid_o, '0, clk_i, rst_i)
397+
377398
// ---------
378399
// L0 ITLB
379400
// ---------
@@ -441,13 +462,17 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
441462
sb_d = sb_q;
442463
if (retire_load) sb_d[lsu_rd] = 1'b0;
443464
// only place the reservation if we actually executed the load or offload instruction
444-
if ((is_load | acc_register_rd) && !stall && !exception) sb_d[rd] = 1'b1;
465+
if ((is_load | acc_register_rd | x_issue_valid_o & x_issue_ready_i & x_issue_resp_i.writeback) && !stall && !exception) sb_d[rd] = 1'b1;
445466
if (retire_acc) sb_d[acc_prsp_i.id[RegWidth-1:0]] = 1'b0;
467+
if (retire_x) sb_d[x_result_i.rd] = 1'b0;
446468
sb_d[0] = 1'b0;
447469
end
448470
// TODO(zarubaf): This can probably be described a bit more efficient
449471
assign opa_ready = (opa_select != Reg) | ~sb_q[rs1];
450472
assign opb_ready = (opb_select != Reg & opb_select != SImmediate) | ~sb_q[rs2];
473+
assign opc_ready = (opc_select != Reg) | ~sb_q[rs3];
474+
475+
// Here we do not use the opc_ready signal
451476
assign operands_ready = opa_ready & opb_ready;
452477
// either we are not using the destination register or we need to make
453478
// sure that its destination operand is not marked busy in the scoreboard.
@@ -460,14 +485,16 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
460485
& ((itlb_valid & itlb_ready) | ~trans_active);
461486
// the accelerator interface stalled us. Also wait for CAQ if this is an FP load/store.
462487
assign acc_stall = acc_qvalid_o & ~acc_qready_i | (caq_ena & ~caq_qready);
488+
// the coprocessor is not ready yet
489+
assign x_stall = x_issue_valid_o & ~x_issue_ready_i;
463490
// the LSU Interface didn't accept our request yet
464491
assign lsu_stall = lsu_tlb_qvalid & ~lsu_tlb_qready;
465492
// Stall the stage if we either didn't get a valid instruction, the LSU is not ready
466493
// or we are waiting on a fence instruction.
467494
// We do not include accelerator stalls in this signal for loop-free CAQ enable control.
468495
assign nonacc_stall = ~valid_instr | lsu_stall | fence_stall;
469496
// To get the signal for all stall conditions, add the accelerator stalls.
470-
assign stall = nonacc_stall | acc_stall;
497+
assign stall = nonacc_stall | acc_stall | x_stall;
471498

472499
// --------------------
473500
// Instruction Frontend
@@ -510,6 +537,7 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
510537
assign rd = inst_data_i[7 + RegWidth - 1:7];
511538
assign rs1 = inst_data_i[15 + RegWidth - 1:15];
512539
assign rs2 = inst_data_i[20 + RegWidth - 1:20];
540+
assign rs3 = inst_data_i[27 + RegWidth - 1:20];
513541

514542
always_comb begin
515543
illegal_inst = 1'b0;
@@ -518,6 +546,10 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
518546
alu_op = Add;
519547
opa_select = None;
520548
opb_select = None;
549+
opc_select = None;
550+
551+
x_issue_req_o = '0;
552+
x_issue_valid_o = '0;
521553

522554
flush_i_valid_o = 1'b0;
523555
tlb_flush = 1'b0;
@@ -2268,8 +2300,27 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
22682300
end else illegal_inst = 1'b1;
22692301
end
22702302

2271-
default: begin
2272-
illegal_inst = 1'b1;
2303+
default: begin // Offload the instruction to the coprocessor
2304+
opa_select = Reg;
2305+
opb_select = Reg;
2306+
opc_select = Reg;
2307+
2308+
x_issue_req_o.instr = inst_data_i;
2309+
x_issue_req_o.mode = priv_lvl_q;
2310+
x_issue_req_o.id = xif_offload_counter_q;
2311+
x_issue_req_o.rs = {rs3, rs2, rs1};
2312+
x_issue_req_o.rs_valid = {~sb_q[rs3], ~sb_q[rs2], ~sb_q[rs1]};
2313+
x_issue_req_o.ecs = '0; // Not implemented
2314+
x_issue_req_o.ecs_valid = '0; // Not implemented
2315+
2316+
// Since we canno know whether a source register will be used or not by the processor,
2317+
// here we do not use valid_instr as in the other instructions
2318+
x_issue_valid_o = inst_ready_i
2319+
& inst_valid_o
2320+
& ((itlb_valid & itlb_ready) | ~trans_active);
2321+
2322+
// Flag the instruction as illegal if not accepted by the coprocessor or if it requests an unsupported operation
2323+
illegal_inst = x_issue_ready_i & x_issue_valid_o & (~x_issue_resp_i.accept | |{x_issue_resp_i.dualwrite, x_issue_resp_i.dualread, x_issue_resp_i.loadstore, x_issue_resp_i.ecswrite});
22732324
end
22742325
endcase
22752326

@@ -2691,7 +2742,7 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
26912742

26922743
snitch_regfile #(
26932744
.DataWidth ( 32 ),
2694-
.NrReadPorts ( 2 ),
2745+
.NrReadPorts ( 3 ),
26952746
.NrWritePorts ( 1 ),
26962747
.ZeroRegZero ( 1 ),
26972748
.AddrWidth ( RegWidth )
@@ -2731,8 +2782,18 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
27312782
endcase
27322783
end
27332784

2785+
// The C operand is currently only used for XIF instructions
2786+
always_comb begin
2787+
unique case (opc_select)
2788+
None: opc = '0;
2789+
Reg: opc = gpr_rdata[2];
2790+
default: opc = '0;
2791+
endcase
2792+
end
2793+
27342794
assign gpr_raddr[0] = rs1;
27352795
assign gpr_raddr[1] = rs2;
2796+
assign gpr_raddr[2] = rs3;
27362797

27372798
// --------------------
27382799
// ALU
@@ -2985,8 +3046,11 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
29853046
// external interfaces
29863047
lsu_pready = 1'b0;
29873048
acc_pready_o = 1'b0;
3049+
// Always assert x_result_ready if the coprocessor does not request a write
3050+
x_result_ready_o = ~x_result_i.we;
29883051
retire_acc = 1'b0;
29893052
retire_load = 1'b0;
3053+
retire_x = 1'b0;
29903054

29913055
if (retire_i) begin
29923056
gpr_we[0] = 1'b1;
@@ -3003,6 +3067,12 @@ module snitch import snitch_pkg::*; import riscv_instr::*; #(
30033067
gpr_waddr[0] = acc_prsp_i.id;
30043068
gpr_wdata[0] = acc_prsp_i.data[31:0];
30053069
acc_pready_o = 1'b1;
3070+
end else if (x_result_valid_i & x_result_i.we) begin
3071+
retire_x = 1'b1;
3072+
gpr_we[0] = 1'b1;
3073+
gpr_waddr[0] = x_result_i.rd;
3074+
gpr_wdata[0] = x_result_i.data[31:0];
3075+
x_result_ready_o = 1'b1;
30063076
end
30073077
end
30083078

hw/snitch_cluster/src/snitch_cc.sv

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ module snitch_cc #(
4545
parameter type acc_req_t = logic,
4646
parameter type acc_resp_t = logic,
4747
parameter type dma_events_t = logic,
48+
// XIF parameters
49+
parameter int unsigned XifIdWidth = 4,
50+
// XIF port types
51+
parameter type x_issue_req_t = logic,
52+
parameter type x_issue_resp_t = logic,
53+
parameter type x_result_t = logic,
4854
parameter fpnew_pkg::fpu_implementation_t FPUImplementation = '0,
4955
/// Boot address of core.
5056
parameter logic [31:0] BootAddr = 32'h0000_1000,
@@ -133,7 +139,15 @@ module snitch_cc #(
133139
// TCDM Streamer Ports
134140
output tcdm_req_t [TCDMPorts-1:0] tcdm_req_o,
135141
input tcdm_rsp_t [TCDMPorts-1:0] tcdm_rsp_i,
136-
// Accelerator Offload port
142+
// X Interface - Issue ports
143+
output x_issue_req_t x_issue_req_o,
144+
input x_issue_resp_t x_issue_resp_i,
145+
output logic x_issue_valid_o,
146+
input logic x_issue_ready_i,
147+
// X Interface - Result ports
148+
input x_result_t x_result_i,
149+
input logic x_result_valid_i,
150+
output logic x_result_ready_o,
137151
// DMA ports
138152
output axi_req_t [DMANumChannels-1:0] axi_dma_req_o,
139153
input axi_rsp_t [DMANumChannels-1:0] axi_dma_res_i,
@@ -222,6 +236,10 @@ module snitch_cc #(
222236
.drsp_t (drsp_t),
223237
.pa_t (pa_t),
224238
.l0_pte_t (l0_pte_t),
239+
.XifIdWidth (XifIdWidth),
240+
.x_issue_req_t (x_issue_req_t),
241+
.x_issue_resp_t (x_issue_resp_t),
242+
.x_result_t (x_result_t),
225243
.BootAddr (BootAddr),
226244
.SnitchPMACfg (SnitchPMACfg),
227245
.NumIntOutstandingLoads (NumIntOutstandingLoads),
@@ -266,6 +284,13 @@ module snitch_cc #(
266284
.acc_prsp_i ( acc_demux_snitch ),
267285
.acc_pvalid_i ( acc_demux_snitch_valid ),
268286
.acc_pready_o ( acc_demux_snitch_ready ),
287+
.x_issue_req_o ( x_issue_req_o ),
288+
.x_issue_resp_i ( x_issue_resp_i ),
289+
.x_issue_valid_o ( x_issue_valid_o ),
290+
.x_issue_ready_i ( x_issue_ready_i ),
291+
.x_result_i ( x_result_i ),
292+
.x_result_valid_i ( x_result_valid_i ),
293+
.x_result_ready_o ( x_result_ready_o ),
269294
.caq_pvalid_i ( caq_pvalid_q ),
270295
.data_req_o ( snitch_dreq_d ),
271296
.data_rsp_i ( snitch_drsp_d ),

hw/snitch_cluster/src/snitch_cluster.sv

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ module snitch_cluster
206206
// Memory configuration input types; these vary depending on implementation.
207207
parameter type sram_cfg_t = logic,
208208
parameter type sram_cfgs_t = logic,
209+
// XIF parameters
210+
parameter int unsigned XifIdWidth = 4,
211+
// XIF port types
212+
parameter type x_issue_req_t = logic,
213+
parameter type x_issue_resp_t = logic,
214+
parameter type x_result_t = logic,
209215
// Memory latency parameter. Most of the memories have a read latency of 1. In
210216
// case you have memory macros which are pipelined you want to adjust this
211217
// value here. This only applies to the TCDM. The instruction cache macros will break!
@@ -270,6 +276,15 @@ module snitch_cluster
270276
/// AXI DMA cluster in-port.
271277
input wide_in_req_t wide_in_req_i,
272278
output wide_in_resp_t wide_in_resp_o,
279+
// X Interface - Issue ports
280+
output x_issue_req_t [NrCores-1:0] x_issue_req_o,
281+
input x_issue_resp_t [NrCores-1:0] x_issue_resp_i,
282+
output logic [NrCores-1:0] x_issue_valid_o,
283+
input logic [NrCores-1:0] x_issue_ready_i,
284+
// X Interface - Result ports
285+
input x_result_t [NrCores-1:0] x_result_i,
286+
input logic [NrCores-1:0] x_result_valid_i,
287+
output logic [NrCores-1:0] x_result_ready_o,
273288
// An additional AXI Core cluster out-port, used e.g. to connect
274289
// to the configuration interface of an external accelerator.
275290
// Compared to the `narrow_out` interface, the address space of
@@ -1035,6 +1050,10 @@ module snitch_cluster
10351050
.acc_req_t (acc_req_t),
10361051
.acc_resp_t (acc_resp_t),
10371052
.dma_events_t (dma_events_t),
1053+
.XifIdWidth (XifIdWidth),
1054+
.x_issue_req_t (x_issue_req_t),
1055+
.x_issue_resp_t (x_issue_resp_t),
1056+
.x_result_t (x_result_t),
10381057
.BootAddr (BootAddrInternal),
10391058
.RVE (RVE[i]),
10401059
.RVF (RVF[i]),
@@ -1094,6 +1113,13 @@ module snitch_cluster
10941113
.data_rsp_i (core_rsp[i]),
10951114
.tcdm_req_o (tcdm_req_wo_user),
10961115
.tcdm_rsp_i (tcdm_rsp[TcdmPortsOffs+:TcdmPorts]),
1116+
.x_issue_req_o (x_issue_req_o[i]),
1117+
.x_issue_resp_i (x_issue_resp_i[i]),
1118+
.x_issue_valid_o (x_issue_valid_o[i]),
1119+
.x_issue_ready_i (x_issue_ready_i[i]),
1120+
.x_result_i (x_result_i[i]),
1121+
.x_result_valid_i (x_result_valid_i[i]),
1122+
.x_result_ready_o (x_result_ready_o[i]),
10971123
.axi_dma_req_o (axi_dma_req),
10981124
.axi_dma_res_i (axi_dma_res),
10991125
.axi_dma_busy_o (),

hw/snitch_cluster/src/snitch_cluster_pkg.sv.tpl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ package ${cfg['cluster']['name']}_pkg;
6767
localparam int unsigned ICacheLineCount [NrHives] = '{${icache_cfg('depth')}};
6868
localparam int unsigned ICacheWays [NrHives] = '{${icache_cfg('ways')}};
6969

70+
localparam int unsigned XifIdWidth = ${cfg['cluster']['xif_id_width']};
71+
7072
localparam int unsigned Hive [NrCores] = '{${core_cfg('hive')}};
7173

7274
localparam int unsigned TcdmAddrWidth = $clog2(TcdmSize*1024);
@@ -104,6 +106,40 @@ package ${cfg['cluster']['name']}_pkg;
104106

105107
`TCDM_TYPEDEF_ALL(tcdm_dma, tcdm_addr_t, data_dma_t, strb_dma_t, logic)
106108

109+
typedef struct packed {
110+
logic [31:0] instr;
111+
logic [1:0] mode;
112+
logic [XifIdWidth-1:0] id;
113+
logic [2:0][31:0] rs;
114+
logic [2:0] rs_valid;
115+
logic [5:0] ecs;
116+
logic ecs_valid;
117+
} x_issue_req_t;
118+
119+
typedef struct packed {
120+
logic accept;
121+
logic writeback;
122+
logic dualwrite;
123+
logic [2:0] dualread;
124+
logic loadstore;
125+
logic ecswrite;
126+
logic exc;
127+
} x_issue_resp_t;
128+
129+
typedef struct packed {
130+
logic [XifIdWidth-1:0] id;
131+
logic [31:0] data;
132+
logic [4:0] rd;
133+
logic we;
134+
logic [5:0] ecsdata;
135+
logic [2:0] ecswe;
136+
logic exc;
137+
logic [5:0] exccode;
138+
logic err;
139+
logic dbg;
140+
} x_result_t;
141+
142+
107143
function automatic snitch_pma_pkg::rule_t [snitch_pma_pkg::NrMaxRules-1:0] get_cached_regions();
108144
automatic snitch_pma_pkg::rule_t [snitch_pma_pkg::NrMaxRules-1:0] cached_regions;
109145
cached_regions = '{default: '0};

0 commit comments

Comments
 (0)