CVXIF 1.0.0 (#2340)

This commit is contained in:
Guillaume Chauvon 2024-07-12 10:53:18 +02:00 committed by GitHub
parent 5fcc39dbee
commit 8fa590b5c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 1656 additions and 662 deletions

View file

@ -398,7 +398,7 @@ generated_tests:
- mv verif/sim/seedlist.yaml artifacts/coverage - mv verif/sim/seedlist.yaml artifacts/coverage
- python3 .gitlab-ci/scripts/report_pass.py - python3 .gitlab-ci/scripts/report_pass.py
generated_xif_tests: .generated_xif_tests:
extends: extends:
- .verif_test - .verif_test
variables: variables:
@ -519,7 +519,7 @@ code_coverage-report:
needs: needs:
- generated_tests - generated_tests
- directed_isacov-tests - directed_isacov-tests
- generated_xif_tests # - generated_xif_tests
- csr_embedded_tests - csr_embedded_tests
variables: variables:
DASHBOARD_JOB_TITLE: "Report merge coverage" DASHBOARD_JOB_TITLE: "Report merge coverage"

View file

@ -1,2 +1,2 @@
cv32a65x: cv32a65x:
gates: 162197 gates: 163431

View file

@ -76,7 +76,6 @@ sources:
- core/include/std_cache_pkg.sv - core/include/std_cache_pkg.sv
# Extension Interface # Extension Interface
- core/include/cvxif_pkg.sv
- core/cvxif_example/include/cvxif_instr_pkg.sv - core/cvxif_example/include/cvxif_instr_pkg.sv
- core/cvxif_fu.sv - core/cvxif_fu.sv
- core/cvxif_example/cvxif_example_coprocessor.sv - core/cvxif_example/cvxif_example_coprocessor.sv

View file

@ -71,11 +71,14 @@ ${CVA6_REPO_DIR}/core/include/instr_tracer_pkg.sv
${CVA6_REPO_DIR}/core/include/build_config_pkg.sv ${CVA6_REPO_DIR}/core/include/build_config_pkg.sv
//CVXIF //CVXIF
${CVA6_REPO_DIR}/core/include/cvxif_pkg.sv ${CVA6_REPO_DIR}/core/cvxif_compressed_if_driver.sv
${CVA6_REPO_DIR}/core/cvxif_issue_register_commit_if_driver.sv
${CVA6_REPO_DIR}/core/cvxif_example/include/cvxif_instr_pkg.sv ${CVA6_REPO_DIR}/core/cvxif_example/include/cvxif_instr_pkg.sv
${CVA6_REPO_DIR}/core/cvxif_fu.sv ${CVA6_REPO_DIR}/core/cvxif_fu.sv
${CVA6_REPO_DIR}/core/cvxif_example/cvxif_example_coprocessor.sv ${CVA6_REPO_DIR}/core/cvxif_example/cvxif_example_coprocessor.sv
${CVA6_REPO_DIR}/core/cvxif_example/instr_decoder.sv ${CVA6_REPO_DIR}/core/cvxif_example/instr_decoder.sv
${CVA6_REPO_DIR}/core/cvxif_example/compressed_instr_decoder.sv
${CVA6_REPO_DIR}/core/cvxif_example/copro_alu.sv
// Common Cells // Common Cells
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/cf_math_pkg.sv ${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/cf_math_pkg.sv

View file

@ -27,12 +27,11 @@ ${CVA6_REPO_DIR}/core/include/instr_tracer_pkg.sv
${CVA6_REPO_DIR}/core/include/build_config_pkg.sv ${CVA6_REPO_DIR}/core/include/build_config_pkg.sv
//CVXIF //CVXIF
${CVA6_REPO_DIR}/core/include/cvxif_pkg.sv
${CVA6_REPO_DIR}/core/cvxif_example/include/cvxif_instr_pkg.sv ${CVA6_REPO_DIR}/core/cvxif_example/include/cvxif_instr_pkg.sv
${CVA6_REPO_DIR}/core/cvxif_fu.sv
${CVA6_REPO_DIR}/core/cvxif_example/cvxif_example_coprocessor.sv ${CVA6_REPO_DIR}/core/cvxif_example/cvxif_example_coprocessor.sv
${CVA6_REPO_DIR}/core/cvxif_example/instr_decoder.sv ${CVA6_REPO_DIR}/core/cvxif_example/instr_decoder.sv
${CVA6_REPO_DIR}/core/cva6_fifo_v3.sv ${CVA6_REPO_DIR}/core/cvxif_example/compressed_instr_decoder.sv
${CVA6_REPO_DIR}/core/cvxif_example/copro_alu.sv
// Common Cells // Common Cells

View file

@ -13,6 +13,7 @@
// Description: CVA6 Top-level module // Description: CVA6 Top-level module
`include "rvfi_types.svh" `include "rvfi_types.svh"
`include "cvxif_types.svh"
module cva6 module cva6
import ariane_pkg::*; import ariane_pkg::*;
@ -272,8 +273,22 @@ module cva6
// //
parameter type acc_cfg_t = logic, parameter type acc_cfg_t = logic,
parameter acc_cfg_t AccCfg = '0, parameter acc_cfg_t AccCfg = '0,
parameter type cvxif_req_t = cvxif_pkg::cvxif_req_t, // CVXIF Types
parameter type cvxif_resp_t = cvxif_pkg::cvxif_resp_t parameter type readregflags_t = `READREGFLAGS_T(CVA6Cfg),
parameter type writeregflags_t = `WRITEREGFLAGS_T(CVA6Cfg),
parameter type id_t = `ID_T(CVA6Cfg),
parameter type hartid_t = `HARTID_T(CVA6Cfg),
parameter type x_compressed_req_t = `X_COMPRESSED_REQ_T(CVA6Cfg, hartid_t),
parameter type x_compressed_resp_t = `X_COMPRESSED_RESP_T(CVA6Cfg),
parameter type x_issue_req_t = `X_ISSUE_REQ_T(CVA6Cfg, hartit_t, id_t),
parameter type x_issue_resp_t = `X_ISSUE_RESP_T(CVA6Cfg, writeregflags_t, readregflags_t),
parameter type x_register_t = `X_REGISTER_T(CVA6Cfg, hartid_t, id_t, readregflags_t),
parameter type x_commit_t = `X_COMMIT_T(CVA6Cfg, hartid_t, id_t),
parameter type x_result_t = `X_RESULT_T(CVA6Cfg, hartid_t, id_t, writeregflags_t),
parameter type cvxif_req_t =
`CVXIF_REQ_T(CVA6Cfg, x_compressed_req_t, x_issue_req_t, x_register_req_t, x_commit_t),
parameter type cvxif_resp_t =
`CVXIF_RESP_T(CVA6Cfg, x_compressed_resp_t, x_issue_resp_t, x_result_t)
) ( ) (
// Subsystem Clock - SUBSYSTEM // Subsystem Clock - SUBSYSTEM
input logic clk_i, input logic clk_i,
@ -343,8 +358,27 @@ module cva6
logic [CVA6Cfg.NrCommitPorts-1:0] commit_macro_ack; logic [CVA6Cfg.NrCommitPorts-1:0] commit_macro_ack;
localparam NumPorts = 4; localparam NumPorts = 4;
cvxif_pkg::cvxif_req_t cvxif_req;
cvxif_pkg::cvxif_resp_t cvxif_resp; // CVXIF
cvxif_req_t cvxif_req;
// CVXIF OUTPUTS
logic x_compressed_valid;
x_compressed_req_t x_compressed_req;
logic x_issue_valid;
x_issue_req_t x_issue_req;
logic x_register_valid;
x_register_t x_register;
logic x_commit_valid;
x_commit_t x_commit;
logic x_result_ready;
// CVXIF INPUTS
logic x_compressed_ready;
x_compressed_resp_t x_compressed_resp;
logic x_issue_ready;
x_issue_resp_t x_issue_resp;
logic x_register_ready;
logic x_result_valid;
x_result_t x_result;
// -------------- // --------------
// PCGEN <-> CSR // PCGEN <-> CSR
@ -437,9 +471,11 @@ module cva6
logic x_valid_ex_id; logic x_valid_ex_id;
exception_t x_exception_ex_id; exception_t x_exception_ex_id;
logic x_we_ex_id; logic x_we_ex_id;
logic [4:0] x_rd_ex_id;
logic [CVA6Cfg.NrIssuePorts-1:0] x_issue_valid_id_ex; logic [CVA6Cfg.NrIssuePorts-1:0] x_issue_valid_id_ex;
logic x_issue_ready_ex_id; logic x_issue_ready_ex_id;
logic [31:0] x_off_instr_id_ex; logic [31:0] x_off_instr_id_ex;
logic x_transaction_rejected;
// -------------- // --------------
// EX <-> COMMIT // EX <-> COMMIT
// -------------- // --------------
@ -633,7 +669,9 @@ module cva6
.irq_ctrl_t(irq_ctrl_t), .irq_ctrl_t(irq_ctrl_t),
.scoreboard_entry_t(scoreboard_entry_t), .scoreboard_entry_t(scoreboard_entry_t),
.interrupts_t(interrupts_t), .interrupts_t(interrupts_t),
.INTERRUPTS(INTERRUPTS) .INTERRUPTS(INTERRUPTS),
.x_compressed_req_t(x_compressed_req_t),
.x_compressed_resp_t(x_compressed_resp_t)
) id_stage_i ( ) id_stage_i (
.clk_i, .clk_i,
.rst_ni, .rst_ni,
@ -652,20 +690,25 @@ module cva6
.rvfi_is_compressed_o(rvfi_is_compressed), .rvfi_is_compressed_o(rvfi_is_compressed),
.priv_lvl_i (priv_lvl), .priv_lvl_i (priv_lvl),
.v_i (v), .v_i (v),
.fs_i (fs), .fs_i (fs),
.vfs_i (vfs), .vfs_i (vfs),
.frm_i (frm_csr_id_issue_ex), .frm_i (frm_csr_id_issue_ex),
.vs_i (vs), .vs_i (vs),
.irq_i (irq_i), .irq_i (irq_i),
.irq_ctrl_i (irq_ctrl_csr_id), .irq_ctrl_i (irq_ctrl_csr_id),
.debug_mode_i(debug_mode), .debug_mode_i (debug_mode),
.tvm_i (tvm_csr_id), .tvm_i (tvm_csr_id),
.tw_i (tw_csr_id), .tw_i (tw_csr_id),
.vtw_i (vtw_csr_id), .vtw_i (vtw_csr_id),
.tsr_i (tsr_csr_id), .tsr_i (tsr_csr_id),
.hu_i (hu) .hu_i (hu),
.hart_id_i (hart_id_i),
.compressed_ready_i(x_compressed_ready),
.compressed_resp_i (x_compressed_resp),
.compressed_valid_o(x_compressed_valid),
.compressed_req_o (x_compressed_req)
); );
logic [CVA6Cfg.NrWbPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_ex_id; logic [CVA6Cfg.NrWbPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_ex_id;
@ -693,16 +736,39 @@ module cva6
assign ex_ex_ex_id[FPU_WB] = fpu_exception_ex_id; assign ex_ex_ex_id[FPU_WB] = fpu_exception_ex_id;
assign wt_valid_ex_id[FPU_WB] = fpu_valid_ex_id; assign wt_valid_ex_id[FPU_WB] = fpu_valid_ex_id;
always_comb begin : gen_cvxif_input_assignement
x_compressed_ready = cvxif_resp_i.compressed_ready;
x_compressed_resp = cvxif_resp_i.compressed_resp;
x_issue_ready = cvxif_resp_i.issue_ready;
x_issue_resp = cvxif_resp_i.issue_resp;
x_register_ready = cvxif_resp_i.register_ready;
x_result_valid = cvxif_resp_i.result_valid;
x_result = cvxif_resp_i.result;
end
if (CVA6Cfg.CvxifEn) begin if (CVA6Cfg.CvxifEn) begin
always_comb begin : gen_cvxif_output_assignement
cvxif_req.compressed_valid = x_compressed_valid;
cvxif_req.compressed_req = x_compressed_req;
cvxif_req.issue_valid = x_issue_valid;
cvxif_req.issue_req = x_issue_req;
cvxif_req.register_valid = x_register_valid;
cvxif_req.register = x_register;
cvxif_req.commit_valid = x_commit_valid;
cvxif_req.commit = x_commit;
cvxif_req.result_ready = x_result_ready;
end
assign trans_id_ex_id[X_WB] = x_trans_id_ex_id; assign trans_id_ex_id[X_WB] = x_trans_id_ex_id;
assign wbdata_ex_id[X_WB] = x_result_ex_id; assign wbdata_ex_id[X_WB] = x_result_ex_id;
assign ex_ex_ex_id[X_WB] = x_exception_ex_id; assign ex_ex_ex_id[X_WB] = x_exception_ex_id;
assign wt_valid_ex_id[X_WB] = x_valid_ex_id; assign wt_valid_ex_id[X_WB] = x_valid_ex_id;
end else if (CVA6Cfg.EnableAccelerator) begin end else if (CVA6Cfg.EnableAccelerator) begin
assign cvxif_req = '0;
assign trans_id_ex_id[ACC_WB] = acc_trans_id_ex_id; assign trans_id_ex_id[ACC_WB] = acc_trans_id_ex_id;
assign wbdata_ex_id[ACC_WB] = acc_result_ex_id; assign wbdata_ex_id[ACC_WB] = acc_result_ex_id;
assign ex_ex_ex_id[ACC_WB] = acc_exception_ex_id; assign ex_ex_ex_id[ACC_WB] = acc_exception_ex_id;
assign wt_valid_ex_id[ACC_WB] = acc_valid_ex_id; assign wt_valid_ex_id[ACC_WB] = acc_valid_ex_id;
end else begin
assign cvxif_req = '0;
end end
if (CVA6Cfg.CvxifEn && CVA6Cfg.EnableAccelerator) begin : gen_err_xif_and_acc if (CVA6Cfg.CvxifEn && CVA6Cfg.EnableAccelerator) begin : gen_err_xif_and_acc
@ -718,63 +784,79 @@ module cva6
.branchpredict_sbe_t(branchpredict_sbe_t), .branchpredict_sbe_t(branchpredict_sbe_t),
.exception_t(exception_t), .exception_t(exception_t),
.fu_data_t(fu_data_t), .fu_data_t(fu_data_t),
.scoreboard_entry_t(scoreboard_entry_t) .scoreboard_entry_t(scoreboard_entry_t),
.x_issue_req_t(x_issue_req_t),
.x_issue_resp_t(x_issue_resp_t),
.x_register_t(x_register_t),
.x_commit_t(x_commit_t)
) issue_stage_i ( ) issue_stage_i (
.clk_i, .clk_i,
.rst_ni, .rst_ni,
.sb_full_o (sb_full), .sb_full_o (sb_full),
.flush_unissued_instr_i(flush_unissued_instr_ctrl_id), .flush_unissued_instr_i (flush_unissued_instr_ctrl_id),
.flush_i (flush_ctrl_id), .flush_i (flush_ctrl_id),
.stall_i (stall_acc_id), .stall_i (stall_acc_id),
// ID Stage // ID Stage
.decoded_instr_i (issue_entry_id_issue), .decoded_instr_i (issue_entry_id_issue),
.orig_instr_i (orig_instr_id_issue), .orig_instr_i (orig_instr_id_issue),
.decoded_instr_valid_i (issue_entry_valid_id_issue), .decoded_instr_valid_i (issue_entry_valid_id_issue),
.is_ctrl_flow_i (is_ctrl_fow_id_issue), .is_ctrl_flow_i (is_ctrl_fow_id_issue),
.decoded_instr_ack_o (issue_instr_issue_id), .decoded_instr_ack_o (issue_instr_issue_id),
// Functional Units // Functional Units
.rs1_forwarding_o (rs1_forwarding_id_ex), .rs1_forwarding_o (rs1_forwarding_id_ex),
.rs2_forwarding_o (rs2_forwarding_id_ex), .rs2_forwarding_o (rs2_forwarding_id_ex),
.fu_data_o (fu_data_id_ex), .fu_data_o (fu_data_id_ex),
.pc_o (pc_id_ex), .pc_o (pc_id_ex),
.is_compressed_instr_o (is_compressed_instr_id_ex), .is_compressed_instr_o (is_compressed_instr_id_ex),
.tinst_o (tinst_ex), .tinst_o (tinst_ex),
// fixed latency unit ready // fixed latency unit ready
.flu_ready_i (flu_ready_ex_id), .flu_ready_i (flu_ready_ex_id),
// ALU // ALU
.alu_valid_o (alu_valid_id_ex), .alu_valid_o (alu_valid_id_ex),
// Branches and Jumps // Branches and Jumps
.branch_valid_o (branch_valid_id_ex), // branch is valid .branch_valid_o (branch_valid_id_ex), // branch is valid
.branch_predict_o (branch_predict_id_ex), // branch predict to ex .branch_predict_o (branch_predict_id_ex), // branch predict to ex
.resolve_branch_i (resolve_branch_ex_id), // in order to resolve the branch .resolve_branch_i (resolve_branch_ex_id), // in order to resolve the branch
// LSU // LSU
.lsu_ready_i (lsu_ready_ex_id), .lsu_ready_i (lsu_ready_ex_id),
.lsu_valid_o (lsu_valid_id_ex), .lsu_valid_o (lsu_valid_id_ex),
// Multiplier // Multiplier
.mult_valid_o (mult_valid_id_ex), .mult_valid_o (mult_valid_id_ex),
// FPU // FPU
.fpu_ready_i (fpu_ready_ex_id), .fpu_ready_i (fpu_ready_ex_id),
.fpu_valid_o (fpu_valid_id_ex), .fpu_valid_o (fpu_valid_id_ex),
.fpu_fmt_o (fpu_fmt_id_ex), .fpu_fmt_o (fpu_fmt_id_ex),
.fpu_rm_o (fpu_rm_id_ex), .fpu_rm_o (fpu_rm_id_ex),
// ALU2 // ALU2
.alu2_valid_o (alu2_valid_id_ex), .alu2_valid_o (alu2_valid_id_ex),
// CSR // CSR
.csr_valid_o (csr_valid_id_ex), .csr_valid_o (csr_valid_id_ex),
// CVXIF // CVXIF
.x_issue_valid_o (x_issue_valid_id_ex), .xfu_valid_o (x_issue_valid_id_ex),
.x_issue_ready_i (x_issue_ready_ex_id), .xfu_ready_i (x_issue_ready_ex_id),
.x_off_instr_o (x_off_instr_id_ex), .x_off_instr_o (x_off_instr_id_ex),
.hart_id_i (hart_id_i),
.x_issue_ready_i (x_issue_ready),
.x_issue_resp_i (x_issue_resp),
.x_issue_valid_o (x_issue_valid),
.x_issue_req_o (x_issue_req),
.x_register_ready_i (x_register_ready),
.x_register_valid_o (x_register_valid),
.x_register_o (x_register),
.x_commit_valid_o (x_commit_valid),
.x_commit_o (x_commit),
.x_transaction_rejected_o(x_transaction_rejected),
// Accelerator // Accelerator
.issue_instr_o (issue_instr_id_acc), .issue_instr_o (issue_instr_id_acc),
.issue_instr_hs_o (issue_instr_hs_id_acc), .issue_instr_hs_o (issue_instr_hs_id_acc),
// Commit // Commit
.resolved_branch_i (resolved_branch), .resolved_branch_i (resolved_branch),
.trans_id_i (trans_id_ex_id), .trans_id_i (trans_id_ex_id),
.wbdata_i (wbdata_ex_id), .wbdata_i (wbdata_ex_id),
.ex_ex_i (ex_ex_ex_id), .ex_ex_i (ex_ex_ex_id),
.wt_valid_i (wt_valid_ex_id), .wt_valid_i (wt_valid_ex_id),
.x_we_i (x_we_ex_id), .x_we_i (x_we_ex_id),
.x_rd_i (x_rd_ex_id),
.waddr_i (waddr_commit_id), .waddr_i (waddr_commit_id),
.wdata_i (wdata_commit_id), .wdata_i (wdata_commit_id),
@ -806,7 +888,8 @@ module cva6
.icache_arsp_t(icache_arsp_t), .icache_arsp_t(icache_arsp_t),
.icache_dreq_t(icache_dreq_t), .icache_dreq_t(icache_dreq_t),
.icache_drsp_t(icache_drsp_t), .icache_drsp_t(icache_drsp_t),
.lsu_ctrl_t(lsu_ctrl_t) .lsu_ctrl_t(lsu_ctrl_t),
.x_result_t(x_result_t)
) ex_stage_i ( ) ex_stage_i (
.clk_i(clk_i), .clk_i(clk_i),
.rst_ni(rst_ni), .rst_ni(rst_ni),
@ -877,13 +960,16 @@ module cva6
.x_valid_i (x_issue_valid_id_ex), .x_valid_i (x_issue_valid_id_ex),
.x_ready_o (x_issue_ready_ex_id), .x_ready_o (x_issue_ready_ex_id),
.x_off_instr_i (x_off_instr_id_ex), .x_off_instr_i (x_off_instr_id_ex),
.x_transaction_rejected_i(x_transaction_rejected),
.x_trans_id_o (x_trans_id_ex_id), .x_trans_id_o (x_trans_id_ex_id),
.x_exception_o (x_exception_ex_id), .x_exception_o (x_exception_ex_id),
.x_result_o (x_result_ex_id), .x_result_o (x_result_ex_id),
.x_valid_o (x_valid_ex_id), .x_valid_o (x_valid_ex_id),
.x_we_o (x_we_ex_id), .x_we_o (x_we_ex_id),
.cvxif_req_o (cvxif_req), .x_rd_o (x_rd_ex_id),
.cvxif_resp_i (cvxif_resp), .x_result_valid_i (x_result_valid),
.x_result_i (x_result),
.x_result_ready_o (x_result_ready),
// Accelerator // Accelerator
.acc_valid_i (acc_valid_acc_ex), .acc_valid_i (acc_valid_acc_ex),
// Performance counters // Performance counters
@ -1432,7 +1518,6 @@ module cva6
// Feed through cvxif // Feed through cvxif
assign cvxif_req_o = cvxif_req; assign cvxif_req_o = cvxif_req;
assign cvxif_resp = cvxif_resp_i;
end : gen_no_accelerator end : gen_no_accelerator
// ------------------- // -------------------

View file

@ -0,0 +1,74 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module cvxif_compressed_if_driver #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type x_compressed_req_t = logic,
parameter type x_compressed_resp_t = logic
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
// CVA6 Hart id
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_i,
input logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_i,
output logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_o,
output logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_o,
output logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_o,
input logic stall_i,
output logic stall_o,
// CVXIF Compressed interface
input logic compressed_ready_i,
input x_compressed_resp_t compressed_resp_i,
output logic compressed_valid_o,
output x_compressed_req_t compressed_req_o
);
always_comb begin
is_illegal_o = is_illegal_i;
instruction_o = instruction_i;
is_compressed_o = is_compressed_i;
compressed_valid_o = 1'b0;
compressed_req_o.instr = '0;
compressed_req_o.hartid = hart_id_i;
stall_o = stall_i;
if (is_illegal_i[0]) begin
compressed_valid_o = is_illegal_i[0];
compressed_req_o.instr = instruction_i[0][15:0];
is_illegal_o[0] = ~compressed_resp_i.accept;
instruction_o[0] = compressed_resp_i.accept ? compressed_resp_i.instr : instruction_i[0];
is_compressed_o[0] = compressed_resp_i.accept ? 1'b0 : is_compressed_i[0];
if (~stall_i) begin
// Propagate stall from macro decoder or wait for compressed ready if compressed transaction is happening.
// Stall if both instruction are illegal
if (CVA6Cfg.SuperscalarEn) begin
stall_o = is_illegal_i[1];
end else begin
stall_o = (compressed_valid_o && ~compressed_ready_i);
end
end
end
if (CVA6Cfg.SuperscalarEn) begin
if (~is_illegal_i[0] && is_illegal_i[1]) begin // 2nd instruction is illegal
compressed_valid_o = is_illegal_i[1];
compressed_req_o.instr = instruction_i[1][15:0];
is_illegal_o[1] = ~compressed_resp_i.accept;
instruction_o[1] = compressed_resp_i.accept ? compressed_resp_i.instr : instruction_i[1];
is_compressed_o[1] = compressed_resp_i.accept ? 1'b0 : is_compressed_i[1];
end
end
end
endmodule

View file

@ -0,0 +1,50 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module compressed_instr_decoder
import cvxif_instr_pkg::*;
#(
parameter int NbInstr = 1,
parameter copro_compressed_resp_t CoproInstr [NbInstr] = {0},
parameter type x_compressed_req_t = logic,
parameter type x_compressed_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic compressed_valid_i,
input x_compressed_req_t compressed_req_i,
output logic compressed_ready_o,
output x_compressed_resp_t compressed_resp_o
);
logic [NbInstr-1:0] sel;
for (genvar i = 0; i < NbInstr; i++) begin : gen_predecoder_selector
assign sel[i] = ((CoproInstr[i].mask & compressed_req_i.instr) == CoproInstr[i].instr);
end
always_comb begin
compressed_ready_o = '1;
compressed_resp_o.accept = '0;
compressed_resp_o.instr = '0;
for (int unsigned i = 0; i < NbInstr; i++) begin
if (sel[i] && compressed_valid_i) begin
compressed_resp_o.accept = CoproInstr[i].resp.accept;
compressed_resp_o.instr = CoproInstr[i].resp.instr;
// Remap rs1 and rs2
compressed_resp_o.instr[19:15] = compressed_req_i.instr[11:7];
compressed_resp_o.instr[24:20] = compressed_req_i.instr[6:2];
end
end
end
assert property (@(posedge clk_i) $onehot0(sel))
else $warning("This offloaded instruction is valid for multiple coprocessor instructions !");
endmodule

