mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 21:57:11 -04:00
Merge branch 'new-if' of iis-git.ee.ethz.ch:floce/ariane into new-if
This commit is contained in:
commit
983e2b636f
17 changed files with 2922 additions and 2708 deletions
|
@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Support for M Extension (mul, div and reminder)
|
||||
### Changed
|
||||
|
||||
## 0.3.0
|
||||
### Added
|
||||
- Added support for device tree in Ariane's testbench
|
||||
|
|
40
Makefile
40
Makefile
|
@ -32,25 +32,27 @@ src = $(wildcard src/*.sv) $(wildcard tb/common/*.sv)
|
|||
tbs = $(wildcard tb/*_tb.sv)
|
||||
# RISCV-tests path
|
||||
riscv-test-dir = riscv-tests/isa
|
||||
riscv-tests = rv64ui-p-add rv64ui-p-addi rv64ui-p-slli rv64ui-p-addiw rv64ui-p-addw rv64ui-p-and rv64ui-p-auipc \
|
||||
rv64ui-p-beq rv64ui-p-bge rv64ui-p-bgeu rv64ui-p-andi rv64ui-p-blt rv64ui-p-bltu rv64ui-p-bne \
|
||||
rv64ui-p-simple rv64ui-p-jal rv64ui-p-jalr rv64ui-p-or rv64ui-p-ori rv64ui-p-sub rv64ui-p-subw \
|
||||
rv64ui-p-xor rv64ui-p-xori rv64ui-p-slliw rv64ui-p-sll rv64ui-p-slli rv64ui-p-sllw \
|
||||
rv64ui-p-slt rv64ui-p-slti rv64ui-p-sltiu rv64ui-p-sltu rv64ui-p-sra rv64ui-p-srai \
|
||||
rv64ui-p-sraiw rv64ui-p-sraw rv64ui-p-srl rv64ui-p-srli rv64ui-p-srliw rv64ui-p-srlw \
|
||||
rv64ui-p-lb rv64ui-p-lbu rv64ui-p-ld rv64ui-p-lh rv64ui-p-lhu rv64ui-p-lui \
|
||||
rv64ui-p-lw rv64ui-p-lwu \
|
||||
rv64mi-p-csr rv64mi-p-mcsr rv64mi-p-illegal \
|
||||
rv64mi-p-ma_addr rv64mi-p-ma_fetch rv64mi-p-sbreak rv64mi-p-scall \
|
||||
rv64si-p-csr rv64si-p-ma_fetch rv64si-p-scall rv64si-p-wfi rv64si-p-sbreak \
|
||||
rv64si-p-dirty rv64uc-p-rvc \
|
||||
rv64ui-v-add rv64ui-v-addi rv64ui-p-slli rv64ui-v-addiw rv64ui-v-addw rv64ui-v-and rv64ui-v-auipc \
|
||||
rv64ui-v-beq rv64ui-v-bge rv64ui-v-bgeu rv64ui-v-andi rv64ui-v-blt rv64ui-v-bltu rv64ui-v-bne \
|
||||
rv64ui-v-simple rv64ui-v-jal rv64ui-v-jalr rv64ui-v-or rv64ui-v-ori rv64ui-v-sub rv64ui-v-subw \
|
||||
rv64ui-v-xor rv64ui-v-xori rv64ui-v-slliw rv64ui-v-sll rv64ui-v-slli rv64ui-v-sllw \
|
||||
rv64ui-v-slt rv64ui-v-slti rv64ui-v-sltiu rv64ui-v-sltu rv64ui-v-sra rv64ui-v-srai \
|
||||
rv64ui-v-sraiw rv64ui-v-sraw rv64ui-v-srl rv64ui-v-srli rv64ui-v-srliw rv64ui-v-srlw \
|
||||
rv64ui-v-lb rv64ui-v-lbu rv64ui-v-ld rv64ui-v-lh rv64ui-v-lhu rv64ui-v-lui
|
||||
riscv-tests = rv64ui-p-add rv64ui-p-addi rv64ui-p-slli rv64ui-p-addiw rv64ui-p-addw rv64ui-p-and rv64ui-p-auipc \
|
||||
rv64ui-p-beq rv64ui-p-bge rv64ui-p-bgeu rv64ui-p-andi rv64ui-p-blt rv64ui-p-bltu rv64ui-p-bne \
|
||||
rv64ui-p-simple rv64ui-p-jal rv64ui-p-jalr rv64ui-p-or rv64ui-p-ori rv64ui-p-sub rv64ui-p-subw \
|
||||
rv64ui-p-xor rv64ui-p-xori rv64ui-p-slliw rv64ui-p-sll rv64ui-p-slli rv64ui-p-sllw \
|
||||
rv64ui-p-slt rv64ui-p-slti rv64ui-p-sltiu rv64ui-p-sltu rv64ui-p-sra rv64ui-p-srai \
|
||||
rv64ui-p-sraiw rv64ui-p-sraw rv64ui-p-srl rv64ui-p-srli rv64ui-p-srliw rv64ui-p-srlw \
|
||||
rv64ui-p-lb rv64ui-p-lbu rv64ui-p-ld rv64ui-p-lh rv64ui-p-lhu rv64ui-p-lui rv64ui-p-lw rv64ui-p-lwu \
|
||||
rv64mi-p-csr rv64mi-p-mcsr rv64mi-p-illegal rv64mi-p-ma_addr rv64mi-p-ma_fetch rv64mi-p-sbreak rv64mi-p-scall \
|
||||
rv64si-p-csr rv64si-p-ma_fetch rv64si-p-scall rv64si-p-wfi rv64si-p-sbreak rv64si-p-dirty \
|
||||
rv64uc-p-rvc \
|
||||
rv64ui-v-add rv64ui-v-addi rv64ui-p-slli rv64ui-v-addiw rv64ui-v-addw rv64ui-v-and rv64ui-v-auipc \
|
||||
rv64ui-v-beq rv64ui-v-bge rv64ui-v-bgeu rv64ui-v-andi rv64ui-v-blt rv64ui-v-bltu rv64ui-v-bne \
|
||||
rv64ui-v-simple rv64ui-v-jal rv64ui-v-jalr rv64ui-v-or rv64ui-v-ori rv64ui-v-sub rv64ui-v-subw \
|
||||
rv64ui-v-xor rv64ui-v-xori rv64ui-v-slliw rv64ui-v-sll rv64ui-v-slli rv64ui-v-slliw \
|
||||
rv64ui-v-slt rv64ui-v-slti rv64ui-v-sltiu rv64ui-v-sltu rv64ui-v-sra rv64ui-v-srai \
|
||||
rv64ui-v-sraiw rv64ui-v-sraw rv64ui-v-srl rv64ui-v-srli rv64ui-v-srliw rv64ui-v-srlw \
|
||||
rv64ui-v-lb rv64ui-v-lbu rv64ui-v-ld rv64ui-v-lh rv64ui-v-lhu rv64ui-v-lui \
|
||||
rv64um-p-mul rv64um-p-mulh rv64um-p-mulhsu rv64um-p-mulhu rv64um-p-div rv64um-p-divu rv64um-p-rem \
|
||||
rv64um-p-remu rv64um-p-mulw rv64um-p-divw rv64um-p-divuw rv64um-p-remw rv64um-p-remuw \
|
||||
rv64um-v-mul rv64um-v-mulh rv64um-v-mulhsu rv64um-v-mulhu rv64um-v-div rv64um-v-divu rv64um-v-rem \
|
||||
rv64um-v-remu rv64um-v-mulw rv64um-v-divw rv64um-v-divuw rv64um-v-remw rv64um-v-remuw
|
||||
|
||||
# failed test directory
|
||||
failed-tests = $(wildcard failedtests/*.S)
|
||||
|
|
|
@ -100,5 +100,12 @@ Check out the [contribution guide](CONTRIBUTING.md)
|
|||
| csr | :white_check_mark: | dirty | :white_check_mark: | ma_fetch | :white_check_mark: |
|
||||
| sbreak | :white_check_mark: | scall | :white_check_mark: | wfi | :white_check_mark: |
|
||||
|
||||
## Multiplication Instructions
|
||||
|
||||
|
||||
| **Test Name** | **P/V** | **Test Name** | **P/V** | **Test Name** | **P/V** |
|
||||
|---------------|---------------------------------------|---------------|---------------------------------------|---------------|---------------------------------------|
|
||||
| mulw | :white_check_mark: :white_check_mark: | remuw | :white_check_mark: :white_check_mark: | mulhu | :white_check_mark: :white_check_mark: |
|
||||
| divw | :white_check_mark: :white_check_mark: | mul | :white_check_mark: :white_check_mark: | div | :white_check_mark: :white_check_mark: |
|
||||
| divuw | :white_check_mark: :white_check_mark: | mulh | :white_check_mark: :white_check_mark: | divu | :white_check_mark: :white_check_mark: |
|
||||
| remw | :white_check_mark: :white_check_mark: | mulhsu | :white_check_mark: :white_check_mark: | rem | :white_check_mark: :white_check_mark: |
|
||||
| remu | :white_check_mark: :white_check_mark: | | | | |
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -18,7 +18,7 @@ package ariane_pkg;
|
|||
localparam NR_SB_ENTRIES = 8; // number of scoreboard entries
|
||||
localparam TRANS_ID_BITS = $clog2(NR_SB_ENTRIES); // depending on the number of scoreboard entries we need that many bits
|
||||
// to uniquely identify the entry in the scoreboard
|
||||
localparam NR_WB_PORTS = 4;
|
||||
localparam NR_WB_PORTS = 5;
|
||||
localparam ASID_WIDTH = 1;
|
||||
localparam BTB_ENTRIES = 8;
|
||||
localparam BITS_SATURATION_COUNTER = 2;
|
||||
|
@ -93,7 +93,11 @@ package ariane_pkg;
|
|||
// CSR functions
|
||||
MRET, SRET, ECALL, WFI, FENCE, FENCE_I, SFENCE_VMA, CSR_WRITE, CSR_READ, CSR_SET, CSR_CLEAR,
|
||||
// LSU functions
|
||||
LD, SD, LW, LWU, SW, LH, LHU, SH, LB, SB, LBU
|
||||
LD, SD, LW, LWU, SW, LH, LHU, SH, LB, SB, LBU,
|
||||
// Multiplications
|
||||
MUL, MULH, MULHU, MULHSU, MULW,
|
||||
// Divisions
|
||||
DIV, DIVU, DIVW, DIVUW, REM, REMU, REMW, REMUW
|
||||
} fu_op;
|
||||
|
||||
typedef struct packed {
|
||||
|
|
|
@ -36,8 +36,8 @@ module alu
|
|||
output logic alu_ready_o,
|
||||
output logic [TRANS_ID_BITS-1:0] alu_trans_id_o
|
||||
);
|
||||
// ALU is a single cycle instructions, hence it is always ready
|
||||
|
||||
// ALU is a single cycle instructions, hence it is always ready
|
||||
assign alu_ready_o = 1'b1;
|
||||
assign alu_valid_o = alu_valid_i;
|
||||
assign alu_trans_id_o = trans_id_i;
|
||||
|
|
|
@ -172,6 +172,9 @@ module ariane
|
|||
// MULT
|
||||
logic mult_ready_ex_id;
|
||||
logic mult_valid_id_ex;
|
||||
logic [TRANS_ID_BITS-1:0] mult_trans_id_ex_id;
|
||||
logic [63:0] mult_result_ex_id;
|
||||
logic mult_valid_ex_id;
|
||||
// CSR
|
||||
logic csr_ready_ex_id;
|
||||
logic csr_valid_id_ex;
|
||||
|
@ -380,10 +383,10 @@ module ariane
|
|||
.csr_ready_i ( csr_ready_ex_id ),
|
||||
.csr_valid_o ( csr_valid_id_ex ),
|
||||
|
||||
.trans_id_i ( {alu_trans_id_ex_id, lsu_trans_id_ex_id, branch_trans_id_ex_id, csr_trans_id_ex_id }),
|
||||
.wdata_i ( {alu_result_ex_id, lsu_result_ex_id, branch_result_ex_id, csr_result_ex_id }),
|
||||
.ex_ex_i ( {{$bits(exception){1'b0}}, lsu_exception_ex_id, branch_exception_ex_id, {$bits(exception){1'b0}} }),
|
||||
.wb_valid_i ( {alu_valid_ex_id, lsu_valid_ex_id, branch_valid_ex_id, csr_valid_ex_id }),
|
||||
.trans_id_i ( {alu_trans_id_ex_id, lsu_trans_id_ex_id, branch_trans_id_ex_id, csr_trans_id_ex_id, mult_trans_id_ex_id }),
|
||||
.wdata_i ( {alu_result_ex_id, lsu_result_ex_id, branch_result_ex_id, csr_result_ex_id, mult_result_ex_id }),
|
||||
.ex_ex_i ( {{$bits(exception){1'b0}}, lsu_exception_ex_id, branch_exception_ex_id, {$bits(exception){1'b0}}, {$bits(exception){1'b0}} }),
|
||||
.wb_valid_i ( {alu_valid_ex_id, lsu_valid_ex_id, branch_valid_ex_id, csr_valid_ex_id, mult_valid_ex_id }),
|
||||
|
||||
.waddr_a_i ( waddr_a_commit_id ),
|
||||
.wdata_a_i ( wdata_a_commit_id ),
|
||||
|
@ -462,6 +465,9 @@ module ariane
|
|||
|
||||
.mult_ready_o ( mult_ready_ex_id ),
|
||||
.mult_valid_i ( mult_valid_id_ex ),
|
||||
.mult_trans_id_o ( mult_trans_id_ex_id ),
|
||||
.mult_result_o ( mult_result_ex_id ),
|
||||
.mult_valid_o ( mult_valid_ex_id ),
|
||||
.*
|
||||
);
|
||||
|
||||
|
|
|
@ -220,22 +220,31 @@ module decoder (
|
|||
// Reg-Reg Operations
|
||||
// --------------------------
|
||||
OPCODE_OP: begin
|
||||
instruction_o.fu = ALU;
|
||||
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
|
||||
instruction_o.rs1 = instr.rtype.rs1;
|
||||
instruction_o.rs2 = instr.rtype.rs2;
|
||||
instruction_o.rd = instr.rtype.rd;
|
||||
|
||||
unique case ({instr.rtype.funct7, instr.rtype.funct3})
|
||||
{6'b00_0000, 3'b000}: instruction_o.op = ADD; // Add
|
||||
{6'b10_0000, 3'b000}: instruction_o.op = SUB; // Sub
|
||||
{6'b00_0000, 3'b010}: instruction_o.op = SLTS; // Set Lower Than
|
||||
{6'b00_0000, 3'b011}: instruction_o.op = SLTU; // Set Lower Than Unsigned
|
||||
{6'b00_0000, 3'b100}: instruction_o.op = XORL; // Xor
|
||||
{6'b00_0000, 3'b110}: instruction_o.op = ORL; // Or
|
||||
{6'b00_0000, 3'b111}: instruction_o.op = ANDL; // And
|
||||
{6'b00_0000, 3'b001}: instruction_o.op = SLL; // Shift Left Logical
|
||||
{6'b00_0000, 3'b101}: instruction_o.op = SRL; // Shift Right Logical
|
||||
{6'b10_0000, 3'b101}: instruction_o.op = SRA; // Shift Right Arithmetic
|
||||
{7'b000_0000, 3'b000}: instruction_o.op = ADD; // Add
|
||||
{7'b010_0000, 3'b000}: instruction_o.op = SUB; // Sub
|
||||
{7'b000_0000, 3'b010}: instruction_o.op = SLTS; // Set Lower Than
|
||||
{7'b000_0000, 3'b011}: instruction_o.op = SLTU; // Set Lower Than Unsigned
|
||||
{7'b000_0000, 3'b100}: instruction_o.op = XORL; // Xor
|
||||
{7'b000_0000, 3'b110}: instruction_o.op = ORL; // Or
|
||||
{7'b000_0000, 3'b111}: instruction_o.op = ANDL; // And
|
||||
{7'b000_0000, 3'b001}: instruction_o.op = SLL; // Shift Left Logical
|
||||
{7'b000_0000, 3'b101}: instruction_o.op = SRL; // Shift Right Logical
|
||||
{7'b010_0000, 3'b101}: instruction_o.op = SRA; // Shift Right Arithmetic
|
||||
// Multiplications
|
||||
{7'b000_0001, 3'b000}: instruction_o.op = MUL;
|
||||
{7'b000_0001, 3'b001}: instruction_o.op = MULH;
|
||||
{7'b000_0001, 3'b010}: instruction_o.op = MULHSU;
|
||||
{7'b000_0001, 3'b011}: instruction_o.op = MULHU;
|
||||
{7'b000_0001, 3'b100}: instruction_o.op = DIV;
|
||||
{7'b000_0001, 3'b101}: instruction_o.op = DIVU;
|
||||
{7'b000_0001, 3'b110}: instruction_o.op = REM;
|
||||
{7'b000_0001, 3'b111}: instruction_o.op = REMU;
|
||||
default: begin
|
||||
illegal_instr = 1'b1;
|
||||
end
|
||||
|
@ -246,7 +255,7 @@ module decoder (
|
|||
// 32bit Reg-Reg Operations
|
||||
// --------------------------
|
||||
OPCODE_OP32: begin
|
||||
instruction_o.fu = ALU;
|
||||
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
|
||||
instruction_o.rs1 = instr.rtype.rs1;
|
||||
instruction_o.rs2 = instr.rtype.rs2;
|
||||
instruction_o.rd = instr.rtype.rd;
|
||||
|
@ -254,12 +263,17 @@ module decoder (
|
|||
if (~instr.instr[28])
|
||||
unique case ({instr.rtype.funct7, instr.rtype.funct3})
|
||||
|
||||
{6'b00_0000, 3'b000}: instruction_o.op = ADDW; // addw
|
||||
{6'b10_0000, 3'b000}: instruction_o.op = SUBW; // subw
|
||||
{6'b00_0000, 3'b001}: instruction_o.op = SLLW; // sllw
|
||||
{6'b00_0000, 3'b101}: instruction_o.op = SRLW; // srlw
|
||||
{6'b10_0000, 3'b101}: instruction_o.op = SRAW; // sraw
|
||||
// multiplications
|
||||
{7'b000_0000, 3'b000}: instruction_o.op = ADDW; // addw
|
||||
{7'b010_0000, 3'b000}: instruction_o.op = SUBW; // subw
|
||||
{7'b000_0000, 3'b001}: instruction_o.op = SLLW; // sllw
|
||||
{7'b000_0000, 3'b101}: instruction_o.op = SRLW; // srlw
|
||||
{7'b010_0000, 3'b101}: instruction_o.op = SRAW; // sraw
|
||||
// Multiplications
|
||||
{7'b000_0001, 3'b000}: instruction_o.op = MULW;
|
||||
{7'b000_0001, 3'b100}: instruction_o.op = DIVW;
|
||||
{7'b000_0001, 3'b101}: instruction_o.op = DIVUW;
|
||||
{7'b000_0001, 3'b110}: instruction_o.op = REMW;
|
||||
{7'b000_0001, 3'b111}: instruction_o.op = REMUW;
|
||||
|
||||
default: illegal_instr = 1'b1;
|
||||
endcase
|
||||
|
|
27
src/div.sv
Normal file
27
src/div.sv
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Author:
|
||||
//
|
||||
// Date: 25.07.2017
|
||||
// Description: Ariane Divider
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
//
|
||||
module div (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni // Asynchronous reset active low
|
||||
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -63,7 +63,6 @@ module ex_stage #(
|
|||
output logic lsu_commit_ready_o, // commit queue is ready to accept another commit request
|
||||
output exception lsu_exception_o,
|
||||
output logic no_st_pending_o,
|
||||
|
||||
// CSR
|
||||
output logic csr_ready_o,
|
||||
input logic csr_valid_i,
|
||||
|
@ -72,7 +71,14 @@ module ex_stage #(
|
|||
output logic csr_valid_o,
|
||||
output logic [11:0] csr_addr_o,
|
||||
input logic csr_commit_i,
|
||||
// memory management
|
||||
// MULT
|
||||
output logic mult_ready_o, // FU is ready
|
||||
input logic mult_valid_i, // Output is valid
|
||||
output logic [TRANS_ID_BITS-1:0] mult_trans_id_o,
|
||||
output logic [63:0] mult_result_o,
|
||||
output logic mult_valid_o,
|
||||
|
||||
// Memory Management
|
||||
input logic enable_translation_i,
|
||||
input logic en_ld_st_translation_i,
|
||||
input logic flush_tlb_i,
|
||||
|
@ -106,11 +112,7 @@ module ex_stage #(
|
|||
output logic data_if_tag_valid_o,
|
||||
input logic data_if_data_gnt_i,
|
||||
input logic data_if_data_rvalid_i,
|
||||
input logic [63:0] data_if_data_rdata_i,
|
||||
|
||||
// MULT
|
||||
output logic mult_ready_o, // FU is ready
|
||||
input logic mult_valid_i // Output is valid
|
||||
input logic [63:0] data_if_data_rdata_i
|
||||
);
|
||||
|
||||
// -----
|
||||
|
@ -125,14 +127,19 @@ module ex_stage #(
|
|||
// Branch Engine
|
||||
// --------------------
|
||||
branch_unit branch_unit_i (
|
||||
.fu_valid_i ( alu_valid_i || lsu_valid_i || csr_valid_i ), // any functional unit is valid, check that there is no accidental mis-predict
|
||||
.fu_valid_i ( alu_valid_i || lsu_valid_i || csr_valid_i || mult_valid_i), // any functional unit is valid, check that there is no accidental mis-predict
|
||||
.*
|
||||
);
|
||||
|
||||
// ----------------
|
||||
// Multiplication
|
||||
// ----------------
|
||||
// TODO
|
||||
`ifndef SYNTHESIS
|
||||
mult mult_i (
|
||||
.result_o ( mult_result_o ),
|
||||
.*
|
||||
);
|
||||
`endif
|
||||
|
||||
// ----------------
|
||||
// Load-Store Unit
|
||||
|
@ -153,4 +160,4 @@ module ex_stage #(
|
|||
);
|
||||
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
|
|
|
@ -150,11 +150,14 @@ module if_stage (
|
|||
WAIT_ABORTED: begin
|
||||
// abort the current rvalid, we don't want it anymore
|
||||
fifo_valid = 1'b0;
|
||||
// we've got a new fetch here, the fetch fifo is for sure empty as we just flushed it, but we still need to
|
||||
// wait for the queue to be emptied
|
||||
// we've got a new fetch here, the fetch FIFO is for sure empty as we just flushed it, but we still need to
|
||||
// wait for the address queue to be emptied
|
||||
if (fetch_valid_i && empty) begin
|
||||
instr_req_o = 1'b1;
|
||||
NS = WAIT_GNT;
|
||||
// re-do the request
|
||||
if (instr_gnt_i)
|
||||
NS = WAIT_RVALID;
|
||||
else
|
||||
NS = WAIT_GNT;
|
||||
end else if (fetch_valid_i) // the fetch is valid but the queue is not empty wait for it
|
||||
NS = WAIT_ABORTED_REQUEST;
|
||||
else if (empty) // the fetch is not valid and the queue is empty we are back to normal operation
|
||||
|
@ -168,8 +171,8 @@ module if_stage (
|
|||
// save request data
|
||||
branchpredict_n = branchpredict_q;
|
||||
instr_addr_n = instr_addr_q;
|
||||
// Here we wait for the queue to be empty, we do not make any new requests
|
||||
if (empty)
|
||||
// here we wait for the queue to be empty, we do not make any new requests
|
||||
if (empty) // do the new request
|
||||
NS = WAIT_GNT;
|
||||
end
|
||||
endcase
|
||||
|
@ -178,7 +181,9 @@ module if_stage (
|
|||
// -------------
|
||||
if (flush_i) begin
|
||||
// if the address queue is empty this case is simple: just go back to idle
|
||||
if (empty)
|
||||
// also if there is just a single element in the queue and we are commiting we can skip
|
||||
// waiting for all rvalids as the queue will be empty in the next cycle anyway
|
||||
if (empty && !(instr_req_o && instr_gnt_i))
|
||||
NS = IDLE;
|
||||
// if it wasn't empty we need to wait for all outstanding rvalids until we can make any further requests
|
||||
else
|
||||
|
@ -196,7 +201,7 @@ module if_stage (
|
|||
.flush_i ( 1'b0 ), // do not flush, we need to keep track of all outstanding rvalids
|
||||
.full_o ( full ), // the address buffer is full
|
||||
.empty_o ( empty ), // ...or empty
|
||||
.single_element_o ( ), // isn't needed here
|
||||
.single_element_o ( single_element ), // just a single element in the queue
|
||||
.data_i ( push_data ),
|
||||
.push_i ( instr_gnt_i ), // if we got a grant push the address and data
|
||||
.data_o ( pop_data ), // data we send to the fetch_fifo, along with the instr data which comes from memory
|
||||
|
|
154
src/mult.sv
154
src/mult.sv
|
@ -0,0 +1,154 @@
|
|||
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
// Author: Pasquale Davide Schiavone <pschiavo@iis.ee.ethz.ch>
|
||||
//
|
||||
// Date: 05.06.2017
|
||||
// Description: Ariane Multiplier
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
//
|
||||
|
||||
import ariane_pkg::*;
|
||||
|
||||
module mult
|
||||
(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic [TRANS_ID_BITS-1:0] trans_id_i,
|
||||
input logic mult_valid_i,
|
||||
input fu_op operator_i,
|
||||
input logic [63:0] operand_a_i,
|
||||
input logic [63:0] operand_b_i,
|
||||
output logic [63:0] result_o,
|
||||
output logic mult_valid_o,
|
||||
output logic mult_ready_o,
|
||||
output logic [TRANS_ID_BITS-1:0] mult_trans_id_o
|
||||
);
|
||||
|
||||
// ----------------
|
||||
// Mock Multiplier
|
||||
// ----------------
|
||||
`ifndef SYNTHESIS
|
||||
|
||||
function automatic logic [63:0] sign_extend (logic [31:0] operand);
|
||||
return {{32{operand[31]}}, operand[31:0]};
|
||||
endfunction
|
||||
|
||||
assign mult_valid_o = mult_valid_i;
|
||||
assign mult_trans_id_o = trans_id_i;
|
||||
assign mult_ready_o = 1'b1;
|
||||
|
||||
// sign extend operand a and b
|
||||
logic sign_a, sign_b;
|
||||
logic [127:0] mult_result;
|
||||
logic [63:0] mult_result_w;
|
||||
|
||||
assign mult_result = $signed({operand_a_i[63] & sign_a, operand_a_i}) * $signed({operand_b_i[63] & sign_b, operand_b_i});
|
||||
assign mult_result_w = $signed({operand_a_i[31] & sign_a, operand_a_i[31:0]}) * $signed({operand_b_i[31] & sign_b, operand_b_i[31:0]});
|
||||
|
||||
always_comb begin : mul_div
|
||||
|
||||
// perform multiplication
|
||||
|
||||
result_o = '0;
|
||||
sign_a = 1'b0;
|
||||
sign_b = 1'b0;
|
||||
|
||||
case (operator_i)
|
||||
// MUL performs an XLEN-bit×XLEN-bit multiplication and places the lower XLEN bits in the destination register
|
||||
MUL:
|
||||
result_o = mult_result[63:0];
|
||||
|
||||
MULH: begin
|
||||
sign_a = 1'b1;
|
||||
sign_b = 1'b1;
|
||||
result_o = mult_result[127:64];
|
||||
end
|
||||
|
||||
MULHU:
|
||||
result_o = mult_result[127:64];
|
||||
|
||||
MULHSU: begin
|
||||
sign_a = 1'b1;
|
||||
result_o = mult_result[127:64];
|
||||
end
|
||||
|
||||
MULW:
|
||||
result_o = sign_extend(mult_result_w[31:0]);
|
||||
|
||||
// Divisions
|
||||
DIV: begin
|
||||
result_o = $signed(operand_a_i) / $signed(operand_b_i);
|
||||
// division by zero
|
||||
// set all bits
|
||||
if (operand_b_i == '0)
|
||||
result_o = -1;
|
||||
end
|
||||
|
||||
DIVU: begin
|
||||
result_o = operand_a_i / operand_b_i;
|
||||
// division by zero
|
||||
// set all bits
|
||||
if (operand_b_i == '0)
|
||||
result_o = -1;
|
||||
end
|
||||
|
||||
DIVW: begin
|
||||
result_o = sign_extend($signed(operand_a_i[31:0]) / $signed(operand_b_i[31:0]));
|
||||
// division by zero
|
||||
// set all bits
|
||||
if (operand_b_i == '0)
|
||||
result_o = -1;
|
||||
end
|
||||
|
||||
DIVUW: begin
|
||||
result_o = sign_extend(operand_a_i[31:0] / operand_b_i[31:0]);
|
||||
// division by zero
|
||||
// set all bits
|
||||
if (operand_b_i == '0)
|
||||
result_o = -1;
|
||||
end
|
||||
|
||||
REM: begin
|
||||
result_o = $signed(operand_a_i) % $signed(operand_b_i);
|
||||
// division by zero
|
||||
if (operand_b_i == '0)
|
||||
result_o = operand_a_i;
|
||||
end
|
||||
|
||||
REMU: begin
|
||||
result_o = operand_a_i % operand_b_i;
|
||||
// division by zero
|
||||
if (operand_b_i == '0)
|
||||
result_o = operand_a_i;
|
||||
end
|
||||
|
||||
REMW: begin
|
||||
result_o = sign_extend($signed(operand_a_i[31:0]) % $signed(operand_b_i[31:0]));
|
||||
// division by zero
|
||||
if (operand_b_i == '0)
|
||||
result_o = operand_a_i;
|
||||
end
|
||||
|
||||
REMUW: begin
|
||||
result_o = sign_extend(operand_a_i[31:0] % operand_b_i[31:0]);
|
||||
// division by zero
|
||||
if (operand_b_i == '0)
|
||||
result_o = operand_a_i;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
`endif
|
||||
endmodule
|
46
src/multw.sv
Normal file
46
src/multw.sv
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Author: Pasquale Davide Schiavone <pschiavo@iis.ee.ethz.ch>
|
||||
//
|
||||
// Date: 05.06.2017
|
||||
// Description: Ariane MULW
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
//
|
||||
|
||||
import ariane_pkg::*;
|
||||
|
||||
module multw
|
||||
(
|
||||
input logic [TRANS_ID_BITS-1:0] trans_id_i,
|
||||
input logic mulw_valid_i,
|
||||
input logic [63:0] operand_a_i,
|
||||
input logic [63:0] operand_b_i,
|
||||
output logic [63:0] result_o,
|
||||
output logic mulw_valid_o,
|
||||
output logic mulw_ready_o,
|
||||
output logic [TRANS_ID_BITS-1:0] mulw_trans_id_o
|
||||
);
|
||||
// MULW is a single cycle instructions, hence it is always ready
|
||||
|
||||
assign mulw_ready_o = 1'b1;
|
||||
assign mulw_valid_o = mulw_valid_i;
|
||||
assign mulw_trans_id_o = trans_id_i;
|
||||
|
||||
logic signed [63:0] multw_result;
|
||||
|
||||
assign multw_result = $signed(operand_a_i[31:0])*$signed(operand_b_i[31:0]);
|
||||
assign result_o = $signed(multw_result[31:0]);
|
||||
|
||||
endmodule
|
|
@ -51,7 +51,7 @@ module pcgen_stage (
|
|||
logic set_pc_n, set_pc_q;
|
||||
branchpredict_sbe branch_predict_btb;
|
||||
// branch-predict input register -> this path is critical
|
||||
branchpredict resolved_branch_q;
|
||||
branchpredict resolved_branch_q;
|
||||
|
||||
btb #(
|
||||
.NR_ENTRIES ( BTB_ENTRIES ),
|
||||
|
|
|
@ -93,6 +93,7 @@ module store_buffer (
|
|||
speculative_status_cnt_n = speculative_status_cnt_q;
|
||||
speculative_read_pointer_n = speculative_read_pointer_q;
|
||||
speculative_write_pointer_n = speculative_write_pointer_q;
|
||||
speculative_queue_n = speculative_queue_q;
|
||||
// LSU interface
|
||||
// we are ready to accept a new entry and the input data is valid
|
||||
if (valid_i) begin
|
||||
|
|
|
@ -149,12 +149,14 @@ class instruction_trace_item;
|
|||
INSTR_SRA: s = this.printRInstr("sra");
|
||||
INSTR_OR: s = this.printRInstr("or");
|
||||
INSTR_AND: s = this.printRInstr("and");
|
||||
INSTR_MUL: s = this.printMulInstr(1'b0);
|
||||
// OP32
|
||||
INSTR_ADDW: s = this.printRInstr("addw");
|
||||
INSTR_SUBW: s = this.printRInstr("subw");
|
||||
INSTR_SLLW: s = this.printRInstr("sllw");
|
||||
INSTR_SRLW: s = this.printRInstr("srlw");
|
||||
INSTR_SRAW: s = this.printRInstr("sraw");
|
||||
INSTR_MULW: s = this.printMulInstr(1'b1);
|
||||
// FENCE
|
||||
INSTR_FENCE: s = this.printMnemonic("fence");
|
||||
INSTR_FENCEI: s = this.printMnemonic("fence.i");
|
||||
|
@ -354,47 +356,24 @@ class instruction_trace_item;
|
|||
|
||||
endfunction // printSInstr
|
||||
|
||||
function string printMulInstr();
|
||||
// string mnemonic;
|
||||
// string str_suf;
|
||||
// string str_imm;
|
||||
// string str_asm;
|
||||
// begin
|
||||
function string printMulInstr(logic is_op32);
|
||||
string s = "";
|
||||
|
||||
// // always read rs1 and rs2 and write rd
|
||||
// regs_read.push_back('{rs1, rs1_value});
|
||||
// regs_read.push_back('{rs2, rs2_value});
|
||||
// regs_write.push_back('{rd, 'x});
|
||||
case (this.instr[14:12])
|
||||
3'b000: s = "mul";
|
||||
3'b001: s = "mulh";
|
||||
3'b010: s = "mulhsu";
|
||||
3'b011: s = "mulhu";
|
||||
3'b100: s = "div";
|
||||
3'b101: s = "divu";
|
||||
3'b110: s = "rem";
|
||||
3'b111: s = "remu";
|
||||
endcase
|
||||
// if it is a 32 bit instruction concatenate a w on it
|
||||
if (is_op32)
|
||||
s = {s, "w"};
|
||||
|
||||
// if (instr[12])
|
||||
// regs_read.push_back('{rd, rs3_value});
|
||||
return this.printRInstr(s);
|
||||
|
||||
// case ({instr[31:30], instr[14]})
|
||||
// 3'b000: str_suf = "u";
|
||||
// 3'b001: str_suf = "uR";
|
||||
// 3'b010: str_suf = "hhu";
|
||||
// 3'b011: str_suf = "hhuR";
|
||||
// 3'b100: str_suf = "s";
|
||||
// 3'b101: str_suf = "sR";
|
||||
// 3'b110: str_suf = "hhs";
|
||||
// 3'b111: str_suf = "hhsR";
|
||||
// endcase
|
||||
|
||||
// if (instr[12])
|
||||
// mnemonic = "p.mac";
|
||||
// else
|
||||
// mnemonic = "p.mul";
|
||||
|
||||
// if (imm_s3_type[4:0] != 5'b00000)
|
||||
// str_asm = $sformatf("%s%sN", mnemonic, str_suf);
|
||||
// else
|
||||
// str_asm = $sformatf("%s%s", mnemonic, str_suf);
|
||||
|
||||
// if (instr[29:25] != 5'b00000)
|
||||
// str = $sformatf("%-16s x%0d, x%0d, x%0d, %0d", str_asm, rd, rs1, rs2, $unsigned(imm_s3_type[4:0]));
|
||||
// else
|
||||
// str = $sformatf("%-16s x%0d, x%0d, x%0d", str_asm, rd, rs1, rs2);
|
||||
// end
|
||||
return "";
|
||||
endfunction
|
||||
endclass
|
||||
|
|
|
@ -63,6 +63,7 @@ parameter INSTR_SRL = { 7'b0000000, 10'b?, 3'b101, 5'b?, OPCODE_OP };
|
|||
parameter INSTR_SRA = { 7'b0100000, 10'b?, 3'b101, 5'b?, OPCODE_OP };
|
||||
parameter INSTR_OR = { 7'b0000000, 10'b?, 3'b110, 5'b?, OPCODE_OP };
|
||||
parameter INSTR_AND = { 7'b0000000, 10'b?, 3'b111, 5'b?, OPCODE_OP };
|
||||
parameter INSTR_MUL = { 7'b0000001, 10'b?, 3'b???, 5'b?, OPCODE_OP };
|
||||
|
||||
// OP32
|
||||
parameter INSTR_ADDW = { 7'b0000000, 10'b?, 3'b000, 5'b?, OPCODE_OP32 };
|
||||
|
@ -70,6 +71,7 @@ parameter INSTR_SUBW = { 7'b0100000, 10'b?, 3'b000, 5'b?, OPCODE_OP32 };
|
|||
parameter INSTR_SLLW = { 7'b0000000, 10'b?, 3'b001, 5'b?, OPCODE_OP32 };
|
||||
parameter INSTR_SRLW = { 7'b0000000, 10'b?, 3'b101, 5'b?, OPCODE_OP32 };
|
||||
parameter INSTR_SRAW = { 7'b0100000, 10'b?, 3'b101, 5'b?, OPCODE_OP32 };
|
||||
parameter INSTR_MULW = { 7'b0000001, 10'b?, 3'b???, 5'b?, OPCODE_OP32 };
|
||||
|
||||
// FENCE
|
||||
parameter INSTR_FENCE = { 4'b0, 8'b?, 13'b0, OPCODE_FENCE };
|
||||
|
@ -106,4 +108,4 @@ parameter INSTR_REMU = { 7'b0000001, 10'b?, 3'b111, 5'b?, OPCODE_OP };
|
|||
|
||||
// Load/Stores
|
||||
parameter INSTR_LOAD = {25'b?, OPCODE_LOAD};
|
||||
parameter INSTR_STORE = {25'b?, OPCODE_STORE};
|
||||
parameter INSTR_STORE = {25'b?, OPCODE_STORE};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue