Merge branch 'new-if' of iis-git.ee.ethz.ch:floce/ariane into new-if

This commit is contained in:
Florian Zaruba 2017-08-04 10:59:31 +02:00
commit 983e2b636f
17 changed files with 2922 additions and 2708 deletions

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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 {

View file

@ -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;

View file

@ -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 ),
.*
);

View file

@ -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
View 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

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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 ),

View file

@ -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

View file

@ -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

View file

@ -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};