View file

@ -0,0 +1,135 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module copro_alu
import cvxif_instr_pkg::*;
#(
parameter int unsigned NrRgprPorts = 2,
parameter type hartid_t = logic,
parameter type id_t = logic,
parameter type registers_t = logic
) (
input logic clk_i,
input logic rst_ni,
input registers_t registers_i,
input opcode_t opcode_i,
input hartid_t hartid_i,
input id_t id_i,
input logic [ 4:0] rd_i,
output logic [31:0] result_o, // TODO parametrize to 64 bits
output hartid_t hartid_o,
output id_t id_o,
output logic [ 4:0] rd_o,
output logic valid_o,
output logic we_o
);
logic [31:0] result_n, result_q;
hartid_t hartid_n, hartid_q;
id_t id_n, id_q;
logic valid_n, valid_q;
logic [4:0] rd_n, rd_q;
logic we_n, we_q;
assign result_o = result_q;
assign hartid_o = hartid_q;
assign id_o = id_q;
assign valid_o = valid_q;
assign rd_o = rd_q;
assign we_o = we_q;
always_comb begin
case (opcode_i)
cvxif_instr_pkg::NOP: begin
result_n = '0;
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = '0;
we_n = '0;
end
cvxif_instr_pkg::ADD: begin
result_n = registers_i[1] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::DOUBLE_RS1: begin
result_n = registers_i[0] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::DOUBLE_RS2: begin
result_n = registers_i[1] + registers_i[1];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::ADD_MULTI: begin
result_n = registers_i[1] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::ADD_RS3_R4: begin
result_n = NrRgprPorts == 3 ? registers_i[2] + registers_i[1] + registers_i[0] : registers_i[1] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = rd_i;
we_n = 1'b1;
end
cvxif_instr_pkg::ADD_RS3_R: begin
result_n = NrRgprPorts == 3 ? registers_i[2] + registers_i[1] + registers_i[0] : registers_i[1] + registers_i[0];
hartid_n = hartid_i;
id_n = id_i;
valid_n = 1'b1;
rd_n = 5'b01010;
we_n = 1'b1;
end
default: begin
result_n = '0;
hartid_n = '0;
id_n = '0;
valid_n = '0;
rd_n = '0;
we_n = '0;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (~rst_ni) begin
result_q <= '0;
hartid_q <= '0;
id_q <= '0;
valid_q <= '0;
rd_q <= '0;
we_q <= '0;
end else begin
result_q <= result_n;
hartid_q <= hartid_n;
id_q <= id_n;
valid_q <= valid_n;
rd_q <= rd_n;
we_q <= we_n;
end
end
endmodule

View file

@ -1,19 +1,31 @@
// Copyright 2021 Thales DIS design services SAS // Copyright 2024 Thales DIS France SAS
// //
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); // Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/ // You may obtain a copy of the License at https://solderpad.org/licenses/
// //
// Original Author: Guillaume Chauvon (guillaume.chauvon@thalesgroup.com) // Original Author: Guillaume Chauvon
// Example coprocessor adds rs1,rs2(,rs3) together and gives back the result to the CPU via the CoreV-X-Interface.
// Coprocessor delays the sending of the result depending on result least significant bits.
module cvxif_example_coprocessor module cvxif_example_coprocessor
import cvxif_pkg::*;
import cvxif_instr_pkg::*; import cvxif_instr_pkg::*;
#( #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty // CVXIF Types
parameter int unsigned NrRgprPorts = 2,
parameter type readregflags_t = logic,
parameter type writeregflags_t = logic,
parameter type id_t = logic,
parameter type hartid_t = logic,
parameter type x_compressed_req_t = logic,
parameter type x_compressed_resp_t = logic,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type x_commit_t = logic,
parameter type x_result_t = logic,
parameter type cvxif_req_t = logic,
parameter type cvxif_resp_t = logic,
localparam type registers_t = logic [NrRgprPorts-1:0][31:0]
) ( ) (
input logic clk_i, // Clock input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low input logic rst_ni, // Asynchronous reset active low
@ -21,138 +33,115 @@ module cvxif_example_coprocessor
output cvxif_resp_t cvxif_resp_o output cvxif_resp_t cvxif_resp_o
); );
//Compressed interface // Compressed interface signals
logic x_compressed_valid_i; x_compressed_req_t compressed_req;
logic x_compressed_ready_o; x_compressed_resp_t compressed_resp;
x_compressed_req_t x_compressed_req_i; logic compressed_valid, compressed_ready;
x_compressed_resp_t x_compressed_resp_o; // Issue interface signals
//Issue interface x_issue_req_t issue_req;
logic x_issue_valid_i; x_issue_resp_t issue_resp;
logic x_issue_ready_o; logic issue_valid, issue_ready;
x_issue_req_t x_issue_req_i;
x_issue_resp_t x_issue_resp_o;
//Commit interface
logic x_commit_valid_i;
x_commit_t x_commit_i;
//Memory interface
logic x_mem_valid_o;
logic x_mem_ready_i;
x_mem_req_t x_mem_req_o;
x_mem_resp_t x_mem_resp_i;
//Memory result interface
logic x_mem_result_valid_i;
x_mem_result_t x_mem_result_i;
//Result interface
logic x_result_valid_o;
logic x_result_ready_i;
x_result_t x_result_o;
assign x_compressed_valid_i = cvxif_req_i.x_compressed_valid; // Register interface signals
assign x_compressed_req_i = cvxif_req_i.x_compressed_req; x_register_t register;
assign x_issue_valid_i = cvxif_req_i.x_issue_valid; logic register_valid;
assign x_issue_req_i = cvxif_req_i.x_issue_req;
assign x_commit_valid_i = cvxif_req_i.x_commit_valid;
assign x_commit_i = cvxif_req_i.x_commit;
assign x_mem_ready_i = cvxif_req_i.x_mem_ready;
assign x_mem_resp_i = cvxif_req_i.x_mem_resp;
assign x_mem_result_valid_i = cvxif_req_i.x_mem_result_valid;
assign x_mem_result_i = cvxif_req_i.x_mem_result;
assign x_result_ready_i = cvxif_req_i.x_result_ready;
assign cvxif_resp_o.x_compressed_ready = x_compressed_ready_o; // Decoder and alu signals
assign cvxif_resp_o.x_compressed_resp = x_compressed_resp_o; registers_t registers;
assign cvxif_resp_o.x_issue_ready = x_issue_ready_o; opcode_t opcode;
assign cvxif_resp_o.x_issue_resp = x_issue_resp_o; hartid_t issue_hartid, hartid;
assign cvxif_resp_o.x_mem_valid = x_mem_valid_o; id_t issue_id, id;
assign cvxif_resp_o.x_mem_req = x_mem_req_o; logic [4:0] issue_rd, rd;
assign cvxif_resp_o.x_result_valid = x_result_valid_o; logic [31:0] result;
assign cvxif_resp_o.x_result = x_result_o; logic we;
//Compressed interface // Issue and Register interface
assign x_compressed_ready_o = '0; // Mandatory when X_ISSUE_REGISTER_SPLIT = 0
assign x_compressed_resp_o.instr = '0; assign cvxif_resp_o.compressed_ready = compressed_ready;
assign x_compressed_resp_o.accept = '0; assign cvxif_resp_o.compressed_resp = compressed_resp;
assign cvxif_resp_o.issue_ready = issue_ready;
assign cvxif_resp_o.issue_resp = issue_resp;
assign cvxif_resp_o.register_ready = cvxif_resp_o.issue_ready;
assign compressed_req = cvxif_req_i.compressed_req;
assign compressed_valid = cvxif_req_i.compressed_valid;
assign issue_req = cvxif_req_i.issue_req;
assign issue_valid = cvxif_req_i.issue_valid;
assign register = cvxif_req_i.register;
assign register_valid = cvxif_req_i.register_valid;
compressed_instr_decoder #(
.NbInstr(cvxif_instr_pkg::NbCompInstr),
.CoproInstr(cvxif_instr_pkg::CoproCompInstr),
.x_compressed_req_t(x_compressed_req_t),
.x_compressed_resp_t(x_compressed_resp_t)
) compressed_instr_decoder_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.compressed_valid_i(compressed_valid),
.compressed_req_i (compressed_req),
.compressed_ready_o(compressed_ready),
.compressed_resp_o (compressed_resp)
);
instr_decoder #( instr_decoder #(
.NbInstr (cvxif_instr_pkg::NbInstr), .NbInstr (cvxif_instr_pkg::NbInstr),
.CoproInstr(cvxif_instr_pkg::CoproInstr) .CoproInstr(cvxif_instr_pkg::CoproInstr),
.NrRgprPorts(NrRgprPorts),
.hartid_t (hartid_t),
.id_t (id_t),
.x_issue_req_t (x_issue_req_t),
.x_issue_resp_t (x_issue_resp_t),
.x_register_t (x_register_t),
.registers_t (registers_t)
) instr_decoder_i ( ) instr_decoder_i (
.clk_i (clk_i), .clk_i (clk_i),
.x_issue_req_i (x_issue_req_i), .rst_ni (rst_ni),
.x_issue_resp_o(x_issue_resp_o) .issue_valid_i (issue_valid),
.issue_req_i (issue_req),
.issue_ready_o (issue_ready),
.issue_resp_o (issue_resp),
.register_valid_i(register_valid),
.register_i (register),
.registers_o (registers),
.opcode_o (opcode),
.hartid_o (issue_hartid),
.id_o (issue_id),
.rd_o (issue_rd)
); );
typedef struct packed { logic alu_valid;
x_issue_req_t req; // Result interface
x_issue_resp_t resp; copro_alu #(
} x_issue_t; .NrRgprPorts(NrRgprPorts),
.hartid_t(hartid_t),
logic fifo_full, fifo_empty; .id_t(id_t),
logic x_issue_ready_q; .registers_t(registers_t)
logic instr_push, instr_pop; ) i_copro_alu (
x_issue_t req_i; .clk_i (clk_i),
x_issue_t req_o; .rst_ni (rst_ni),
.registers_i(registers),
.opcode_i (opcode),
.hartid_i (issue_hartid),
assign instr_push = x_issue_resp_o.accept ? 1 : 0; .id_i (issue_id),
assign instr_pop = (x_commit_i.x_commit_kill && x_commit_valid_i) || x_result_valid_o; .rd_i (issue_rd),
assign x_issue_ready_q = ~fifo_full; // if something is in the fifo, the instruction is being processed .hartid_o (hartid),
// so we can't receive anything else .id_o (id),
assign req_i.req = x_issue_req_i; .result_o (result),
assign req_i.resp = x_issue_resp_o; .valid_o (alu_valid),
.rd_o (rd),
always_ff @(posedge clk_i or negedge rst_ni) begin : regs .we_o (we)
if (!rst_ni) begin
x_issue_ready_o <= 1;
end else begin
x_issue_ready_o <= x_issue_ready_q;
end
end
cva6_fifo_v3 #(
.FALL_THROUGH(1), //data_o ready and pop in the same cycle
.DATA_WIDTH (64),
.DEPTH (8),
.dtype (x_issue_t),
.FPGA_EN (CVA6Cfg.FpgaEn)
) fifo_commit_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i (1'b0),
.testmode_i(1'b0),
.full_o (fifo_full),
.empty_o (fifo_empty),
.usage_o (),
.data_i (req_i),
.push_i (instr_push),
.data_o (req_o),
.pop_i (instr_pop)
);
logic [3:0] c;
counter #(
.WIDTH(4)
) counter_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clear_i (~x_commit_i.x_commit_kill && x_commit_valid_i),
.en_i (1'b1),
.load_i (),
.down_i (),
.d_i (),
.q_o (c),
.overflow_o()
); );
always_comb begin always_comb begin
x_result_o.data = req_o.req.rs[0] + req_o.req.rs[1] + (X_NUM_RS == 3 ? req_o.req.rs[2] : 0); cvxif_resp_o.result_valid = alu_valid; //TODO Should wait for ready from CPU
x_result_valid_o = (c == x_result_o.data[3:0]) && ~fifo_empty ? 1 : 0; cvxif_resp_o.result.hartid = hartid;
x_result_o.id = req_o.req.id; cvxif_resp_o.result.id = id;
x_result_o.rd = req_o.req.instr[11:7]; cvxif_resp_o.result.data = result;
x_result_o.we = req_o.resp.writeback & x_result_valid_o; cvxif_resp_o.result.rd = rd;
x_result_o.exc = 0; cvxif_resp_o.result.we = we;
x_result_o.exccode = 0;
end end
endmodule endmodule

View file

@ -7,40 +7,144 @@
// //
// Original Author: Guillaume Chauvon (guillaume.chauvon@thalesgroup.com) // Original Author: Guillaume Chauvon (guillaume.chauvon@thalesgroup.com)
package cvxif_instr_pkg; package cvxif_instr_pkg;
typedef enum logic [3:0] {
ILLEGAL = 4'b0000,
NOP = 4'b0001,
ADD = 4'b0010,
DOUBLE_RS1 = 4'b0011,
DOUBLE_RS2 = 4'b0100,
ADD_MULTI = 4'b0101,
ADD_RS3_R4 = 4'b0110,
ADD_RS3_R = 4'b0111
} opcode_t;
typedef struct packed { typedef struct packed {
logic [31:0] instr; logic accept;
logic [31:0] mask; logic writeback; // TODO depends on dualwrite
cvxif_pkg::x_issue_resp_t resp; logic [2:0] register_read; // TODO Nr read ports
} issue_resp_t;
typedef struct packed {
logic accept;
logic [31:0] instr;
} compressed_resp_t;
typedef struct packed {
logic [31:0] instr;
logic [31:0] mask;
issue_resp_t resp;
opcode_t opcode;
} copro_issue_resp_t; } copro_issue_resp_t;
// 2 Possible RISCV instructions for Coprocessor
parameter int unsigned NbInstr = 2; typedef struct packed {
logic [15:0] instr;
logic [15:0] mask;
compressed_resp_t resp;
} copro_compressed_resp_t;
// 4 Possible RISCV instructions for Coprocessor
parameter int unsigned NbInstr = 10;
parameter copro_issue_resp_t CoproInstr[NbInstr] = '{ parameter copro_issue_resp_t CoproInstr[NbInstr] = '{
'{ '{
instr: 32'b00000_00_00000_00000_0_00_00000_0101011, // custom1 opcode // Custom Nop
mask: 32'b00000_00_00000_00000_0_00_00000_1111111, instr:
resp : '{ 32'b00000_00_00000_00000_0_00_00000_1111011, // custom3 opcode
accept : 1'b1, mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
writeback : 1'b0, resp : '{accept : 1'b1, writeback : 1'b0, register_read : {1'b0, 1'b0, 1'b0}},
dualwrite : 1'b0, opcode : NOP
dualread : 1'b0,
loadstore : 1'b0,
exc : 1'b0
}
}, },
'{ '{
instr: 32'b00000_00_00000_00000_0_00_00000_1011011, // custom2 opcode // Custom Add : cus_add rd, rs1, rs2
mask: 32'b00000_00_00000_00000_0_00_00000_1111111, instr:
resp : '{ 32'b00000_00_00000_00000_0_01_00000_1111011, // custom3 opcode
accept : 1'b1, mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
writeback : 1'b1, resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b1, 1'b1}},
dualwrite : 1'b0, opcode : ADD
dualread : 1'b0, },
loadstore : 1'b0, '{
exc : 1'b0 // Custom Add rs1 : cus_add rd, rs1, rs1
} instr:
32'b00000_01_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b0, 1'b1}},
opcode : DOUBLE_RS1
},
'{
// Custom Add rs2 : cus_add rd, rs2, rs2
instr:
32'b00000_10_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b1, 1'b0}},
opcode : DOUBLE_RS2
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_11_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b0, 1'b1, 1'b1}},
opcode : ADD_MULTI
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00001_00_00000_00000_0_01_00000_1111011, // custom3 opcode
mask: 32'b11111_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : ADD_RS3_R
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1000011, // MADD opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : ADD_RS3_R4
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1000111, // MSUB opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : ADD_RS3_R4
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1001011, // NMSUB opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : ADD_RS3_R4
},
'{
// Custom Add Multi rs1 : cus_add rd, rs1, rs1
instr:
32'b00000_00_00000_00000_0_00_00000_1001111, // NMADD opcode
mask: 32'b00000_11_00000_00000_1_11_00000_1111111,
resp : '{accept : 1'b1, writeback : 1'b1, register_read : {1'b1, 1'b1, 1'b1}},
opcode : ADD_RS3_R4
}
};
parameter int unsigned NbCompInstr = 2;
parameter copro_compressed_resp_t CoproCompInstr[NbCompInstr] = '{
// C_NOP
'{
instr : 16'b111_0_00000_00000_00,
mask : 16'b111_1_00000_00000_11,
resp : '{accept : 1'b1, instr : 32'b00000_00_00000_00000_0_00_00000_1111011}
},
'{
instr : 16'b111_1_00000_00000_00,
mask : 16'b111_1_00000_00000_11,
resp : '{accept : 1'b1, instr : 32'b00000_00_00000_00000_0_01_01010_1111011}
} }
}; };

View file

@ -1,46 +1,86 @@
// Copyright 2021 Thales DIS design services SAS // Copyright 2024 Thales DIS France SAS
// //
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); // Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/ // You may obtain a copy of the License at https://solderpad.org/licenses/
// //
// Original Author: Guillaume Chauvon (guillaume.chauvon@thalesgroup.com) // Original Author: Guillaume Chauvon
module instr_decoder module instr_decoder
import cvxif_pkg::*; import cvxif_instr_pkg::*;
#( #(
parameter int NbInstr = 1, parameter int NbInstr = 1,
parameter cvxif_instr_pkg::copro_issue_resp_t CoproInstr[NbInstr] = {0} parameter copro_issue_resp_t CoproInstr [NbInstr] = {0},
parameter int unsigned NrRgprPorts = 2,
parameter type hartid_t = logic,
parameter type id_t = logic,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type registers_t = logic
) ( ) (
input logic clk_i, input logic clk_i,
input x_issue_req_t x_issue_req_i, input logic rst_ni,
output x_issue_resp_t x_issue_resp_o input logic issue_valid_i,
input x_issue_req_t issue_req_i,
output logic issue_ready_o,
output x_issue_resp_t issue_resp_o,
input logic register_valid_i,
input x_register_t register_i,
output registers_t registers_o,
output opcode_t opcode_o,
output hartid_t hartid_o,
output id_t id_o,
output logic [4:0] rd_o
); );
logic [NbInstr-1:0] sel; logic [NbInstr-1:0] sel;
logic rs1_ready;
logic rs2_ready;
logic rs3_ready;
for (genvar i = 0; i < NbInstr; i++) begin : gen_predecoder_selector for (genvar i = 0; i < NbInstr; i++) begin : gen_predecoder_selector
assign sel[i] = ((CoproInstr[i].mask & x_issue_req_i.instr) == CoproInstr[i].instr); assign sel[i] = ((CoproInstr[i].mask & issue_req_i.instr) == CoproInstr[i].instr);
end end
always_comb begin always_comb begin
x_issue_resp_o.accept = '0; rs1_ready = '0;
x_issue_resp_o.writeback = '0; rs2_ready = '0;
x_issue_resp_o.dualwrite = '0; rs3_ready = '0;
x_issue_resp_o.dualread = '0; issue_ready_o = '0;
x_issue_resp_o.loadstore = '0; issue_resp_o.accept = '0;
x_issue_resp_o.exc = '0; issue_resp_o.writeback = '0;
issue_resp_o.register_read = '0;
registers_o = '0;
opcode_o = ILLEGAL;
hartid_o = '0;
id_o = '0;
rd_o = '0;
for (int unsigned i = 0; i < NbInstr; i++) begin for (int unsigned i = 0; i < NbInstr; i++) begin
if (sel[i]) begin if (sel[i] && issue_valid_i) begin
x_issue_resp_o.accept = CoproInstr[i].resp.accept; issue_resp_o.accept = CoproInstr[i].resp.accept;
x_issue_resp_o.writeback = CoproInstr[i].resp.writeback; issue_resp_o.writeback = CoproInstr[i].resp.writeback;
x_issue_resp_o.dualwrite = CoproInstr[i].resp.dualwrite; issue_resp_o.register_read = CoproInstr[i].resp.register_read; // Warning : potential 3 bits vector into 2 bits one
x_issue_resp_o.dualread = CoproInstr[i].resp.dualread; if (issue_resp_o.accept) begin
x_issue_resp_o.loadstore = CoproInstr[i].resp.loadstore; rs1_ready = (~CoproInstr[i].resp.register_read[0] || register_i.rs_valid[0]);
x_issue_resp_o.exc = CoproInstr[i].resp.exc; rs2_ready = (~CoproInstr[i].resp.register_read[1] || register_i.rs_valid[1]);
rs3_ready = NrRgprPorts == 3 ? (~CoproInstr[i].resp.register_read[2] || register_i.rs_valid[2]) : 1'b1;
issue_ready_o = rs1_ready && rs2_ready && rs3_ready;
end
opcode_o = CoproInstr[i].opcode;
id_o = issue_req_i.id;
hartid_o = issue_req_i.hartid;
rd_o = issue_req_i.instr[11:7];
for (int unsigned j = 0; j < NrRgprPorts; j++) begin
registers_o[j] = issue_resp_o.register_read[j] ? register_i.rs[j] : '0;
end
end end
end end
// Coprocessor could not decode offloaded instruction -> instruction is not accepted
if (issue_valid_i && ~(|sel)) begin
issue_ready_o = 1'b1;
end
end end
assert property (@(posedge clk_i) $onehot0(sel)) assert property (@(posedge clk_i) $onehot0(sel))

View file

@ -1,13 +1,14 @@
// Copyright 2021 Thales DIS design services SAS // Copyright 2024 Thales DIS France SAS
// //
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); // Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/ // You may obtain a copy of the License at https://solderpad.org/licenses/
// //
// Original Author: Guillaume CHAUVON (guillaume.chauvon@thalesgroup.com) // Original Author: Guillaume Chauvon
// Functional Unit for the logic of the CoreV-X-Interface // Functional Unit for the CoreV-X-Interface
// Handles Result interface and exception forwarding to next stages.
module cvxif_fu module cvxif_fu
@ -15,116 +16,60 @@ module cvxif_fu
#( #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type exception_t = logic, parameter type exception_t = logic,
parameter type fu_data_t = logic parameter type x_result_t = logic
) ( ) (
// Subsystem Clock - SUBSYSTEM // Subsystem Clock - SUBSYSTEM
input logic clk_i, input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM // Asynchronous reset active low - SUBSYSTEM
input logic rst_ni, input logic rst_ni,
// FU data needed to execute instruction - ISSUE_STAGE
input fu_data_t fu_data_i,
// Current privilege mode - CSR_REGFILE
input riscv::priv_lvl_t priv_lvl_i,
// CVXIF instruction is valid - ISSUE_STAGE // CVXIF instruction is valid - ISSUE_STAGE
input logic x_valid_i, input logic x_valid_i,
// CVXIF is ready - ISSUE_STAGE // Transaction ID - ISSUE_STAGE
output logic x_ready_o, input logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_i,
// Instruction is illegal, determined during CVXIF issue transaction - ISSUE_STAGE
input logic x_illegal_i,
// Offloaded instruction - ISSUE_STAGE // Offloaded instruction - ISSUE_STAGE
input logic [ 31:0] x_off_instr_i, input logic [ 31:0] x_off_instr_i,
// CVXIF transaction ID - ISSUE_STAGE // CVXIF is ready - ISSUE_STAGE
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o, output logic x_ready_o,
// CVXIF result transaction ID - ISSUE_STAGE
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o,
// CVXIF exception - ISSUE_STAGE // CVXIF exception - ISSUE_STAGE
output exception_t x_exception_o, output exception_t x_exception_o,
// CVXIF FU result - ISSUE_STAGE // CVXIF FU result - ISSUE_STAGE
output logic [ CVA6Cfg.XLEN-1:0] x_result_o, output logic [ CVA6Cfg.XLEN-1:0] x_result_o,
// CVXIF result valid - ISSUE_STAGE // CVXIF result valid - ISSUE_STAGE
output logic x_valid_o, output logic x_valid_o,
// CVXIF write enable - ISSUE_STAGE // CVXIF write enable - ISSUE_STAGE
output logic x_we_o, output logic x_we_o,
// CVXIF request - SUBSYSTEM // CVXIF destination register - ISSUE_STAGE
output cvxif_pkg::cvxif_req_t cvxif_req_o, output logic [ 4:0] x_rd_o,
// CVXIF response - SUBSYSTEM // CVXIF result interface
input cvxif_pkg::cvxif_resp_t cvxif_resp_i input logic result_valid_i,
input x_result_t result_i,
output logic result_ready_o
); );
localparam X_NUM_RS = ariane_pkg::NR_RGPR_PORTS;
logic illegal_n, illegal_q;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] illegal_id_n, illegal_id_q;
logic [31:0] illegal_instr_n, illegal_instr_q;
logic [X_NUM_RS-1:0] rs_valid;
if (cvxif_pkg::X_NUM_RS == 3) begin : gen_third_operand
assign rs_valid = 3'b111;
end else begin : gen_no_third_operand
assign rs_valid = 2'b11;
end
assign result_ready_o = 1'b1;
assign x_ready_o = 1'b1; // Readyness of cvxif_fu is determined in issue stage by CVXIF issue interface
// Result signals
assign x_valid_o = x_illegal_i ? 1'b1 : result_valid_i;
assign x_result_o = result_i.data;
assign x_trans_id_o = x_illegal_i ? x_trans_id_i : result_i.id;
assign x_we_o = result_i.we;
assign x_rd_o = result_i.rd;
// Handling of illegal instruction exception
always_comb begin always_comb begin
cvxif_req_o = '0; x_exception_o = '0; // No exception in this interface
cvxif_req_o.x_result_ready = 1'b1; if (x_illegal_i) begin
x_ready_o = cvxif_resp_i.x_issue_ready; x_exception_o.valid = '1;
if (x_valid_i) begin x_exception_o.cause = riscv::ILLEGAL_INSTR;
cvxif_req_o.x_issue_valid = x_valid_i; if (CVA6Cfg.TvalEn)
cvxif_req_o.x_issue_req.instr = x_off_instr_i; x_exception_o.tval = x_off_instr_i; // TODO Optimization : Set exception in IRO.
cvxif_req_o.x_issue_req.mode = priv_lvl_i;
cvxif_req_o.x_issue_req.id = fu_data_i.trans_id;
cvxif_req_o.x_issue_req.rs[0] = fu_data_i.operand_a;
cvxif_req_o.x_issue_req.rs[1] = fu_data_i.operand_b;
if (cvxif_pkg::X_NUM_RS == 3) begin
cvxif_req_o.x_issue_req.rs[2] = fu_data_i.imm;
end
cvxif_req_o.x_issue_req.rs_valid = rs_valid;
cvxif_req_o.x_commit_valid = x_valid_i;
cvxif_req_o.x_commit.id = fu_data_i.trans_id;
cvxif_req_o.x_commit.x_commit_kill = 1'b0;
end
end
always_comb begin
illegal_n = illegal_q;
illegal_id_n = illegal_id_q;
illegal_instr_n = illegal_instr_q;
if (~cvxif_resp_i.x_issue_resp.accept && cvxif_req_o.x_issue_valid && cvxif_resp_i.x_issue_ready && ~illegal_n) begin
illegal_n = 1'b1;
illegal_id_n = cvxif_req_o.x_issue_req.id;
illegal_instr_n = cvxif_req_o.x_issue_req.instr;
end
x_valid_o = cvxif_resp_i.x_result_valid; //Read result only when CVXIF is enabled
x_trans_id_o = x_valid_o ? cvxif_resp_i.x_result.id : '0;
x_result_o = x_valid_o ? cvxif_resp_i.x_result.data : '0;
x_exception_o.cause = x_valid_o ? {{(CVA6Cfg.XLEN-6){1'b0}}, cvxif_resp_i.x_result.exccode} : '0;
x_exception_o.valid = x_valid_o ? cvxif_resp_i.x_result.exc : '0;
x_exception_o.tval = '0;
x_exception_o.tinst = '0;
x_exception_o.tval2 = '0;
x_exception_o.gva = '0;
x_we_o = x_valid_o ? cvxif_resp_i.x_result.we : '0;
if (illegal_n) begin
if (~x_valid_o) begin
x_trans_id_o = illegal_id_n;
x_result_o = '0;
x_valid_o = 1'b1;
x_exception_o.cause = riscv::ILLEGAL_INSTR;
x_exception_o.valid = 1'b1;
if (CVA6Cfg.TvalEn) x_exception_o.tval = illegal_instr_n;
x_exception_o.tinst = '0;
x_exception_o.tval2 = '0;
x_exception_o.gva = '0;
x_we_o = '0;
illegal_n = '0; // Reset flag for illegal instr. illegal_id and illegal instr values are a don't care, no need to reset it.
end
end
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (~rst_ni) begin
illegal_q <= 1'b0;
illegal_id_q <= '0;
illegal_instr_q <= '0;
end else begin
illegal_q <= illegal_n;
illegal_id_q <= illegal_id_n;
illegal_instr_q <= illegal_instr_n;
end end
end end

View file

@ -0,0 +1,68 @@
// Copyright 2024 Thales DIS France SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume Chauvon
module cvxif_issue_register_commit_if_driver #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type x_commit_t = logic
) (
// CVA6 inputs
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic [ CVA6Cfg.XLEN-1:0] hart_id_i,
// CVXIF Issue interface
input logic issue_ready_i,
input x_issue_resp_t issue_resp_i,
output logic issue_valid_o,
output x_issue_req_t issue_req_o,
// CVXIF Register interface
input logic register_ready_i,
output logic register_valid_o,
output x_register_t register_o,
// CVXIF Commit interface
output logic commit_valid_o,
output x_commit_t commit_o,
// IRO in/out
input logic valid_i,
input logic [ 31:0] x_off_instr_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_i,
input logic [ CVA6Cfg.NrRgprPorts-1:0][CVA6Cfg.XLEN-1:0] register_i,
input logic [ CVA6Cfg.NrRgprPorts-1:0] rs_valid_i,
output logic cvxif_busy_o
);
// X_ISSUE_REGISTER_SPLIT = 0 : Issue and register transactions are synchrone
// Mandatory assignement
assign register_valid_o = issue_valid_o;
assign register_o.hartid = issue_req_o.hartid;
assign register_o.id = issue_req_o.id;
// cvxif can not take any more instruction if issue transaction is still up.
assign cvxif_busy_o = issue_valid_o && ~issue_ready_i;
always_comb begin
issue_valid_o = valid_i && ~flush_i;
issue_req_o.instr = x_off_instr_i;
issue_req_o.hartid = hart_id_i;
issue_req_o.id = x_trans_id_i;
register_o.rs = register_i;
register_o.rs_valid = rs_valid_i;
end
/* WARNING */
// Always commit since speculation in execute in not possible : TODO to be verified
// Always do commit transaction with issue
// If instruction goes to execute then it is not speculative
assign commit_valid_o = issue_valid_o;
assign commit_o.hartid = issue_req_o.hartid;
assign commit_o.id = issue_req_o.id;
assign commit_o.commit_kill = 1'b0;
endmodule

View file

@ -112,7 +112,8 @@ module decoder
SBIMM, SBIMM,
UIMM, UIMM,
JIMM, JIMM,
RS3 RS3,
MUX_RD_RS3
} imm_select; } imm_select;
logic [CVA6Cfg.XLEN-1:0] imm_i_type; logic [CVA6Cfg.XLEN-1:0] imm_i_type;
@ -1422,13 +1423,16 @@ module decoder
endcase endcase
end end
if (CVA6Cfg.CvxifEn) begin if (CVA6Cfg.CvxifEn) begin
if (is_illegal_i || illegal_instr) begin if (~ex_i.valid && (is_illegal_i || illegal_instr)) begin
instruction_o.fu = CVXIF; instruction_o.fu = CVXIF;
instruction_o.rs1[4:0] = instr.r4type.rs1; instruction_o.rs1[4:0] = instr.r4type.rs1;
instruction_o.rs2[4:0] = instr.r4type.rs2; instruction_o.rs2[4:0] = instr.r4type.rs2;
instruction_o.rd[4:0] = instr.r4type.rd; instruction_o.rd[4:0] = instr.r4type.rd;
instruction_o.op = ariane_pkg::OFFLOAD; instruction_o.op = ariane_pkg::OFFLOAD;
imm_select = RS3; imm_select = instr.rtype.opcode == riscv::OpcodeMadd ||
instr.rtype.opcode == riscv::OpcodeMsub ||
instr.rtype.opcode == riscv::OpcodeNmadd ||
instr.rtype.opcode == riscv::OpcodeNmsub ? RS3 : MUX_RD_RS3;
end end
end end
@ -1504,6 +1508,11 @@ module decoder
instruction_o.result = {{CVA6Cfg.XLEN - 5{1'b0}}, instr.r4type.rs3}; instruction_o.result = {{CVA6Cfg.XLEN - 5{1'b0}}, instr.r4type.rs3};
instruction_o.use_imm = 1'b0; instruction_o.use_imm = 1'b0;
end end
MUX_RD_RS3: begin
// result holds address of operand rs3 which is in rd field
instruction_o.result = {{CVA6Cfg.XLEN - 5{1'b0}}, instr.rtype.rd};
instruction_o.use_imm = 1'b0;
end
default: begin default: begin
instruction_o.result = {CVA6Cfg.XLEN{1'b0}}; instruction_o.result = {CVA6Cfg.XLEN{1'b0}};
instruction_o.use_imm = 1'b0; instruction_o.use_imm = 1'b0;

View file

@ -28,7 +28,8 @@ module ex_stage
parameter type icache_arsp_t = logic, parameter type icache_arsp_t = logic,
parameter type icache_dreq_t = logic, parameter type icache_dreq_t = logic,
parameter type icache_drsp_t = logic, parameter type icache_drsp_t = logic,
parameter type lsu_ctrl_t = logic parameter type lsu_ctrl_t = logic,
parameter type x_result_t = logic
) ( ) (
// Subsystem Clock - SUBSYSTEM // Subsystem Clock - SUBSYSTEM
input logic clk_i, input logic clk_i,
@ -136,7 +137,7 @@ module ex_stage
input logic [CVA6Cfg.NrIssuePorts-1:0] x_valid_i, input logic [CVA6Cfg.NrIssuePorts-1:0] x_valid_i,
// CVXIF is ready - ISSUE_STAGE // CVXIF is ready - ISSUE_STAGE
output logic x_ready_o, output logic x_ready_o,
// undecoded instruction - ISSUE_STAGE // CVXIF undecoded instruction
input logic [31:0] x_off_instr_i, input logic [31:0] x_off_instr_i,
// CVXIF transaction ID - ISSUE_STAGE // CVXIF transaction ID - ISSUE_STAGE
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o, output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o,
@ -148,10 +149,14 @@ module ex_stage
output logic x_valid_o, output logic x_valid_o,
// CVXIF write enable - ISSUE_STAGE // CVXIF write enable - ISSUE_STAGE
output logic x_we_o, output logic x_we_o,
// CVXIF request - SUBSYSTEM // CVXIF destination register - ISSUE_STAGE
output cvxif_pkg::cvxif_req_t cvxif_req_o, output logic [4:0] x_rd_o,
// CVXIF response - SUBSYSTEM // CVXIF Result interface - SUBSYSTEM
input cvxif_pkg::cvxif_resp_t cvxif_resp_i, input logic x_result_valid_i,
input x_result_t x_result_i,
output logic x_result_ready_o,
// CVXIF Issue transaction rejected -> illegal instruction - ISSUE_STAGE
input logic x_transaction_rejected_i,
// accelerate port result is valid - ACC_DISPATCHER // accelerate port result is valid - ACC_DISPATCHER
input logic acc_valid_i, input logic acc_valid_i,
// Enable virtual memory translation - CSR_REGFILE // Enable virtual memory translation - CSR_REGFILE
@ -592,29 +597,31 @@ module ex_stage
cvxif_fu #( cvxif_fu #(
.CVA6Cfg(CVA6Cfg), .CVA6Cfg(CVA6Cfg),
.exception_t(exception_t), .exception_t(exception_t),
.fu_data_t(fu_data_t) .x_result_t(x_result_t)
) cvxif_fu_i ( ) cvxif_fu_i (
.clk_i, .clk_i,
.rst_ni, .rst_ni,
.fu_data_i (cvxif_data), .x_valid_i(|x_valid_i),
.priv_lvl_i(ld_st_priv_lvl_i), .x_trans_id_i(cvxif_data.trans_id),
.x_valid_i (|x_valid_i), .x_illegal_i(x_transaction_rejected_i),
.x_ready_o,
.x_off_instr_i, .x_off_instr_i,
.x_ready_o,
.x_trans_id_o, .x_trans_id_o,
.x_exception_o, .x_exception_o,
.x_result_o, .x_result_o,
.x_valid_o, .x_valid_o,
.x_we_o, .x_we_o,
.cvxif_req_o, .x_rd_o,
.cvxif_resp_i .result_valid_i(x_result_valid_i),
.result_i(x_result_i),
.result_ready_o(x_result_ready_o)
); );
end else begin : gen_no_cvxif end else begin : gen_no_cvxif
assign cvxif_req_o = '0; assign x_result_ready_o = '0;
assign x_trans_id_o = '0; assign x_trans_id_o = '0;
assign x_exception_o = '0; assign x_exception_o = '0;
assign x_result_o = '0; assign x_result_o = '0;
assign x_valid_o = '0; assign x_valid_o = '0;
end end
if (CVA6Cfg.RVS) begin if (CVA6Cfg.RVS) begin

View file

@ -21,7 +21,9 @@ module id_stage #(
parameter type irq_ctrl_t = logic, parameter type irq_ctrl_t = logic,
parameter type scoreboard_entry_t = logic, parameter type scoreboard_entry_t = logic,
parameter type interrupts_t = logic, parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0 parameter interrupts_t INTERRUPTS = '0,
parameter type x_compressed_req_t = logic,
parameter type x_compressed_resp_t = logic
) ( ) (
// Subsystem Clock - SUBSYSTEM // Subsystem Clock - SUBSYSTEM
input logic clk_i, input logic clk_i,
@ -76,7 +78,13 @@ module id_stage #(
// Trap sret - CSR_REGFILE // Trap sret - CSR_REGFILE
input logic tsr_i, input logic tsr_i,
// Hypervisor user mode - CSR_REGFILE // Hypervisor user mode - CSR_REGFILE
input logic hu_i input logic hu_i,
// CVXIF Compressed interface
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
input logic compressed_ready_i,
input x_compressed_resp_t compressed_resp_i,
output logic compressed_valid_o,
output x_compressed_req_t compressed_req_o
); );
// ID/ISSUE register stage // ID/ISSUE register stage
typedef struct packed { typedef struct packed {
@ -93,12 +101,17 @@ module id_stage #(
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal; logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal;
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_cmp; logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_cmp;
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_cvxif;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction; logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] compressed_instr; logic [CVA6Cfg.NrIssuePorts-1:0][31:0] compressed_instr;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_cvxif;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed; logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_cmp; logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_cmp;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_cvxif;
logic [CVA6Cfg.NrIssuePorts-1:0] is_macro_instr_i; logic [CVA6Cfg.NrIssuePorts-1:0] is_macro_instr_i;
logic stall_instr_fetch; logic stall_instr_fetch;
logic stall_macro_deco;
logic is_last_macro_instr_o; logic is_last_macro_instr_o;
logic is_double_rd_macro_instr_o; logic is_double_rd_macro_instr_o;
@ -126,25 +139,64 @@ module id_stage #(
.is_macro_instr_i (is_macro_instr_i[0]), .is_macro_instr_i (is_macro_instr_i[0]),
.clk_i (clk_i), .clk_i (clk_i),
.rst_ni (rst_ni), .rst_ni (rst_ni),
.instr_o (instruction[0]), .instr_o (instruction_cvxif[0]),
.illegal_instr_i (is_illegal[0]), .illegal_instr_i (is_illegal[0]),
.is_compressed_i (is_compressed[0]), .is_compressed_i (is_compressed[0]),
.issue_ack_i (issue_instr_ack_i[0]), .issue_ack_i (issue_instr_ack_i[0]),
.illegal_instr_o (is_illegal_cmp[0]), .illegal_instr_o (is_illegal_cvxif[0]),
.is_compressed_o (is_compressed_cmp[0]), .is_compressed_o (is_compressed_cvxif[0]),
.fetch_stall_o (stall_instr_fetch), .fetch_stall_o (stall_macro_deco),
.is_last_macro_instr_o (is_last_macro_instr_o), .is_last_macro_instr_o (is_last_macro_instr_o),
.is_double_rd_macro_instr_o(is_double_rd_macro_instr_o) .is_double_rd_macro_instr_o(is_double_rd_macro_instr_o)
); );
if (CVA6Cfg.SuperscalarEn) begin if (CVA6Cfg.SuperscalarEn) begin
assign instruction[CVA6Cfg.NrIssuePorts-1] = '0; assign instruction_cvxif[CVA6Cfg.NrIssuePorts-1] = '0;
assign is_illegal_cmp[CVA6Cfg.NrIssuePorts-1] = '0; assign is_illegal_cvxif[CVA6Cfg.NrIssuePorts-1] = '0;
assign is_compressed_cmp[CVA6Cfg.NrIssuePorts-1] = '0; assign is_compressed_cvxif[CVA6Cfg.NrIssuePorts-1] = '0;
end end
cvxif_compressed_if_driver #(
.CVA6Cfg(CVA6Cfg),
.x_compressed_req_t(x_compressed_req_t),
.x_compressed_resp_t(x_compressed_resp_t)
) i_cvxif_compressed_if_driver_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.hart_id_i (hart_id_i),
.is_compressed_i (is_compressed_cvxif),
.is_illegal_i (is_illegal_cvxif),
.instruction_i (instruction_cvxif),
.is_compressed_o (is_compressed_cmp),
.is_illegal_o (is_illegal_cmp),
.instruction_o (instruction),
.stall_i (stall_macro_deco),
.stall_o (stall_instr_fetch),
.compressed_ready_i(compressed_ready_i),
.compressed_resp_i (compressed_resp_i),
.compressed_valid_o(compressed_valid_o),
.compressed_req_o (compressed_req_o)
);
end else begin end else begin
assign instruction = compressed_instr; cvxif_compressed_if_driver #(
assign is_illegal_cmp = is_illegal; .CVA6Cfg(CVA6Cfg),
assign is_compressed_cmp = is_compressed; .x_compressed_req_t(x_compressed_req_t),
.x_compressed_resp_t(x_compressed_resp_t)
) i_cvxif_compressed_if_driver_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.hart_id_i (hart_id_i),
.is_compressed_i (is_compressed),
.is_illegal_i (is_illegal),
.instruction_i (compressed_instr),
.is_compressed_o (is_compressed_cmp),
.is_illegal_o (is_illegal_cmp),
.instruction_o (instruction),
.stall_i (1'b0),
.stall_o (stall_instr_fetch),
.compressed_ready_i(compressed_ready_i),
.compressed_resp_i (compressed_resp_i),
.compressed_valid_o(compressed_valid_o),
.compressed_req_o (compressed_req_o)
);
assign is_last_macro_instr_o = '0; assign is_last_macro_instr_o = '0;
assign is_double_rd_macro_instr_o = '0; assign is_double_rd_macro_instr_o = '0;
end end
@ -157,6 +209,11 @@ module id_stage #(
assign is_macro_instr_i = '0; assign is_macro_instr_i = '0;
assign is_last_macro_instr_o = '0; assign is_last_macro_instr_o = '0;
assign is_double_rd_macro_instr_o = '0; assign is_double_rd_macro_instr_o = '0;
if (CVA6Cfg.CvxifEn) begin
assign compressed_valid_o = '0;
assign compressed_req_o.instr = '0;
assign compressed_req_o.hartid = hart_id_i;
end // TODO Add else to map x_compressed_if outputs to '0 ?
end end
assign rvfi_is_compressed_o = is_compressed_cmp; assign rvfi_is_compressed_o = is_compressed_cmp;

View file

@ -84,7 +84,9 @@ package build_config_pkg;
cfg.XF16Vec = bit'(XF16Vec); cfg.XF16Vec = bit'(XF16Vec);
cfg.XF16ALTVec = bit'(XF16ALTVec); cfg.XF16ALTVec = bit'(XF16ALTVec);
cfg.XF8Vec = bit'(XF8Vec); cfg.XF8Vec = bit'(XF8Vec);
// Can take 2 or 3 in single issue. 4 or 6 in dual issue.
cfg.NrRgprPorts = unsigned'(CVA6Cfg.SuperscalarEn ? 4 : 2); cfg.NrRgprPorts = unsigned'(CVA6Cfg.SuperscalarEn ? 4 : 2);
// cfg.NrRgprPorts = unsigned'(CVA6Cfg.SuperscalarEn ? 6 : 3);
cfg.NrWbPorts = unsigned'(NrWbPorts); cfg.NrWbPorts = unsigned'(NrWbPorts);
cfg.EnableAccelerator = bit'(EnableAccelerator); cfg.EnableAccelerator = bit'(EnableAccelerator);
cfg.PerfCounterEn = CVA6Cfg.PerfCounterEn; cfg.PerfCounterEn = CVA6Cfg.PerfCounterEn;
@ -165,6 +167,16 @@ package build_config_pkg;
cfg.VpnLen = VpnLen; cfg.VpnLen = VpnLen;
cfg.PtLevels = PtLevels; cfg.PtLevels = PtLevels;
cfg.X_NUM_RS = cfg.NrRgprPorts;
cfg.X_ID_WIDTH = cfg.TRANS_ID_BITS;
cfg.X_RFR_WIDTH = cfg.XLEN;
cfg.X_RFW_WIDTH = cfg.XLEN;
cfg.X_NUM_HARTS = 1;
cfg.X_HARTID_WIDTH = cfg.XLEN;
cfg.X_DUALREAD = 0;
cfg.X_DUALWRITE = 0;
cfg.X_ISSUE_REGISTER_SPLIT = 0;
return cfg; return cfg;
endfunction endfunction

View file

@ -337,6 +337,17 @@ package config_pkg;
vm_mode_t MODE_SV; vm_mode_t MODE_SV;
int unsigned SV; int unsigned SV;
int unsigned SVX; int unsigned SVX;
int unsigned X_NUM_RS;
int unsigned X_ID_WIDTH;
int unsigned X_RFR_WIDTH;
int unsigned X_RFW_WIDTH;
int unsigned X_NUM_HARTS;
int unsigned X_HARTID_WIDTH;
int unsigned X_DUALREAD;
int unsigned X_DUALWRITE;
int unsigned X_ISSUE_REGISTER_SPLIT;
} cva6_cfg_t; } cva6_cfg_t;
/// Empty configuration to sanity check proper parameter passing. Whenever /// Empty configuration to sanity check proper parameter passing. Whenever

View file

@ -18,8 +18,6 @@ package cva6_config_pkg;
localparam CVA6ConfigAxiDataWidth = 64; // axi_pkg.sv localparam CVA6ConfigAxiDataWidth = 64; // axi_pkg.sv
localparam CVA6ConfigDataUserWidth = 32; // axi_pkg.sv localparam CVA6ConfigDataUserWidth = 32; // axi_pkg.sv
localparam CVA6ConfigNrScoreboardEntries = 8; // cvxif_pkg.sv
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{ localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
XLEN: unsigned'(CVA6ConfigXlen), XLEN: unsigned'(CVA6ConfigXlen),
FpgaEn: bit'(0), FpgaEn: bit'(0),
@ -49,7 +47,7 @@ package cva6_config_pkg;
RVZiCond: bit'(0), RVZiCond: bit'(0),
RVZicntr: bit'(0), RVZicntr: bit'(0),
RVZihpm: bit'(0), RVZihpm: bit'(0),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), NrScoreboardEntries: unsigned'(8),
PerfCounterEn: bit'(0), PerfCounterEn: bit'(0),
MmuPresent: bit'(0), MmuPresent: bit'(0),
RVS: bit'(0), RVS: bit'(0),

View file

@ -1,110 +0,0 @@
// Copyright 2021 Thales DIS design services SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Guillaume CHAUVON (guillaume.chauvon@thalesgroup.com)
// Package for the CoreV-X-Interface for the CVA6
package cvxif_pkg;
localparam X_DATAWIDTH = riscv::XLEN;
localparam X_NUM_RS = ariane_pkg::NR_RGPR_PORTS; //2 or 3
localparam X_ID_WIDTH = $clog2(cva6_config_pkg::CVA6ConfigNrScoreboardEntries);
localparam X_MEM_WIDTH = 64;
localparam X_RFR_WIDTH = riscv::XLEN;
localparam X_RFW_WIDTH = riscv::XLEN;
typedef struct packed {
logic [15:0] instr;
logic [1:0] mode;
logic [X_ID_WIDTH-1:0] id;
} x_compressed_req_t;
typedef struct packed {
logic [31:0] instr;
logic accept;
} x_compressed_resp_t;
typedef struct packed {
logic [31:0] instr;
logic [1:0] mode;
logic [X_ID_WIDTH-1:0] id;
logic [X_NUM_RS-1:0][X_RFR_WIDTH-1:0] rs;
logic [X_NUM_RS-1:0] rs_valid;
} x_issue_req_t;
typedef struct packed {
logic accept;
logic writeback;
logic dualwrite;
logic dualread;
logic loadstore;
logic exc;
} x_issue_resp_t;
typedef struct packed {
logic [X_ID_WIDTH-1:0] id;
logic x_commit_kill;
} x_commit_t;
typedef struct packed {
logic [X_ID_WIDTH-1:0] id;
logic [31:0] addr;
logic [1:0] mode;
logic we;
logic [1:0] size;
logic [X_MEM_WIDTH-1:0] wdata;
logic last;
logic spec;
} x_mem_req_t;
typedef struct packed {
logic exc;
logic [5:0] exccode;
} x_mem_resp_t;
typedef struct packed {
logic [X_ID_WIDTH-1:0] id;
logic [X_MEM_WIDTH-1:0] rdata;
logic err;
} x_mem_result_t;
typedef struct packed {
logic [X_ID_WIDTH-1:0] id;
logic [X_RFW_WIDTH-1:0] data;
logic [4:0] rd;
logic we;
logic exc;
logic [5:0] exccode;
} x_result_t;
typedef struct packed {
logic x_compressed_valid;
x_compressed_req_t x_compressed_req;
logic x_issue_valid;
x_issue_req_t x_issue_req;
logic x_commit_valid;
x_commit_t x_commit;
logic x_mem_ready;
x_mem_resp_t x_mem_resp;
logic x_mem_result_valid;
x_mem_result_t x_mem_result;
logic x_result_ready;
} cvxif_req_t;
typedef struct packed {
logic x_compressed_ready;
x_compressed_resp_t x_compressed_resp;
logic x_issue_ready;
x_issue_resp_t x_issue_resp;
logic x_mem_valid;
x_mem_req_t x_mem_req;
logic x_result_valid;
x_result_t x_result;
} cvxif_resp_t;
endpackage

View file

@ -0,0 +1,73 @@
`ifndef CVXIF_TYPES_SVH
`define CVXIF_TYPES_SVH
//CVXIF
`define READREGFLAGS_T(Cfg) logic [Cfg.X_NUM_RS+Cfg.X_DUALREAD-1:0]
`define WRITEREGFLAGS_T(Cfg) logic [Cfg.X_DUALWRITE:0]
`define ID_T(Cfg) logic [Cfg.X_ID_WIDTH-1:0]
`define HARTID_T(Cfg) logic [Cfg.X_HARTID_WIDTH-1:0]
`define X_COMPRESSED_REQ_T(Cfg, hartid_t) struct packed { \
logic [15:0] instr; /*Offloaded compressed instruction*/ \
hartid_t hartid; /*Identification of the hart offloading the instruction*/ \
}
`define X_COMPRESSED_RESP_T(Cfg) struct packed { \
logic [31:0] instr; /*Uncompressed instruction*/ \
logic accept; /*Is the offloaded compressed instruction (id) accepted by the coprocessor?*/ \
}
`define X_ISSUE_REQ_T(Cfg, hartit_t, id_t) struct packed { \
logic [31:0] instr; /*Offloaded instruction*/ \
hartid_t hartid; /*Identification of the hart offloading the instruction*/ \
id_t id; /*Identification of the offloaded instruction*/ \
}
`define X_ISSUE_RESP_T(Cfg, writeregflags_t, readregflags_t) struct packed { \
logic accept; /*Is the offloaded instruction (id) accepted by the coprocessor?*/ \
writeregflags_t writeback; /*Will the coprocessor perform a writeback in the core to rd?*/ \
readregflags_t register_read; /*Will the coprocessor perform require specific registers to be read?*/ \
}
`define X_REGISTER_T(Cfg, hartid_t, id_t, readregflags_t) struct packed { \
hartid_t hartid; /*Identification of the hart offloading the instruction*/ \
id_t id; /*Identification of the offloaded instruction*/ \
logic [Cfg.X_NUM_RS-1:0][Cfg.X_RFR_WIDTH-1:0] rs; /*Register file source operands for the offloaded instruction.*/ \
readregflags_t rs_valid; /*Validity of the register file source operand(s).*/ \
}
`define X_COMMIT_T(Cfg, hartid_t, id_t) struct packed { \
hartid_t hartid; /*Identification of the hart offloading the instruction*/ \
id_t id; /*Identification of the offloaded instruction*/ \
logic commit_kill; /*Shall an offloaded instruction be killed?*/ \
}
`define X_RESULT_T(Cfg, hartid_t, id_t, writeregflags_t) struct packed { \
hartid_t hartid; /*Identification of the hart offloading the instruction*/ \
id_t id; /*Identification of the offloaded instruction*/ \
logic [Cfg.X_RFW_WIDTH-1:0] data; /*Register file write data value(s)*/ \
logic [4:0] rd; /*Register file destination address(es)*/ \
writeregflags_t we; /*Register file write enable(s)*/ \
}
`define CVXIF_REQ_T(Cfg, x_compressed_req_t, x_issue_req_t, x_register_req_t, x_commit_t) struct packed { \
logic compressed_valid; \
x_compressed_req_t compressed_req; \
logic issue_valid; \
x_issue_req_t issue_req; \
logic register_valid; \
x_register_t register; \
logic commit_valid; \
x_commit_t commit; \
logic result_ready; \
}
`define CVXIF_RESP_T(Cfg, x_compressed_resp_t, x_issue_resp_t, x_result_t) struct packed { \
logic compressed_ready; \
x_compressed_resp_t compressed_resp; \
logic issue_ready; \
x_issue_resp_t issue_resp; \
logic register_ready; \
logic result_valid; \
x_result_t result; \
}
`endif // CVXIF_TYPES_SVH

View file

@ -21,7 +21,12 @@ module issue_read_operands
parameter type branchpredict_sbe_t = logic, parameter type branchpredict_sbe_t = logic,
parameter type fu_data_t = logic, parameter type fu_data_t = logic,
parameter type scoreboard_entry_t = logic, parameter type scoreboard_entry_t = logic,
parameter type rs3_len_t = logic parameter type rs3_len_t = logic,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type x_commit_t = logic
) ( ) (
// Subsystem Clock - SUBSYSTEM // Subsystem Clock - SUBSYSTEM
input logic clk_i, input logic clk_i,
@ -106,6 +111,25 @@ module issue_read_operands
input logic cvxif_ready_i, input logic cvxif_ready_i,
// CVXIF offloaded instruction - TO_BE_COMPLETED // CVXIF offloaded instruction - TO_BE_COMPLETED
output logic [31:0] cvxif_off_instr_o, output logic [31:0] cvxif_off_instr_o,
// CVA6 Hart ID - SUBSYSTEM
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
// CVXIF Issue interface
input logic x_issue_ready_i,
input x_issue_resp_t x_issue_resp_i,
output logic x_issue_valid_o,
output x_issue_req_t x_issue_req_o,
// CVXIF Register interface
input logic x_register_ready_i,
output logic x_register_valid_o,
output x_register_t x_register_o,
// CVXIF Commit interface
output logic x_commit_valid_o,
output x_commit_t x_commit_o,
// Writeback Handling of CVXIF
output logic x_transaction_accepted_o,
output logic x_transaction_rejected_o,
output logic x_issue_writeback_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_id_o,
// TO_BE_COMPLETED - TO_BE_COMPLETED // TO_BE_COMPLETED - TO_BE_COMPLETED
input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr_i, input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED // TO_BE_COMPLETED - TO_BE_COMPLETED
@ -125,7 +149,7 @@ module issue_read_operands
logic none, load, store, alu, alu2, ctrl_flow, mult, csr, fpu, fpu_vec, cvxif, accel; logic none, load, store, alu, alu2, ctrl_flow, mult, csr, fpu, fpu_vec, cvxif, accel;
} fus_busy_t; } fus_busy_t;
logic [CVA6Cfg.NrIssuePorts-1:0] stall; logic [CVA6Cfg.NrIssuePorts-1:0] stall, stall_rs1, stall_rs2, stall_rs3;
logic [CVA6Cfg.NrIssuePorts-1:0] fu_busy; // functional unit is busy logic [CVA6Cfg.NrIssuePorts-1:0] fu_busy; // functional unit is busy
fus_busy_t [CVA6Cfg.NrIssuePorts-1:0] fus_busy; // which functional units are considered busy fus_busy_t [CVA6Cfg.NrIssuePorts-1:0] fus_busy; // which functional units are considered busy
// operands coming from regfile // operands coming from regfile
@ -148,6 +172,8 @@ module issue_read_operands
logic [CVA6Cfg.NrIssuePorts-1:0] branch_valid_q; logic [CVA6Cfg.NrIssuePorts-1:0] branch_valid_q;
logic [CVA6Cfg.NrIssuePorts-1:0] cvxif_valid_q; logic [CVA6Cfg.NrIssuePorts-1:0] cvxif_valid_q;
logic [ 31:0] cvxif_off_instr_q; logic [ 31:0] cvxif_off_instr_q;
logic cvxif_instruction_valid;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] tinst_n, tinst_q; // transformed instruction logic [CVA6Cfg.NrIssuePorts-1:0][31:0] tinst_n, tinst_q; // transformed instruction
@ -158,6 +184,54 @@ module issue_read_operands
riscv::instruction_t orig_instr; riscv::instruction_t orig_instr;
assign orig_instr = riscv::instruction_t'(orig_instr_i[0]); assign orig_instr = riscv::instruction_t'(orig_instr_i[0]);
// CVXIF Signals
logic cvxif_busy;
logic x_transaction_rejected;
logic [CVA6Cfg.NrRgprPorts-1:0] rs_valid;
logic [CVA6Cfg.NrRgprPorts-1:0][CVA6Cfg.XLEN-1:0] rs;
cvxif_issue_register_commit_if_driver #(
.CVA6Cfg (CVA6Cfg),
.x_issue_req_t (x_issue_req_t),
.x_issue_resp_t(x_issue_resp_t),
.x_register_t (x_register_t),
.x_commit_t (x_commit_t)
) i_cvxif_issue_register_commit_if_driver (
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i (flush_i),
.hart_id_i (hart_id_i),
.issue_ready_i (x_issue_ready_i),
.issue_resp_i (x_issue_resp_i),
.issue_valid_o (x_issue_valid_o),
.issue_req_o (x_issue_req_o),
.register_ready_i(x_register_ready_i),
.register_valid_o(x_register_valid_o),
.register_o (x_register_o),
.commit_valid_o (x_commit_valid_o),
.commit_o (x_commit_o),
.valid_i (cvxif_instruction_valid),
.x_off_instr_i (orig_instr_i[0]),
.x_trans_id_i (issue_instr_i[0].trans_id),
.register_i (rs),
.rs_valid_i (rs_valid),
.cvxif_busy_o (cvxif_busy)
);
if (OPERANDS_PER_INSTR == 3) begin
assign rs_valid = {~stall_rs3[0], ~stall_rs2[0], ~stall_rs1[0]};
assign rs = {fu_data_n[0].imm, fu_data_n[0].operand_b, fu_data_n[0].operand_a};
end else begin
assign rs_valid = {~stall_rs2[0], ~stall_rs1[0]};
assign rs = {fu_data_n[0].operand_b, fu_data_n[0].operand_a};
end
// TODO check only for 1st instruction ??
assign cvxif_instruction_valid = (!issue_instr_i[0].ex.valid && issue_instr_valid_i[0] && (issue_instr_i[0].fu == CVXIF));
assign x_transaction_accepted_o = x_issue_valid_o && x_issue_ready_i && x_issue_resp_i.accept;
assign x_transaction_rejected = x_issue_valid_o && x_issue_ready_i && ~x_issue_resp_i.accept;
assign x_issue_writeback_o = x_issue_resp_i.writeback;
assign x_id_o = x_issue_req_o.id;
// ID <-> EX registers // ID <-> EX registers
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
@ -212,7 +286,7 @@ module issue_read_operands
fus_busy[0].store = 1'b1; fus_busy[0].store = 1'b1;
end end
if (!cvxif_ready_i) begin if (cvxif_busy) begin
fus_busy[0].cvxif = 1'b1; fus_busy[0].cvxif = 1'b1;
end end
@ -310,6 +384,9 @@ module issue_read_operands
// forward corresponding register // forward corresponding register
always_comb begin : operands_available always_comb begin : operands_available
stall = '{default: stall_i}; stall = '{default: stall_i};
stall_rs1 = '{default: stall_i};
stall_rs2 = '{default: stall_i};
stall_rs3 = '{default: stall_i};
// operand forwarding signals // operand forwarding signals
forward_rs1 = '0; forward_rs1 = '0;
forward_rs2 = '0; forward_rs2 = '0;
@ -323,12 +400,16 @@ module issue_read_operands
// 0. check that we are not using the zimm type in RS1 // 0. check that we are not using the zimm type in RS1
// as this is an immediate we do not have to wait on anything here // as this is an immediate we do not have to wait on anything here
// 0.bis check that rs1 is required by coprocessor if not do not wait here
// 1. check if the source registers are clobbered --> check appropriate clobber list (gpr/fpr) // 1. check if the source registers are clobbered --> check appropriate clobber list (gpr/fpr)
// 2. poll the scoreboard // 2. poll the scoreboard
if (!issue_instr_i[i].use_zimm && ((CVA6Cfg.FpPresent && is_rs1_fpr( if (!issue_instr_i[i].use_zimm && ((CVA6Cfg.FpPresent && is_rs1_fpr(
issue_instr_i[i].op issue_instr_i[i].op
)) ? rd_clobber_fpr_i[issue_instr_i[i].rs1] != NONE : )) ? rd_clobber_fpr_i[issue_instr_i[i].rs1] != NONE :
rd_clobber_gpr_i[issue_instr_i[i].rs1] != NONE)) begin rd_clobber_gpr_i[issue_instr_i[i].rs1] != NONE) ||
((CVA6Cfg.CvxifEn && x_issue_valid_o &&
x_issue_resp_i.accept && x_issue_resp_i.register_read[0]) &&
rd_clobber_gpr_i[issue_instr_i[i].rs1] != NONE)) begin
// check if the clobbering instruction is not a CSR instruction, CSR instructions can only // check if the clobbering instruction is not a CSR instruction, CSR instructions can only
// be fetched through the register file since they can't be forwarded // be fetched through the register file since they can't be forwarded
// if the operand is available, forward it. CSRs don't write to/from FPR // if the operand is available, forward it. CSRs don't write to/from FPR
@ -339,13 +420,17 @@ module issue_read_operands
forward_rs1[i] = 1'b1; forward_rs1[i] = 1'b1;
end else begin // the operand is not available -> stall end else begin // the operand is not available -> stall
stall[i] = 1'b1; stall[i] = 1'b1;
stall_rs1[i] = 1'b1;
end end
end end
if ((CVA6Cfg.FpPresent && is_rs2_fpr( if (((CVA6Cfg.FpPresent && is_rs2_fpr(
issue_instr_i[i].op issue_instr_i[i].op
)) ? rd_clobber_fpr_i[issue_instr_i[i].rs2] != NONE : )) ? rd_clobber_fpr_i[issue_instr_i[i].rs2] != NONE :
rd_clobber_gpr_i[issue_instr_i[i].rs2] != NONE) begin rd_clobber_gpr_i[issue_instr_i[i].rs2] != NONE) ||
((CVA6Cfg.CvxifEn &&
x_issue_valid_o && x_issue_resp_i.accept && x_issue_resp_i.register_read[1]) &&
rd_clobber_gpr_i[issue_instr_i[i].rs2] != NONE)) begin
// if the operand is available, forward it. CSRs don't write to/from FPR // if the operand is available, forward it. CSRs don't write to/from FPR
if (rs2_valid_i[i] && (CVA6Cfg.FpPresent && is_rs2_fpr( if (rs2_valid_i[i] && (CVA6Cfg.FpPresent && is_rs2_fpr(
issue_instr_i[i].op issue_instr_i[i].op
@ -354,20 +439,23 @@ module issue_read_operands
forward_rs2[i] = 1'b1; forward_rs2[i] = 1'b1;
end else begin // the operand is not available -> stall end else begin // the operand is not available -> stall
stall[i] = 1'b1; stall[i] = 1'b1;
stall_rs2[i] = 1'b1;
end end
end end
// Only check clobbered gpr for OFFLOADED instruction // Only check clobbered gpr for OFFLOADED instruction
if ((CVA6Cfg.FpPresent && is_imm_fpr( if (((CVA6Cfg.FpPresent && is_imm_fpr(
issue_instr_i[i].op issue_instr_i[i].op
)) ? rd_clobber_fpr_i[issue_instr_i[i].result[REG_ADDR_SIZE-1:0]] != NONE : )) ? rd_clobber_fpr_i[issue_instr_i[i].result[REG_ADDR_SIZE-1:0]] != NONE : 0) ||
issue_instr_i[i].op == OFFLOAD && CVA6Cfg.NrRgprPorts == 3 ? ((CVA6Cfg.CvxifEn && OPERANDS_PER_INSTR == 3 &&
rd_clobber_gpr_i[issue_instr_i[i].result[REG_ADDR_SIZE-1:0]] != NONE : 0) begin x_issue_valid_o && x_issue_resp_i.accept && x_issue_resp_i.register_read[2]) &&
rd_clobber_gpr_i[issue_instr_i[i].result] != NONE)) begin
// if the operand is available, forward it. CSRs don't write to/from FPR so no need to check // if the operand is available, forward it. CSRs don't write to/from FPR so no need to check
if (rs3_valid_i[i]) begin if (rs3_valid_i[i]) begin
forward_rs3[i] = 1'b1; forward_rs3[i] = 1'b1;
end else begin // the operand is not available -> stall end else begin // the operand is not available -> stall
stall[i] = 1'b1; stall[i] = 1'b1;
stall_rs3[i] = 1'b1;
end end
end end
end end
@ -395,7 +483,7 @@ module issue_read_operands
)) ? is_rd_fpr( )) ? is_rd_fpr(
issue_instr_i[0].op issue_instr_i[0].op
) && issue_instr_i[0].rd == issue_instr_i[1].result[REG_ADDR_SIZE-1:0] : ) && issue_instr_i[0].rd == issue_instr_i[1].result[REG_ADDR_SIZE-1:0] :
issue_instr_i[1].op == OFFLOAD && CVA6Cfg.NrRgprPorts == 3 ? issue_instr_i[1].op == OFFLOAD && OPERANDS_PER_INSTR == 3 ?
issue_instr_i[0].rd == issue_instr_i[1].result[REG_ADDR_SIZE-1:0] : 1'b0) begin issue_instr_i[0].rd == issue_instr_i[1].result[REG_ADDR_SIZE-1:0] : 1'b0) begin
stall[1] = 1'b1; stall[1] = 1'b1;
end end
@ -403,7 +491,7 @@ module issue_read_operands
end end
// third operand from fp regfile or gp regfile if NR_RGPR_PORTS == 3 // third operand from fp regfile or gp regfile if NR_RGPR_PORTS == 3
if (CVA6Cfg.NrRgprPorts == 3) begin : gen_gp_rs3 if (OPERANDS_PER_INSTR == 3) begin : gen_gp_rs3
assign imm_forward_rs3 = rs3_i[0]; assign imm_forward_rs3 = rs3_i[0];
end else begin : gen_fp_rs3 end else begin : gen_fp_rs3
assign imm_forward_rs3 = {{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, rs3_i[0]}; assign imm_forward_rs3 = {{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, rs3_i[0]};
@ -418,7 +506,7 @@ module issue_read_operands
// immediates are the third operands in the store case // immediates are the third operands in the store case
// for FP operations, the imm field can also be the third operand from the regfile // for FP operations, the imm field can also be the third operand from the regfile
if (CVA6Cfg.NrRgprPorts == 3) begin if (OPERANDS_PER_INSTR == 3) begin
fu_data_n[i].imm = (CVA6Cfg.FpPresent && is_imm_fpr(issue_instr_i[i].op)) ? fu_data_n[i].imm = (CVA6Cfg.FpPresent && is_imm_fpr(issue_instr_i[i].op)) ?
{{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, operand_c_regfile[i]} : {{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, operand_c_regfile[i]} :
issue_instr_i[i].op == OFFLOAD ? operand_c_regfile[i] : issue_instr_i[i].result; issue_instr_i[i].op == OFFLOAD ? operand_c_regfile[i] : issue_instr_i[i].result;
@ -440,7 +528,7 @@ module issue_read_operands
if (forward_rs2[i]) begin if (forward_rs2[i]) begin
fu_data_n[i].operand_b = rs2_i[i]; fu_data_n[i].operand_b = rs2_i[i];
end end
if (CVA6Cfg.FpPresent && forward_rs3[i]) begin if ((CVA6Cfg.FpPresent || (CVA6Cfg.CvxifEn && OPERANDS_PER_INSTR == 3)) && forward_rs3[i]) begin
fu_data_n[i].imm = imm_forward_rs3; fu_data_n[i].imm = imm_forward_rs3;
end end
@ -555,7 +643,7 @@ module issue_read_operands
case (issue_instr_i[i].fu) case (issue_instr_i[i].fu)
CVXIF: begin CVXIF: begin
cvxif_valid_q[i] <= 1'b1; cvxif_valid_q[i] <= 1'b1;
cvxif_off_instr_q <= orig_instr; cvxif_off_instr_q <= orig_instr[i];
end end
default: ; default: ;
endcase endcase
@ -619,6 +707,9 @@ module issue_read_operands
if (issue_instr_i[i].fu == NONE) begin if (issue_instr_i[i].fu == NONE) begin
issue_ack_o[i] = 1'b1; issue_ack_o[i] = 1'b1;
end end
if (issue_instr_i[i].fu == CVXIF) begin
issue_ack_o[i] = (x_transaction_accepted_o || x_transaction_rejected);
end
end end
end end
@ -749,14 +840,14 @@ module issue_read_operands
end end
endgenerate endgenerate
if (CVA6Cfg.NrRgprPorts == 3) begin : gen_operand_c if (OPERANDS_PER_INSTR == 3) begin : gen_operand_c
assign operand_c_fpr = {{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, fprdata[2]}; assign operand_c_fpr = {{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, fprdata[2]};
end else begin end else begin
assign operand_c_fpr = fprdata[2]; assign operand_c_fpr = fprdata[2];
end end
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
if (CVA6Cfg.NrRgprPorts == 3) begin : gen_operand_c if (OPERANDS_PER_INSTR == 3) begin : gen_operand_c
assign operand_c_gpr[i] = rdata[i*OPERANDS_PER_INSTR+2]; assign operand_c_gpr[i] = rdata[i*OPERANDS_PER_INSTR+2];
end end
@ -766,7 +857,7 @@ module issue_read_operands
assign operand_b_regfile[i] = (CVA6Cfg.FpPresent && is_rs2_fpr( assign operand_b_regfile[i] = (CVA6Cfg.FpPresent && is_rs2_fpr(
issue_instr_i[i].op issue_instr_i[i].op
)) ? {{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, fprdata[1]} : rdata[i*OPERANDS_PER_INSTR+1]; )) ? {{CVA6Cfg.XLEN - CVA6Cfg.FLen{1'b0}}, fprdata[1]} : rdata[i*OPERANDS_PER_INSTR+1];
assign operand_c_regfile[i] = (CVA6Cfg.NrRgprPorts == 3) ? ((CVA6Cfg.FpPresent && is_imm_fpr( assign operand_c_regfile[i] = (OPERANDS_PER_INSTR == 3) ? ((CVA6Cfg.FpPresent && is_imm_fpr(
issue_instr_i[i].op issue_instr_i[i].op
)) ? operand_c_fpr : operand_c_gpr[i]) : operand_c_fpr; )) ? operand_c_fpr : operand_c_gpr[i]) : operand_c_fpr;
end end
@ -780,9 +871,10 @@ module issue_read_operands
if (CVA6Cfg.RVH) begin if (CVA6Cfg.RVH) begin
tinst_q <= '0; tinst_q <= '0;
end end
pc_o <= '0; pc_o <= '0;
is_compressed_instr_o <= 1'b0; is_compressed_instr_o <= 1'b0;
branch_predict_o <= {cf_t'(0), {CVA6Cfg.VLEN{1'b0}}}; branch_predict_o <= {cf_t'(0), {CVA6Cfg.VLEN{1'b0}}};
x_transaction_rejected_o <= 1'b0;
end else begin end else begin
fu_data_q <= fu_data_n; fu_data_q <= fu_data_n;
if (CVA6Cfg.RVH) begin if (CVA6Cfg.RVH) begin
@ -800,6 +892,10 @@ module issue_read_operands
is_compressed_instr_o <= issue_instr_i[0].is_compressed; is_compressed_instr_o <= issue_instr_i[0].is_compressed;
branch_predict_o <= issue_instr_i[0].bp; branch_predict_o <= issue_instr_i[0].bp;
end end
x_transaction_rejected_o <= 1'b0;
if (issue_instr_i[0].fu == CVXIF) begin
x_transaction_rejected_o <= x_transaction_rejected;
end
end end
end end

View file

@ -22,7 +22,11 @@ module issue_stage
parameter type branchpredict_sbe_t = logic, parameter type branchpredict_sbe_t = logic,
parameter type exception_t = logic, parameter type exception_t = logic,
parameter type fu_data_t = logic, parameter type fu_data_t = logic,
parameter type scoreboard_entry_t = logic parameter type scoreboard_entry_t = logic,
parameter type x_issue_req_t = logic,
parameter type x_issue_resp_t = logic,
parameter type x_register_t = logic,
parameter type x_commit_t = logic
) ( ) (
// Subsystem Clock - SUBSYSTEM // Subsystem Clock - SUBSYSTEM
input logic clk_i, input logic clk_i,
@ -87,11 +91,27 @@ module issue_stage
// CSR is valid - EX_STAGE // CSR is valid - EX_STAGE
output logic [CVA6Cfg.NrIssuePorts-1:0] csr_valid_o, output logic [CVA6Cfg.NrIssuePorts-1:0] csr_valid_o,
// CVXIF FU is valid - EX_STAGE // CVXIF FU is valid - EX_STAGE
output logic [CVA6Cfg.NrIssuePorts-1:0] x_issue_valid_o, output logic [CVA6Cfg.NrIssuePorts-1:0] xfu_valid_o,
// CVXIF is FU ready - EX_STAGE // CVXIF is FU ready - EX_STAGE
input logic x_issue_ready_i, input logic xfu_ready_i,
// CVXIF offloader instruction value - EX_STAGE // CVXIF offloader instruction value - EX_STAGE
output logic [31:0] x_off_instr_o, output logic [31:0] x_off_instr_o,
// CVA6 Hart ID - SUBSYSTEM
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
// CVXIF Issue interface
input logic x_issue_ready_i,
input x_issue_resp_t x_issue_resp_i,
output logic x_issue_valid_o,
output x_issue_req_t x_issue_req_o,
// CVXIF Register interface
input logic x_register_ready_i,
output logic x_register_valid_o,
output x_register_t x_register_o,
// CVXIF Commit interface
output logic x_commit_valid_o,
output x_commit_t x_commit_o,
// CVXIF Transaction rejected -> instruction is illegal - EX_STAGE
output logic x_transaction_rejected_o,
// Issue scoreboard entry - ACC_DISPATCHER // Issue scoreboard entry - ACC_DISPATCHER
output scoreboard_entry_t issue_instr_o, output scoreboard_entry_t issue_instr_o,
// TO_BE_COMPLETED - ACC_DISPATCHER // TO_BE_COMPLETED - ACC_DISPATCHER
@ -108,6 +128,8 @@ module issue_stage
input logic [CVA6Cfg.NrWbPorts-1:0] wt_valid_i, input logic [CVA6Cfg.NrWbPorts-1:0] wt_valid_i,
// CVXIF write enable - EX_STAGE // CVXIF write enable - EX_STAGE
input logic x_we_i, input logic x_we_i,
// CVXIF destination register - ISSUE_STAGE
input logic [4:0] x_rd_i,
// TO_BE_COMPLETED - EX_STAGE // TO_BE_COMPLETED - EX_STAGE
input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr_i, input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr_i,
// TO_BE_COMPLETED - EX_STAGE // TO_BE_COMPLETED - EX_STAGE
@ -165,6 +187,9 @@ module issue_stage
assign issue_instr_o = issue_instr_sb_iro[0]; assign issue_instr_o = issue_instr_sb_iro[0];
assign issue_instr_hs_o = issue_instr_valid_sb_iro[0] & issue_ack_iro_sb[0]; assign issue_instr_hs_o = issue_instr_valid_sb_iro[0] & issue_ack_iro_sb[0];
logic x_transaction_accepted_iro_sb, x_issue_writeback_iro_sb;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_id_iro_sb;
// --------------------------------------------------------- // ---------------------------------------------------------
// 2. Manage instructions in a scoreboard // 2. Manage instructions in a scoreboard
@ -176,18 +201,21 @@ module issue_stage
.exception_t(exception_t), .exception_t(exception_t),
.scoreboard_entry_t(scoreboard_entry_t) .scoreboard_entry_t(scoreboard_entry_t)
) i_scoreboard ( ) i_scoreboard (
.sb_full_o (sb_full_o), .sb_full_o (sb_full_o),
.rd_clobber_gpr_o(rd_clobber_gpr_sb_iro), .rd_clobber_gpr_o (rd_clobber_gpr_sb_iro),
.rd_clobber_fpr_o(rd_clobber_fpr_sb_iro), .rd_clobber_fpr_o (rd_clobber_fpr_sb_iro),
.rs1_i (rs1_iro_sb), .x_transaction_accepted_i(x_transaction_accepted_iro_sb),
.rs1_o (rs1_sb_iro), .x_issue_writeback_i (x_issue_writeback_iro_sb),
.rs1_valid_o (rs1_valid_sb_iro), .x_id_i (x_id_iro_sb),
.rs2_i (rs2_iro_sb), .rs1_i (rs1_iro_sb),
.rs2_o (rs2_sb_iro), .rs1_o (rs1_sb_iro),
.rs2_valid_o (rs2_valid_iro_sb), .rs1_valid_o (rs1_valid_sb_iro),
.rs3_i (rs3_iro_sb), .rs2_i (rs2_iro_sb),
.rs3_o (rs3_sb_iro), .rs2_o (rs2_sb_iro),
.rs3_valid_o (rs3_valid_iro_sb), .rs2_valid_o (rs2_valid_iro_sb),
.rs3_i (rs3_iro_sb),
.rs3_o (rs3_sb_iro),
.rs3_valid_o (rs3_valid_iro_sb),
.decoded_instr_i (decoded_instr_i), .decoded_instr_i (decoded_instr_i),
.decoded_instr_valid_i(decoded_instr_valid_i), .decoded_instr_valid_i(decoded_instr_valid_i),
@ -212,38 +240,56 @@ module issue_stage
.branchpredict_sbe_t(branchpredict_sbe_t), .branchpredict_sbe_t(branchpredict_sbe_t),
.fu_data_t(fu_data_t), .fu_data_t(fu_data_t),
.scoreboard_entry_t(scoreboard_entry_t), .scoreboard_entry_t(scoreboard_entry_t),
.rs3_len_t(rs3_len_t) .rs3_len_t(rs3_len_t),
.x_issue_req_t(x_issue_req_t),
.x_issue_resp_t(x_issue_resp_t),
.x_register_t(x_register_t),
.x_commit_t(x_commit_t)
) i_issue_read_operands ( ) i_issue_read_operands (
.flush_i (flush_unissued_instr_i), .flush_i (flush_unissued_instr_i),
.issue_instr_i (issue_instr_sb_iro), .issue_instr_i (issue_instr_sb_iro),
.orig_instr_i (orig_instr_sb_iro), .orig_instr_i (orig_instr_sb_iro),
.issue_instr_valid_i(issue_instr_valid_sb_iro), .issue_instr_valid_i (issue_instr_valid_sb_iro),
.issue_ack_o (issue_ack_iro_sb), .issue_ack_o (issue_ack_iro_sb),
.fu_data_o (fu_data_o), .fu_data_o (fu_data_o),
.flu_ready_i (flu_ready_i), .flu_ready_i (flu_ready_i),
.rs1_o (rs1_iro_sb), .rs1_o (rs1_iro_sb),
.rs1_i (rs1_sb_iro), .rs1_i (rs1_sb_iro),
.rs1_valid_i (rs1_valid_sb_iro), .rs1_valid_i (rs1_valid_sb_iro),
.rs2_o (rs2_iro_sb), .rs2_o (rs2_iro_sb),
.rs2_i (rs2_sb_iro), .rs2_i (rs2_sb_iro),
.rs2_valid_i (rs2_valid_iro_sb), .rs2_valid_i (rs2_valid_iro_sb),
.rs3_o (rs3_iro_sb), .rs3_o (rs3_iro_sb),
.rs3_i (rs3_sb_iro), .rs3_i (rs3_sb_iro),
.rs3_valid_i (rs3_valid_iro_sb), .rs3_valid_i (rs3_valid_iro_sb),
.rd_clobber_gpr_i (rd_clobber_gpr_sb_iro), .rd_clobber_gpr_i (rd_clobber_gpr_sb_iro),
.rd_clobber_fpr_i (rd_clobber_fpr_sb_iro), .rd_clobber_fpr_i (rd_clobber_fpr_sb_iro),
.alu_valid_o (alu_valid_o), .alu_valid_o (alu_valid_o),
.alu2_valid_o (alu2_valid_o), .alu2_valid_o (alu2_valid_o),
.branch_valid_o (branch_valid_o), .branch_valid_o (branch_valid_o),
.csr_valid_o (csr_valid_o), .csr_valid_o (csr_valid_o),
.cvxif_valid_o (x_issue_valid_o), .cvxif_valid_o (xfu_valid_o),
.cvxif_ready_i (x_issue_ready_i), .cvxif_ready_i (xfu_ready_i),
.cvxif_off_instr_o (x_off_instr_o), .hart_id_i (hart_id_i),
.mult_valid_o (mult_valid_o), .x_issue_ready_i (x_issue_ready_i),
.rs1_forwarding_o (rs1_forwarding_xlen), .x_issue_resp_i (x_issue_resp_i),
.rs2_forwarding_o (rs2_forwarding_xlen), .x_issue_valid_o (x_issue_valid_o),
.stall_issue_o (stall_issue_o), .x_issue_req_o (x_issue_req_o),
.tinst_o (tinst_o), .x_register_ready_i (x_register_ready_i),
.x_register_valid_o (x_register_valid_o),
.x_register_o (x_register_o),
.x_commit_valid_o (x_commit_valid_o),
.x_commit_o (x_commit_o),
.x_transaction_accepted_o(x_transaction_accepted_iro_sb),
.x_transaction_rejected_o(x_transaction_rejected_o),
.x_issue_writeback_o (x_issue_writeback_iro_sb),
.x_id_o (x_id_iro_sb),
.cvxif_off_instr_o (x_off_instr_o),
.mult_valid_o (mult_valid_o),
.rs1_forwarding_o (rs1_forwarding_xlen),
.rs2_forwarding_o (rs2_forwarding_xlen),
.stall_issue_o (stall_issue_o),
.tinst_o (tinst_o),
.* .*
); );

View file

@ -33,13 +33,16 @@ module scoreboard #(
output ariane_pkg::fu_t [2**ariane_pkg::REG_ADDR_SIZE-1:0] rd_clobber_gpr_o, output ariane_pkg::fu_t [2**ariane_pkg::REG_ADDR_SIZE-1:0] rd_clobber_gpr_o,
// TO_BE_COMPLETED - TO_BE_COMPLETED // TO_BE_COMPLETED - TO_BE_COMPLETED
output ariane_pkg::fu_t [2**ariane_pkg::REG_ADDR_SIZE-1:0] rd_clobber_fpr_o, output ariane_pkg::fu_t [2**ariane_pkg::REG_ADDR_SIZE-1:0] rd_clobber_fpr_o,
// Writeback Handling of CVXIF
input logic x_transaction_accepted_i,
input logic x_issue_writeback_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_id_i,
// rs1 operand address - issue_read_operands // rs1 operand address - issue_read_operands
input logic [CVA6Cfg.NrIssuePorts-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] rs1_i, input logic [CVA6Cfg.NrIssuePorts-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] rs1_i,
// rs1 operand - issue_read_operands // rs1 operand - issue_read_operands
output logic [CVA6Cfg.NrIssuePorts-1:0][ CVA6Cfg.XLEN-1:0] rs1_o, output logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs1_o,
// rs1 operand is valid - issue_read_operands // rs1 operand is valid - issue_read_operands
output logic [CVA6Cfg.NrIssuePorts-1:0] rs1_valid_o, output logic [CVA6Cfg.NrIssuePorts-1:0] rs1_valid_o,
// rs2 operand address - issue_read_operands // rs2 operand address - issue_read_operands
input logic [CVA6Cfg.NrIssuePorts-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] rs2_i, input logic [CVA6Cfg.NrIssuePorts-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] rs2_i,
@ -96,6 +99,8 @@ module scoreboard #(
input logic [CVA6Cfg.NrWbPorts-1:0] wt_valid_i, input logic [CVA6Cfg.NrWbPorts-1:0] wt_valid_i,
// Cvxif we for writeback - TO_BE_COMPLETED // Cvxif we for writeback - TO_BE_COMPLETED
input logic x_we_i, input logic x_we_i,
// CVXIF destination register - ISSUE_STAGE
input logic [4:0] x_rd_i,
// TO_BE_COMPLETED - RVFI // TO_BE_COMPLETED - RVFI
output logic [ CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_issue_pointer_o, output logic [ CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_issue_pointer_o,
@ -225,8 +230,9 @@ module scoreboard #(
if (CVA6Cfg.DebugEn) begin if (CVA6Cfg.DebugEn) begin
mem_n[trans_id_i[i]].sbe.bp.predict_address = resolved_branch_i.target_address; mem_n[trans_id_i[i]].sbe.bp.predict_address = resolved_branch_i.target_address;
end end
if (mem_n[trans_id_i[i]].sbe.fu == ariane_pkg::CVXIF && ~x_we_i) begin if (mem_n[trans_id_i[i]].sbe.fu == ariane_pkg::CVXIF) begin
mem_n[trans_id_i[i]].sbe.rd = 5'b0; if (x_we_i) mem_n[trans_id_i[i]].sbe.rd = x_rd_i;
else mem_n[trans_id_i[i]].sbe.rd = 5'b0;
end end
// write the exception back if it is valid // write the exception back if it is valid
if (ex_i[i].valid) mem_n[trans_id_i[i]].sbe.ex = ex_i[i]; if (ex_i[i].valid) mem_n[trans_id_i[i]].sbe.ex = ex_i[i];
@ -492,8 +498,9 @@ module scoreboard #(
commit_pointer_q <= '0; commit_pointer_q <= '0;
issue_pointer_q <= '0; issue_pointer_q <= '0;
end else begin end else begin
issue_pointer_q <= issue_pointer_n; issue_pointer_q <= issue_pointer_n;
mem_q <= mem_n; mem_q <= mem_n;
mem_q[x_id_i].sbe.rd <= (x_transaction_accepted_i && ~x_issue_writeback_i) ? 5'b0 : mem_n[x_id_i].sbe.rd;
commit_pointer_q <= commit_pointer_n; commit_pointer_q <= commit_pointer_n;
end end
end end

View file

@ -12,6 +12,7 @@
// Date: 19.03.2017 // Date: 19.03.2017
// Description: Ariane Top-level module // Description: Ariane Top-level module
`include "cvxif_types.svh"
module ariane import ariane_pkg::*; #( module ariane import ariane_pkg::*; #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
@ -21,6 +22,21 @@ module ariane import ariane_pkg::*; #(
logic csr; logic csr;
logic instr; logic instr;
}, },
// CVXIF Types
localparam type readregflags_t = `READREGFLAGS_T(CVA6Cfg),
localparam type writeregflags_t = `WRITEREGFLAGS_T(CVA6Cfg),
localparam type id_t = `ID_T(CVA6Cfg),
localparam type hartid_t = `HARTID_T(CVA6Cfg),
localparam type x_compressed_req_t = `X_COMPRESSED_REQ_T(CVA6Cfg, hartid_t),
localparam type x_compressed_resp_t = `X_COMPRESSED_RESP_T(CVA6Cfg),
localparam type x_issue_req_t = `X_ISSUE_REQ_T(CVA6Cfg, hartit_t, id_t),
localparam type x_issue_resp_t = `X_ISSUE_RESP_T(CVA6Cfg, writeregflags_t, readregflags_t),
localparam type x_register_t = `X_REGISTER_T(CVA6Cfg, hartid_t, id_t, readregflags_t),
localparam type x_commit_t = `X_COMMIT_T(CVA6Cfg, hartid_t, id_t),
localparam type x_result_t = `X_RESULT_T(CVA6Cfg, hartid_t, id_t, writeregflags_t),
localparam type cvxif_req_t = `CVXIF_REQ_T(CVA6Cfg, x_compressed_req_t, x_issue_req_t, x_register_req_t, x_commit_t),
localparam type cvxif_resp_t = `CVXIF_RESP_T(CVA6Cfg, x_compressed_resp_t, x_issue_resp_t, x_result_t),
// AXI Types
parameter int unsigned AxiAddrWidth = ariane_axi::AddrWidth, parameter int unsigned AxiAddrWidth = ariane_axi::AddrWidth,
parameter int unsigned AxiDataWidth = ariane_axi::DataWidth, parameter int unsigned AxiDataWidth = ariane_axi::DataWidth,
parameter int unsigned AxiIdWidth = ariane_axi::IdWidth, parameter int unsigned AxiIdWidth = ariane_axi::IdWidth,
@ -50,8 +66,8 @@ module ariane import ariane_pkg::*; #(
input noc_resp_t noc_resp_i input noc_resp_t noc_resp_i
); );
cvxif_pkg::cvxif_req_t cvxif_req; cvxif_req_t cvxif_req;
cvxif_pkg::cvxif_resp_t cvxif_resp; cvxif_resp_t cvxif_resp;
cva6 #( cva6 #(
.CVA6Cfg ( CVA6Cfg ), .CVA6Cfg ( CVA6Cfg ),
@ -62,7 +78,20 @@ module ariane import ariane_pkg::*; #(
.axi_aw_chan_t (axi_aw_chan_t), .axi_aw_chan_t (axi_aw_chan_t),
.axi_w_chan_t (axi_w_chan_t), .axi_w_chan_t (axi_w_chan_t),
.noc_req_t (noc_req_t), .noc_req_t (noc_req_t),
.noc_resp_t (noc_resp_t) .noc_resp_t (noc_resp_t),
.readregflags_t (readregflags_t),
.writeregflags_t (writeregflags_t),
.id_t (id_t),
.hartid_t (hartid_t),
.x_compressed_req_t (x_compressed_req_t),
.x_compressed_resp_t (x_compressed_resp_t),
.x_issue_req_t (x_issue_req_t),
.x_issue_resp_t (x_issue_resp_t),
.x_register_t (x_register_t),
.x_commit_t (x_commit_t),
.x_result_t (x_result_t),
.cvxif_req_t (cvxif_req_t),
.cvxif_resp_t (cvxif_resp_t)
) i_cva6 ( ) i_cva6 (
.clk_i ( clk_i ), .clk_i ( clk_i ),
.rst_ni ( rst_ni ), .rst_ni ( rst_ni ),
@ -81,7 +110,20 @@ module ariane import ariane_pkg::*; #(
if (CVA6Cfg.CvxifEn) begin : gen_example_coprocessor if (CVA6Cfg.CvxifEn) begin : gen_example_coprocessor
cvxif_example_coprocessor #( cvxif_example_coprocessor #(
.CVA6Cfg ( CVA6Cfg ) .NrRgprPorts (CVA6Cfg.NrRgprPorts),
.readregflags_t (readregflags_t),
.writeregflags_t (writeregflags_t),
.id_t (id_t),
.hartid_t (hartid_t),
.x_compressed_req_t (x_compressed_req_t),
.x_compressed_resp_t (x_compressed_resp_t),
.x_issue_req_t (x_issue_req_t),
.x_issue_resp_t (x_issue_resp_t),
.x_register_t (x_register_t),
.x_commit_t (x_commit_t),
.x_result_t (x_result_t),
.cvxif_req_t (cvxif_req_t),
.cvxif_resp_t (cvxif_resp_t)
) i_cvxif_coprocessor ( ) i_cvxif_coprocessor (
.clk_i ( clk_i ), .clk_i ( clk_i ),
.rst_ni ( rst_ni ), .rst_ni ( rst_ni ),
@ -90,4 +132,6 @@ module ariane import ariane_pkg::*; #(
); );
end end
endmodule // ariane endmodule // ariane

@ -1 +1 @@
Subproject commit ebf2e3a0b402cd56fd4b571b705b31f3be62c2cc Subproject commit c8c8075a6a71be67ac723528070e3e50ff7586b2

View file

@ -30,7 +30,6 @@ class uvme_cva6_cov_model_c extends uvm_component;
uvme_cva6_cntxt_c cntxt; uvme_cva6_cntxt_c cntxt;
// Components // Components
uvme_cvxif_covg_c cvxif_covg;
uvme_isa_cov_model_c isa_covg; uvme_isa_cov_model_c isa_covg;
uvme_cva6_config_covg_c config_covg; uvme_cva6_config_covg_c config_covg;
uvme_illegal_instr_cov_model_c illegal_covg; uvme_illegal_instr_cov_model_c illegal_covg;
@ -102,12 +101,6 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase);
`uvm_fatal("CNTXT", "Context handle is null") `uvm_fatal("CNTXT", "Context handle is null")
end end
if (cfg.cvxif_cfg.cov_model_enabled) begin
cvxif_covg = uvme_cvxif_covg_c::type_id::create("cvxif_covg", this);
uvm_config_db#(uvme_cva6_cfg_c)::set(this, "cvxif_covg", "cfg", cfg);
uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "cvxif_covg", "cntxt", cntxt);
end
if (cfg.isacov_cfg.cov_model_enabled) begin if (cfg.isacov_cfg.cov_model_enabled) begin
isa_covg = uvme_isa_cov_model_c::type_id::create("isa_covg", this); isa_covg = uvme_isa_cov_model_c::type_id::create("isa_covg", this);
illegal_covg = uvme_illegal_instr_cov_model_c::type_id::create("illegal_covg", this); illegal_covg = uvme_illegal_instr_cov_model_c::type_id::create("illegal_covg", this);

View file

@ -0,0 +1,137 @@
..
Copyright (c) 2023 OpenHW Group
Copyright (c) 2023 Thales DIS design services SAS
SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
..
Custom Instruction to challenge CV-X-IF protocol
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes some custom instruction, for stress or challenge the CV-X-IF protocol for the 3 implemented interfaces, it's just to interact with the cvxif agent.
All instructions use opcode `CUSTOM_3`(0x7b, 0b111_1011).
- **CUS_NOP**: Custom No Operation
**Format**: cus_nop -> |0000000000000000000000000|111_1011|
**Description**: do nothing, it's just a hint instruction.
**Pseudocode**: cus_nop
**Invalid values**: NONE
- **CUS_ADD**: Custom Add
**Format**: cus_add rd, rs1, rs2 -> |0000000|rs2|rs1|001|rd|111_1011|
**Description**: add register rs1 to rs2, and store the result in rd.
**Pseudocode**: x[rd] = x[rs1] + x[rs2]
**Invalid values**: NONE
- **CUS_DOUBLE_RS1**: Custom Double RS1
**Format**: cus_add rd, rs1, rs1 -> |0000001|rs2|rs1|001|rd|111_1011|
**Description**: add register rs1 to rs1, and store the result in rd.
Any rs2 value can be given. It should be ignored by CPU.
Exists to check that register depedencies is well implemented in CPU.
**Pseudocode**: x[rd] = x[rs1] + x[rs1]
**Invalid values**: NONE
- **CUS_DOUBLE_RS2**: Custom Double RS2
**Format**: cus_add rd, rs2, rs2 -> |0000010|rs2|rs1|001|rd|111_1011|
**Description**: add register rs2 to rs2, and store the result in rd.
Any rs1 value can be given. It should be ignored by CPU.
Exists to check that register depedencies is well implemented in CPU.
**Pseudocode**: x[rd] = x[rs2] + x[rs2]
**Invalid values**: NONE
- **CUS_ADD_MULTI**: Custom Multicycle Add
**Format**: addi rd, rs1, rs2 -> |0000011|rs2|rs1|001|rd|111_1011|
**Description**: add register rs1 to rs2, and store the result in rd. Coprocessor should randomly delays the result
**Pseudocode**: x[rd] = x[rs1] + x[rs2]
**Invalid values**: NONE
- **CUS_ADD_RS3_MADD**: Custom Add with RS3 opcode == MADD
**Format**: addi rd, rs1, rs2, rs3 -> |rs3|00|rs2|rs1|000|rd|100_0011|
**Description**: add register rs1, rs2 to rs3, and store the result in rd.
**Pseudocode**: x[rd] = x[rs1] + x[rs2] + x[rs3]
**Invalid values**: NONE
- **CUS_ADD_RS3_MSUB**: Custom Add with RS3 opcode == MSUB
**Format**: addi rd, rs1, rs2, rs3 -> |rs3|00|rs2|rs1|000|rd|100_0111|
**Description**: add register rs1, rs2 to rs3, and store the result in rd.
**Pseudocode**: x[rd] = x[rs1] + x[rs2] + x[rs3]
**Invalid values**: NONE
- **CUS_ADD_RS3_NMADD**: Custom Add with RS3 opcode == NMADD
**Format**: addi rd, rs1, rs2, rs3 -> |rs3|00|rs2|rs1|000|rd|100_1111|
**Description**: add register rs1, rs2 to rs3, and store the result in rd.
**Pseudocode**: x[rd] = x[rs1] + x[rs2] + x[rs3]
**Invalid values**: NONE
- **CUS_ADD_RS3_NMADD**: Custom Add with RS3 opcode == NMSUB
**Format**: addi rd, rs1, rs2, rs3 -> |rs3|00|rs2|rs1|000|rd|100_0011|
**Description**: add register rs1, rs2 to rs3, and store the result in rd.
**Pseudocode**: x[rd] = x[rs1] + x[rs2] + x[rs3]
**Invalid values**: NONE
- **CUS_ADD_RS3_RTYPE**: Custom Add with RS3, rd is x10 (a0)
**Format**: addi a0, rs1, rs2, rs3 -> |0000100|rs2|rs1|001|rs3|100_0011|
**Description**: add register rs1, rs2 to rs3, and store the result in x10 (a0).
**Pseudocode**: x[10] = x[rs1] + x[rs2] + x[rs3]
**Invalid values**: NONE
- **CUS_CNOP** : Custom Compressed NOP
**Format**: cus_cnop -> |111|0|00000|00000|00|
**Description**: Extends to CUS_NOP : do nothing, it's just a hint instruction.
**Pseudocode**: cus_cnop
**Invalid values**: NONE
- **CUS_CADD** : Custom Compressed ADD
**Format**: cus_cnop -> |111|1|rs1|rs2|00|
**Description**: Extends to CUS_ADD rs1, rs2 -> x10 : Add rs1 + rs2 into x10 (a0).
**Pseudocode**: cus_cadd
**Invalid values**: NONE

View file

@ -39,7 +39,6 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
// Agent cfg handles // Agent cfg handles
rand uvma_clknrst_cfg_c clknrst_cfg; rand uvma_clknrst_cfg_c clknrst_cfg;
rand uvma_cvxif_cfg_c cvxif_cfg;
rand uvma_axi_cfg_c axi_cfg; rand uvma_axi_cfg_c axi_cfg;
rand uvma_rvfi_cfg_c#(ILEN,XLEN) rvfi_cfg; rand uvma_rvfi_cfg_c#(ILEN,XLEN) rvfi_cfg;
rand uvma_isacov_cfg_c isacov_cfg; rand uvma_isacov_cfg_c isacov_cfg;
@ -75,8 +74,6 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
`uvm_field_object(clknrst_cfg, UVM_DEFAULT) `uvm_field_object(clknrst_cfg, UVM_DEFAULT)
`uvm_field_object(cvxif_cfg, UVM_DEFAULT)
`uvm_field_object(axi_cfg, UVM_DEFAULT) `uvm_field_object(axi_cfg, UVM_DEFAULT)
`uvm_field_object(rvfi_cfg, UVM_DEFAULT) `uvm_field_object(rvfi_cfg, UVM_DEFAULT)
@ -97,19 +94,9 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
soft sys_clk_period == uvme_cva6_sys_default_clk_period; // see uvme_cva6_constants.sv soft sys_clk_period == uvme_cva6_sys_default_clk_period; // see uvme_cva6_constants.sv
} }
constraint cvxif_feature { //CV32A65X do not support dual read & write also the memory interface
cvxif_cfg.dual_read_write_support_x == 0;
cvxif_cfg.load_store_support_x == 0;
cvxif_cfg.seq_cus_instr_x2_enabled == 1;
cvxif_cfg.reg_cus_crosses_enabled == 0;
cvxif_cfg.mode_s_supported == CVA6Cfg.RVS;
cvxif_cfg.mode_u_supported == CVA6Cfg.RVU;
}
constraint cva6_riscv_cons { constraint cva6_riscv_cons {
xlen == CVA6Cfg.XLEN; xlen == CVA6Cfg.XLEN;
ilen == 32; ilen == 32;
ext_i_supported == 1; ext_i_supported == 1;
ext_a_supported == CVA6Cfg.RVA; ext_a_supported == CVA6Cfg.RVA;
ext_m_supported == 1; ext_m_supported == 1;
@ -227,7 +214,6 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c;
} }
if (cov_model_enabled) { if (cov_model_enabled) {
cvxif_cfg.cov_model_enabled == 1;
isacov_cfg.cov_model_enabled == 1; isacov_cfg.cov_model_enabled == 1;
axi_cfg.cov_model_enabled == 1; axi_cfg.cov_model_enabled == 1;
interrupt_cfg.cov_model_enabled == 1; interrupt_cfg.cov_model_enabled == 1;
@ -258,7 +244,6 @@ function uvme_cva6_cfg_c::new(string name="uvme_cva6_cfg");
super.new(name); super.new(name);
clknrst_cfg = uvma_clknrst_cfg_c::type_id::create("clknrst_cfg"); clknrst_cfg = uvma_clknrst_cfg_c::type_id::create("clknrst_cfg");
cvxif_cfg = uvma_cvxif_cfg_c::type_id::create("cvxif_cfg");
axi_cfg = uvma_axi_cfg_c::type_id::create("axi_cfg"); axi_cfg = uvma_axi_cfg_c::type_id::create("axi_cfg");
rvfi_cfg = uvma_rvfi_cfg_c#(ILEN,XLEN)::type_id::create("rvfi_cfg"); rvfi_cfg = uvma_rvfi_cfg_c#(ILEN,XLEN)::type_id::create("rvfi_cfg");
isacov_cfg = uvma_isacov_cfg_c::type_id::create("isacov_cfg"); isacov_cfg = uvma_isacov_cfg_c::type_id::create("isacov_cfg");

View file

@ -31,7 +31,6 @@ class uvme_cva6_cntxt_c extends uvm_object;
// Agent context handles // Agent context handles
uvma_clknrst_cntxt_c clknrst_cntxt; uvma_clknrst_cntxt_c clknrst_cntxt;
uvma_cvxif_cntxt_c cvxif_cntxt;
uvma_axi_cntxt_c axi_cntxt; uvma_axi_cntxt_c axi_cntxt;
uvma_cva6_core_cntrl_cntxt_c core_cntrl_cntxt; uvma_cva6_core_cntrl_cntxt_c core_cntrl_cntxt;
uvma_rvfi_cntxt_c rvfi_cntxt; uvma_rvfi_cntxt_c rvfi_cntxt;

View file

@ -42,7 +42,6 @@ class uvme_cva6_env_c extends uvm_env;
// Agents // Agents
uvma_clknrst_agent_c clknrst_agent; uvma_clknrst_agent_c clknrst_agent;
uvma_cvxif_agent_c cvxif_agent;
uvma_axi_agent_c axi_agent; uvma_axi_agent_c axi_agent;
uvma_cva6_core_cntrl_agent_c core_cntrl_agent; uvma_cva6_core_cntrl_agent_c core_cntrl_agent;
uvma_rvfi_agent_c#(ILEN,XLEN) rvfi_agent; uvma_rvfi_agent_c#(ILEN,XLEN) rvfi_agent;
@ -246,8 +245,6 @@ function void uvme_cva6_env_c::assign_cfg();
uvm_config_db#(uvma_clknrst_cfg_c)::set(this, "*clknrst_agent", "cfg", cfg.clknrst_cfg); uvm_config_db#(uvma_clknrst_cfg_c)::set(this, "*clknrst_agent", "cfg", cfg.clknrst_cfg);
uvm_config_db#(uvma_cvxif_cfg_c)::set(this, "*cvxif_agent", "cfg", cfg.cvxif_cfg);
uvm_config_db#(uvma_axi_cfg_c)::set(this, "*axi_agent", "cfg", cfg.axi_cfg); uvm_config_db#(uvma_axi_cfg_c)::set(this, "*axi_agent", "cfg", cfg.axi_cfg);
uvm_config_db#(uvma_core_cntrl_cfg_c)::set(this, "core_cntrl_agent", "cfg", cfg); uvm_config_db#(uvma_core_cntrl_cfg_c)::set(this, "core_cntrl_agent", "cfg", cfg);
@ -278,7 +275,6 @@ endfunction: assign_cntxt
function void uvme_cva6_env_c::create_agents(); function void uvme_cva6_env_c::create_agents();
clknrst_agent = uvma_clknrst_agent_c::type_id::create("clknrst_agent", this); clknrst_agent = uvma_clknrst_agent_c::type_id::create("clknrst_agent", this);
cvxif_agent = uvma_cvxif_agent_c::type_id::create("cvxif_agent", this);
axi_agent = uvma_axi_agent_c::type_id::create("axi_agent", this); axi_agent = uvma_axi_agent_c::type_id::create("axi_agent", this);
core_cntrl_agent = uvma_cva6_core_cntrl_agent_c::type_id::create("core_cntrl_agent", this); core_cntrl_agent = uvma_cva6_core_cntrl_agent_c::type_id::create("core_cntrl_agent", this);
rvfi_agent = uvma_rvfi_agent_c#(ILEN,XLEN)::type_id::create("rvfi_agent", this); rvfi_agent = uvma_rvfi_agent_c#(ILEN,XLEN)::type_id::create("rvfi_agent", this);
@ -361,7 +357,6 @@ endfunction: connect_scoreboard
function void uvme_cva6_env_c::assemble_vsequencer(); function void uvme_cva6_env_c::assemble_vsequencer();
vsequencer.clknrst_sequencer = clknrst_agent.sequencer; vsequencer.clknrst_sequencer = clknrst_agent.sequencer;
vsequencer.cvxif_vsequencer = cvxif_agent.vsequencer;
vsequencer.axi_vsequencer = axi_agent.vsequencer; vsequencer.axi_vsequencer = axi_agent.vsequencer;
vsequencer.interrupt_sequencer = interrupt_agent.sequencer; vsequencer.interrupt_sequencer = interrupt_agent.sequencer;
@ -372,12 +367,6 @@ task uvme_cva6_env_c::run_phase(uvm_phase phase);
fork fork
begin
uvme_cvxif_vseq_c cvxif_vseq;
cvxif_vseq = uvme_cvxif_vseq_c::type_id::create("cvxif_vseq");
cvxif_vseq.start(cvxif_agent.vsequencer);
end
begin begin
if(cfg.axi_cfg.is_active == UVM_ACTIVE) begin if(cfg.axi_cfg.is_active == UVM_ACTIVE) begin
uvma_axi_vseq_c axi_vseq; uvma_axi_vseq_c axi_vseq;
@ -398,9 +387,6 @@ endtask
function void uvme_cva6_env_c::connect_coverage_model(); function void uvme_cva6_env_c::connect_coverage_model();
if (cfg.cvxif_cfg.cov_model_enabled) begin
cvxif_agent.monitor.req_ap.connect(cov_model.cvxif_covg.req_item_fifo.analysis_export);
end
if (cfg.isacov_cfg.cov_model_enabled) begin if (cfg.isacov_cfg.cov_model_enabled) begin
isacov_agent.monitor.ap.connect(cov_model.isa_covg.mon_trn_fifo.analysis_export); isacov_agent.monitor.ap.connect(cov_model.isa_covg.mon_trn_fifo.analysis_export);
isacov_agent.monitor.ap.connect(cov_model.illegal_covg.mon_trn_fifo.analysis_export); isacov_agent.monitor.ap.connect(cov_model.illegal_covg.mon_trn_fifo.analysis_export);

View file

@ -21,7 +21,6 @@
+incdir+${CVA6_UVME_PATH} +incdir+${CVA6_UVME_PATH}
+incdir+${CVA6_UVME_PATH}/cov +incdir+${CVA6_UVME_PATH}/cov
+incdir+${CVA6_UVME_PATH}/vseq +incdir+${CVA6_UVME_PATH}/vseq
+incdir+${CVA6_UVME_PATH}/cvxif_vseq
+incdir+${CVA6_UVME_PATH}/uvma_interrupt +incdir+${CVA6_UVME_PATH}/uvma_interrupt
// Files // Files

View file

@ -30,7 +30,6 @@
`include "uvml_mem_macros.sv" `include "uvml_mem_macros.sv"
`include "uvma_axi_macros.sv" `include "uvma_axi_macros.sv"
`include "uvma_clknrst_macros.sv" `include "uvma_clknrst_macros.sv"
`include "uvma_cvxif_macros.sv"
`include "uvma_isacov_macros.sv" `include "uvma_isacov_macros.sv"
`include "uvme_cva6_macros.sv" `include "uvme_cva6_macros.sv"
@ -46,7 +45,6 @@ package uvme_cva6_pkg;
import uvml_sb_pkg ::*; import uvml_sb_pkg ::*;
import uvml_trn_pkg ::*; import uvml_trn_pkg ::*;
import uvma_clknrst_pkg::*; import uvma_clknrst_pkg::*;
import uvma_cvxif_pkg::*;
import uvma_axi_pkg::*; import uvma_axi_pkg::*;
import uvml_mem_pkg ::*; import uvml_mem_pkg ::*;
import uvma_core_cntrl_pkg::*; import uvma_core_cntrl_pkg::*;
@ -100,7 +98,6 @@ package uvme_cva6_pkg;
`include "uvma_cva6_core_cntrl_agent.sv" `include "uvma_cva6_core_cntrl_agent.sv"
`include "uvme_cva6_sb.sv" `include "uvme_cva6_sb.sv"
`include "uvme_cva6_vsqr.sv" `include "uvme_cva6_vsqr.sv"
`include "uvme_cvxif_covg.sv"
`include "uvme_isa_covg.sv" `include "uvme_isa_covg.sv"
`include "uvme_illegal_instr_covg.sv" `include "uvme_illegal_instr_covg.sv"
`include "uvme_exception_covg.sv" `include "uvme_exception_covg.sv"

View file

@ -36,7 +36,6 @@ class uvme_cva6_vsqr_c extends uvm_sequencer#(
// Sequencer handles // Sequencer handles
uvma_clknrst_sqr_c clknrst_sequencer; uvma_clknrst_sqr_c clknrst_sequencer;
uvma_cvxif_vsqr_c cvxif_vsequencer;
uvma_axi_vsqr_c axi_vsequencer; uvma_axi_vsqr_c axi_vsequencer;
uvma_interrupt_sqr_c interrupt_sequencer; uvma_interrupt_sqr_c interrupt_sequencer;

View file

@ -36,6 +36,7 @@ if ! [ -n "$UVM_VERBOSITY" ]; then
export UVM_VERBOSITY=UVM_NONE export UVM_VERBOSITY=UVM_NONE
fi fi
export cvxif=1 # For CVXIF in Spike
export DV_OPTS="$DV_OPTS --issrun_opts=+debug_disable=1+UVM_VERBOSITY=$UVM_VERBOSITY" export DV_OPTS="$DV_OPTS --issrun_opts=+debug_disable=1+UVM_VERBOSITY=$UVM_VERBOSITY"
CC_OPTS="-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g ../tests/custom/common/syscalls.c ../tests/custom/common/crt.S -I../tests/custom/env -I../tests/custom/common -lgcc" CC_OPTS="-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g ../tests/custom/common/syscalls.c ../tests/custom/common/crt.S -I../tests/custom/env -I../tests/custom/common -lgcc"
@ -61,6 +62,7 @@ make clean_all
python3 cva6.py --testlist=../tests/testlist_riscv-compliance-cv32a60x.yaml --test rv32i-I-ADD-01 --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS $DV_OPTS python3 cva6.py --testlist=../tests/testlist_riscv-compliance-cv32a60x.yaml --test rv32i-I-ADD-01 --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS $DV_OPTS
python3 cva6.py --testlist=../tests/testlist_riscv-tests-cv32a60x-p.yaml --test rv32ui-p-add --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS $DV_OPTS python3 cva6.py --testlist=../tests/testlist_riscv-tests-cv32a60x-p.yaml --test rv32ui-p-add --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS $DV_OPTS
python3 cva6.py --testlist=../tests/testlist_riscv-arch-test-cv32a60x.yaml --test rv32im-cadd-01 --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS $DV_OPTS --linker=../tests/riscv-arch-test/riscv-target/spike/link.ld python3 cva6.py --testlist=../tests/testlist_riscv-arch-test-cv32a60x.yaml --test rv32im-cadd-01 --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS $DV_OPTS --linker=../tests/riscv-arch-test/riscv-target/spike/link.ld
python3 cva6.py --testlist=../tests/testlist_cvxif.yaml --test cvxif_add_nop --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS $DV_OPTS
python3 cva6.py --c_tests ../tests/custom/hello_world/hello_world.c --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS --linker=../tests/custom/common/test.ld --gcc_opts="$CC_OPTS" $DV_OPTS python3 cva6.py --c_tests ../tests/custom/hello_world/hello_world.c --iss_yaml cva6.yaml --target cv32a65x --iss=$DV_SIMULATORS --linker=../tests/custom/common/test.ld --gcc_opts="$CC_OPTS" $DV_OPTS
make -C ../.. clean make -C ../.. clean
make clean_all make clean_all

View file

@ -163,7 +163,6 @@ export DV_UVMA_CORE_CNTRL_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_core_cntrl
export DV_UVMA_RVFI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_rvfi export DV_UVMA_RVFI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_rvfi
export DV_UVMA_ISACOV_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_isacov export DV_UVMA_ISACOV_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_isacov
export DV_UVMA_CLKNRST_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_clknrst export DV_UVMA_CLKNRST_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_clknrst
export DV_UVMA_CVXIF_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_cvxif
export DV_UVMA_AXI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_axi5 export DV_UVMA_AXI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_axi5
export DV_UVMA_INTERRUPT_PATH = $(DV_UVME_PATH)/uvma_interrupt export DV_UVMA_INTERRUPT_PATH = $(DV_UVME_PATH)/uvma_interrupt
export DV_UVMA_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug export DV_UVMA_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug

View file

@ -29,6 +29,8 @@
import uvm_pkg::*; import uvm_pkg::*;
`include "uvm_macros.svh" `include "uvm_macros.svh"
`include "cvxif_types.svh"
`ifndef DPI_FESVR_SPIKE_UTILS `ifndef DPI_FESVR_SPIKE_UTILS
`define DPI_FESVR_SPIKE_UTILS `define DPI_FESVR_SPIKE_UTILS
@ -46,6 +48,20 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
parameter type rvfi_probes_instr_t = logic, parameter type rvfi_probes_instr_t = logic,
parameter type rvfi_probes_csr_t = logic, parameter type rvfi_probes_csr_t = logic,
parameter type rvfi_probes_t = logic, parameter type rvfi_probes_t = logic,
// CVXIF Types
localparam type readregflags_t = `READREGFLAGS_T(CVA6Cfg),
localparam type writeregflags_t = `WRITEREGFLAGS_T(CVA6Cfg),
localparam type id_t = `ID_T(CVA6Cfg),
localparam type hartid_t = `HARTID_T(CVA6Cfg),
localparam type x_compressed_req_t = `X_COMPRESSED_REQ_T(CVA6Cfg, hartid_t),
localparam type x_compressed_resp_t = `X_COMPRESSED_RESP_T(CVA6Cfg),
localparam type x_issue_req_t = `X_ISSUE_REQ_T(CVA6Cfg, hartit_t, id_t),
localparam type x_issue_resp_t = `X_ISSUE_RESP_T(CVA6Cfg, writeregflags_t, readregflags_t),
localparam type x_register_t = `X_REGISTER_T(CVA6Cfg, hartid_t, id_t, readregflags_t),
localparam type x_commit_t = `X_COMMIT_T(CVA6Cfg, hartid_t, id_t),
localparam type x_result_t = `X_RESULT_T(CVA6Cfg, hartid_t, id_t, writeregflags_t),
localparam type cvxif_req_t = `CVXIF_REQ_T(CVA6Cfg, x_compressed_req_t, x_issue_req_t, x_register_req_t, x_commit_t),
localparam type cvxif_resp_t = `CVXIF_RESP_T(CVA6Cfg, x_compressed_resp_t, x_issue_resp_t, x_result_t),
// //
parameter int unsigned AXI_USER_EN = 0, parameter int unsigned AXI_USER_EN = 0,
parameter int unsigned NUM_WORDS = 2**25 parameter int unsigned NUM_WORDS = 2**25
@ -56,8 +72,6 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
output logic [31:0] tb_exit_o, output logic [31:0] tb_exit_o,
output rvfi_instr_t [CVA6Cfg.NrCommitPorts-1:0] rvfi_o, output rvfi_instr_t [CVA6Cfg.NrCommitPorts-1:0] rvfi_o,
output rvfi_csr_t rvfi_csr_o, output rvfi_csr_t rvfi_csr_o,
input cvxif_pkg::cvxif_resp_t cvxif_resp,
output cvxif_pkg::cvxif_req_t cvxif_req,
input logic [2:0] irq_i, input logic [2:0] irq_i,
uvma_axi_intf axi_slave, uvma_axi_intf axi_slave,
uvmt_axi_switch_intf axi_switch_vif, uvmt_axi_switch_intf axi_switch_vif,
@ -76,6 +90,9 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
assign rvfi_o = rvfi_instr; assign rvfi_o = rvfi_instr;
assign rvfi_csr_o = rvfi_csr; assign rvfi_csr_o = rvfi_csr;
cvxif_req_t cvxif_req;
cvxif_resp_t cvxif_resp;
cva6 #( cva6 #(
.CVA6Cfg ( CVA6Cfg ), .CVA6Cfg ( CVA6Cfg ),
.rvfi_probes_instr_t ( rvfi_probes_instr_t ), .rvfi_probes_instr_t ( rvfi_probes_instr_t ),
@ -93,10 +110,34 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
.rvfi_probes_o ( rvfi_probes ), .rvfi_probes_o ( rvfi_probes ),
.cvxif_req_o ( cvxif_req ), .cvxif_req_o ( cvxif_req ),
.cvxif_resp_i ( cvxif_resp ), .cvxif_resp_i ( cvxif_resp ),
.noc_req_o ( axi_ariane_req ), .noc_req_o ( axi_ariane_req ),
.noc_resp_i ( axi_ariane_resp ) .noc_resp_i ( axi_ariane_resp )
); );
if (CVA6Cfg.CvxifEn) begin : gen_example_coprocessor
cvxif_example_coprocessor #(
.NrRgprPorts (CVA6Cfg.NrRgprPorts),
.readregflags_t (readregflags_t),
.writeregflags_t (writeregflags_t),
.id_t (id_t),
.hartid_t (hartid_t),
.x_compressed_req_t (x_compressed_req_t),
.x_compressed_resp_t (x_compressed_resp_t),
.x_issue_req_t (x_issue_req_t),
.x_issue_resp_t (x_issue_resp_t),
.x_register_t (x_register_t),
.x_commit_t (x_commit_t),
.x_result_t (x_result_t),
.cvxif_req_t (cvxif_req_t),
.cvxif_resp_t (cvxif_resp_t)
) i_cvxif_coprocessor (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.cvxif_req_i ( cvxif_req ),
.cvxif_resp_o ( cvxif_resp )
);
end
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// RVFI // RVFI
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View file

@ -23,7 +23,6 @@
// Agents // Agents
-f ${DV_UVMA_CLKNRST_PATH}/uvma_clknrst_pkg.flist -f ${DV_UVMA_CLKNRST_PATH}/uvma_clknrst_pkg.flist
-f ${DV_UVMA_CVXIF_PATH}/src/uvma_cvxif_pkg.flist
-f ${DV_UVMA_AXI_PATH}/src/uvma_axi_pkg.flist -f ${DV_UVMA_AXI_PATH}/src/uvma_axi_pkg.flist
-f ${DV_UVMA_CORE_CNTRL_PATH}/uvma_core_cntrl_pkg.flist -f ${DV_UVMA_CORE_CNTRL_PATH}/uvma_core_cntrl_pkg.flist
-f ${DV_UVMA_RVFI_PATH}/uvma_rvfi_pkg.flist -f ${DV_UVMA_RVFI_PATH}/uvma_rvfi_pkg.flist

View file

@ -29,7 +29,6 @@ module uvmt_cva6_dut_wrap # (
( (
uvma_clknrst_if clknrst_if, uvma_clknrst_if clknrst_if,
uvma_cvxif_intf cvxif_if,
uvma_axi_intf axi_if, uvma_axi_intf axi_if,
uvmt_axi_switch_intf axi_switch_vif, uvmt_axi_switch_intf axi_switch_vif,
uvmt_default_inputs_intf default_inputs_vif, uvmt_default_inputs_intf default_inputs_vif,
@ -59,8 +58,6 @@ module uvmt_cva6_dut_wrap # (
.clk_i ( clknrst_if.clk ), .clk_i ( clknrst_if.clk ),
.rst_ni ( clknrst_if.reset_n ), .rst_ni ( clknrst_if.reset_n ),
.boot_addr_i ( boot_addr ), .boot_addr_i ( boot_addr ),
.cvxif_resp ( cvxif_if.cvxif_resp_o ),
.cvxif_req ( cvxif_if.cvxif_req_i ),
.irq_i ( interrupt_vif.irq ), .irq_i ( interrupt_vif.irq ),
.axi_slave ( axi_if ), .axi_slave ( axi_if ),
.axi_switch_vif ( axi_switch_vif ), .axi_switch_vif ( axi_switch_vif ),
@ -70,16 +67,4 @@ module uvmt_cva6_dut_wrap # (
.rvfi_o ( rvfi_o ) .rvfi_o ( rvfi_o )
); );
assign cvxif_if.cvxif_resp_o.x_compressed_ready = 0;
assign cvxif_if.cvxif_resp_o.x_compressed_resp = 0;
assign cvxif_if.cvxif_resp_o.x_issue_ready = 1;
assign cvxif_if.cvxif_resp_o.x_issue_resp = 0;
assign cvxif_if.cvxif_resp_o.x_result_valid = 0;
assign cvxif_if.cvxif_resp_o.x_result.id = 0;
assign cvxif_if.cvxif_resp_o.x_result.data = 0;
assign cvxif_if.cvxif_resp_o.x_result.rd = 0;
assign cvxif_if.cvxif_resp_o.x_result.we = 0;
assign cvxif_if.cvxif_resp_o.x_result.exc = 0;
assign cvxif_if.cvxif_resp_o.x_result.exccode = 0;
endmodule endmodule

View file

@ -59,10 +59,7 @@ module uvmt_cva6_tb;
// Agent interfaces // Agent interfaces
uvma_clknrst_if clknrst_if(); // clock and resets from the clknrst agent uvma_clknrst_if clknrst_if(); // clock and resets from the clknrst agent
uvma_cvxif_intf cvxif_if(
.clk(clknrst_if.clk),
.reset_n(clknrst_if.reset_n)
); // cvxif from the cvxif agent
uvma_axi_intf axi_if( uvma_axi_intf axi_if(
.clk(clknrst_if.clk), .clk(clknrst_if.clk),
.rst_n(clknrst_if.reset_n) .rst_n(clknrst_if.reset_n)
@ -83,12 +80,6 @@ module uvmt_cva6_tb;
uvmt_default_inputs_intf default_inputs_vif(); uvmt_default_inputs_intf default_inputs_vif();
//bind assertion module for cvxif interface
bind uvmt_cva6_dut_wrap
uvma_cvxif_assert cvxif_assert(.cvxif_assert(cvxif_if),
.clk(clknrst_if.clk),
.reset_n(clknrst_if.reset_n)
);
//bind assertion module for axi interface //bind assertion module for axi interface
bind uvmt_cva6_dut_wrap bind uvmt_cva6_dut_wrap
uvmt_axi_assert #(CVA6Cfg.DCacheType) axi_assert(.axi_assert_if(axi_if)); uvmt_axi_assert #(CVA6Cfg.DCacheType) axi_assert(.axi_assert_if(axi_if));
@ -122,7 +113,6 @@ module uvmt_cva6_tb;
.NUM_WORDS (NUM_WORDS) .NUM_WORDS (NUM_WORDS)
) cva6_dut_wrap ( ) cva6_dut_wrap (
.clknrst_if(clknrst_if), .clknrst_if(clknrst_if),
.cvxif_if (cvxif_if),
.axi_if (axi_if), .axi_if (axi_if),
.axi_switch_vif (axi_switch_vif), .axi_switch_vif (axi_switch_vif),
.default_inputs_vif (default_inputs_vif), .default_inputs_vif (default_inputs_vif),
@ -371,7 +361,6 @@ module uvmt_cva6_tb;
// Add interfaces handles to uvm_config_db // Add interfaces handles to uvm_config_db
uvm_config_db#(virtual uvma_clknrst_if )::set(.cntxt(null), .inst_name("*.env.clknrst_agent"), .field_name("vif"), .value(clknrst_if)); uvm_config_db#(virtual uvma_clknrst_if )::set(.cntxt(null), .inst_name("*.env.clknrst_agent"), .field_name("vif"), .value(clknrst_if));
uvm_config_db#(virtual uvma_cvxif_intf )::set(.cntxt(null), .inst_name("*.env.cvxif_agent"), .field_name("vif"), .value(cvxif_if) );
uvm_config_db#(virtual uvma_axi_intf )::set(.cntxt(null), .inst_name("*"), .field_name("axi_vif"), .value(axi_if)); uvm_config_db#(virtual uvma_axi_intf )::set(.cntxt(null), .inst_name("*"), .field_name("axi_vif"), .value(axi_if));
uvm_config_db#(virtual uvmt_axi_switch_intf )::set(.cntxt(null), .inst_name("*.env"), .field_name("axi_switch_vif"), .value(axi_switch_vif)); uvm_config_db#(virtual uvmt_axi_switch_intf )::set(.cntxt(null), .inst_name("*.env"), .field_name("axi_switch_vif"), .value(axi_switch_vif));
uvm_config_db#(virtual uvmt_rvfi_if#( .CVA6Cfg(CVA6Cfg), .rvfi_instr_t(rvfi_instr_t), .rvfi_csr_t (rvfi_csr_t)))::set(.cntxt(null), .inst_name("*"), .field_name("rvfi_vif"), .value(rvfi_if)); uvm_config_db#(virtual uvmt_rvfi_if#( .CVA6Cfg(CVA6Cfg), .rvfi_instr_t(rvfi_instr_t), .rvfi_csr_t (rvfi_csr_t)))::set(.cntxt(null), .inst_name("*"), .field_name("rvfi_vif"), .value(rvfi_if));

View file

@ -21,16 +21,36 @@ main:
# core of the test # core of the test
start0:
LOAD_RS(a0, 0x332211); LOAD_RS(a0, 0x332211);
LOAD_RS(a1, 0xDEADBEEF); LOAD_RS(a1, 0xDEADBEEF);
LOAD_RS(a2, 0xDEADBEEF); LOAD_RS(a2, 0xDEADBEEF);
CUS_NOP();
CUS_ADD(01010, 01010, 01011);
CUS_ADD(01011, 01010, 01011);
CUS_ADD(01010, 01011, 01011);
lw a0, num1;
CUS_ADD_RS1(01000,01010,01011);
lw a1, num2;
CUS_ADD(01010,01011,00000);
CUS_ADD(01010,01010,01010,01011); # Take branch to check for instruction kill
CUS_NOP(00000,00000,00000,00000); li a0, 0xCAFE;
CUS_NOP(00000,00000,00000,00000); li a1, 0xCAFE;
CUS_ADD(01010,01010,01010,01011); xor a2, a0, a1;
CUS_NOP(00000,00000,00000,00000); beqz a2, branch2;
CUS_ADD(01010,01010,01010,01011);
branch1:
CUS_ADD(00000, 00000, 01011);
CUS_NOP();
CUS_NOP();
branch2:
CUS_ADD(01010, 01010, 01011);
lw a0, num1;
CUS_ADD_RS1(01000,01010,01011);
lw a1, num2;
CUS_ADD(01010,01011,00000);
# (example of) final self-check test # (example of) final self-check test
li a0, 0xCAFE; li a0, 0xCAFE;
@ -47,3 +67,8 @@ pass:
# Success post-processing (messages, ecall setup etc.) # Success post-processing (messages, ecall setup etc.)
li a0, 0x0; li a0, 0x0;
jal exit; jal exit;
.data
num1: .word 5 // First number
num2: .word 7 // Second number
result: .word 12 // Result

View file

@ -0,0 +1,104 @@
# See LICENSE for license details.
#*****************************************************************************
# Copyright 2022 Thales DIS design services SAS
#
# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
# You may obtain a copy of the License at https:#solderpad.org/licenses/
#
#----------------------------------------------------------------------------------
#include "cvxif_macros.h"
#-------------------------------------------------------------
# Custom tests
#-------------------------------------------------------------
.globl main
main:
# core of the test
start0:
LOAD_RS(a0, 0x332211);
LOAD_RS(a1, 0xDEADBEEF);
LOAD_RS(a2, 0xDEADBEEF);
CUS_NOP();
CUS_ADD(01010, 01010, 01011);
CUS_ADD(01011, 01010, 01011);
CUS_ADD(01010, 01011, 01011);
lw a0, num1;
CUS_ADD_RS1(01000,01010,01011);
lw a1, num2;
CUS_ADD(01010,01011,00000);
# R4-Type RS3 Instructions
LOAD_RS(a0, 0x111111);
LOAD_RS(a1, 0x222222);
LOAD_RS(a2, 0x333333);
CUS_ADD_RS3_MADD(01010,01011,01100,01101);
CUS_ADD_RS3_MSUB(01010,01011,01100,01101);
CUS_ADD_RS3_NMADD(01010,01011,01100,01101);
CUS_ADD_RS3_NMSUB(01010,01011,01100,01101);
# R-type RS3 Instruction
LOAD_RS(a0, 0x111111);
LOAD_RS(a1, 0x222222);
LOAD_RS(a2, 0x333333);
CUS_ADD_RS3_RTYPE(01010,01011,01100); # --> result in 0b01010
CUS_ADD_RS3_RTYPE(01010,01011,01100); # --> result in 0b01010
CUS_ADD_RS3_RTYPE(01010,01011,01100); # --> result in 0b01010
# Take branch to check for instruction kill
li a0, 0xCAFE;
li a1, 0xCAFE;
xor a2, a0, a1;
beqz a2, branch2;
branch1:
CUS_ADD(00000, 00000, 01011);
CUS_NOP();
CUS_NOP();
branch2:
CUS_ADD(01010, 01010, 01011);
lw a0, num1;
CUS_ADD_RS1(01000,01010,01011);
lw a1, num2;
CUS_ADD(01010,01011,00000);
# Compressed instruction leads to error in spike
LOAD_RS(a0, 0x111111);
LOAD_RS(a1, 0x222222);
LOAD_RS(a2, 0x333333);
CUS_CNOP();
CUS_CADD(01011,01010);
xor a1, a0, a2;
beqz a2, pass;
# Should raise an exception
# .half 0x0000;
# .word 0xFFFFFFFF;
# (example of) final self-check test
# li a0, 0xCAFE;
# li a1, 0xCAFE;
# xor a2, a0, a1;
# beqz a2, pass;
fail:
# Failure post-processing (messages, ecall setup etc.)
li a0, 0x0;
jal exit;
pass:
# Success post-processing (messages, ecall setup etc.)
li a0, 0x0;
jal exit;
.data
num1: .word 5 // First number
num2: .word 7 // Second number
result: .word 12 // Result

View file

@ -6,14 +6,23 @@
// You may obtain a copy of the License at https://solderpad.org/licenses/ // You may obtain a copy of the License at https://solderpad.org/licenses/
// //
// Original Author: Zineb EL KACIMI (zineb.el-kacimi@external.thalesgroup.com) // Original Author: Zineb EL KACIMI (zineb.el-kacimi@external.thalesgroup.com)
// Contributor : Guillaume Chauvon
#define LOAD_RS(rs,value) li rs, value #define LOAD_RS(rs,value) li rs, value
#define COMP_RS(rs1,rs2,rd) xor rd, rs1, rs2 #define COMP_RS(rs1,rs2,rd) xor rd, rs1, rs2
#define CUS_NOP() .word 0b##0000000##00000####00000##000##00000##1111011
#define CUS_ADD(rs1,rs2,rd) .word 0b##0000000##rs2####rs1##001##rd##1111011 #define CUS_ADD(rs1,rs2,rd) .word 0b##0000000##rs2####rs1##001##rd##1111011
#define CUS_NOP(rs1,rs2,rd) .word 0b##0000000##00000####00000##000##00000##1111011 #define CUS_ADD_RS1(rs1,rs2,rd) .word 0b##0000001##rs2####rs1##001##rd##1111011 // only use rs1 : rs1 + rs1 => rd
#define CUS_ADD_RS3(rs1,rs2,rs3,rd) .word 0b##rs3##01##rs2####rs1##000##rd##1111011 #define CUS_ADD_RS2(rs1,rs2,rd) .word 0b##0000010##rs2####rs1##001##rd##1111011 // only use rs2 : rs2 + rs2 => rd
#define CUS_ADD_MULTI(rs1,rs2,rd) .word 0b##0001000##rs2####rs1##000##rd##1111011 #define CUS_ADD_MULTI(rs1,rs2,rd) .word 0b##0000011##rs2####rs1##001##rd##1111011
#define CUS_EXC(rs1,rs2,rs3,rd) .word 0b####1100000##rs2####rs1##010##rd##1111011
#define CUS_U_ADD(rs1,rs2,rd) .word 0b####0000010##rs2####rs1##000##rd##1111011 #define CUS_ADD_RS3_MADD(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1000011 //MADD
#define CUS_S_ADD(rs1,rs2,rd) .word 0b####0000110##rs2####rs1##000##rd##1111011 #define CUS_ADD_RS3_MSUB(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1000111 //MSUB
#define CUS_ADD_RS3_NMSUB(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1001011 //NMSUB
#define CUS_ADD_RS3_NMADD(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1001111 //NMADD
#define CUS_ADD_RS3_RTYPE(rs1,rs2,rs3) .word 0b##0000100##rs2####rs1##001##rs3##1111011
#define CUS_CADD(rs1, rs2) .half 0b##111##1##rs1##rs2##00 // -> Extend to CUS_ADD(rs1,rs2,x10)
#define CUS_CNOP() .half 0b##111##0##00000##00000##00 // -> Extend to CUS_NOP

View file

@ -36,10 +36,15 @@ common_test_config_lgcc: &common_test_config_lgcc
testlist: testlist:
- test: cvxif_add_nop - test: cvxif_add_nop
<<: *common_test_config <<: *common_test_config_lgcc
iterations: 0 iterations: 1
asm_tests: <path_var>/custom/cv_xif/cvxif_add_nop.S asm_tests: <path_var>/custom/cv_xif/cvxif_add_nop.S
- test: cvxif_full
<<: *common_test_config_lgcc
iterations: 1
asm_tests: <path_var>/custom/cv_xif/cvxif_full.S
- test: cvxif_multi - test: cvxif_multi
<<: *common_test_config <<: *common_test_config
iterations: 0 iterations: 0