Commit 54104d93 authored by Tristan Gingold's avatar Tristan Gingold

Merge branch 'proposed_master'

parents 9016844b fa17e819
......@@ -11,4 +11,6 @@ files = [ "urv_cpu.v",
"urv_timer.v",
"urv_exceptions.v",
"urv_iram.v",
"xurv_core.vhd" ];
"urv_ecc.v",
"xurv_core.vhd",
"urv_pkg.vhd" ]
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: na
--
-- description: uRV configuration
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
// Platform definition. Currently supported ones are:
// SPARTAN6 - Xilinx Spartan-6 FPGA
// GENERIC - Generic, HW-independent
`define URV_PLATFORM_SPARTAN6 1
`define URV_PLATFORM_GENERIC 1
//`define URV_PLATFORM_SPARTAN6 1
//`define URV_PLATFORM_ALTERA 1
This diff is collapsed.
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_csr
--
-- description: uRV CSR
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -39,7 +44,7 @@ module urv_csr
input [31:0] d_rs1_i,
output reg [31:0] x_rd_o,
output [31:0] x_rd_o,
input [39:0] csr_time_i,
input [39:0] csr_cycles_i,
......@@ -52,11 +57,18 @@ module urv_csr
input [31:0] csr_mip_i,
input [31:0] csr_mie_i,
input [31:0] csr_mepc_i,
input [31:0] csr_mcause_i
input [31:0] csr_mcause_i,
// Debug mailboxes
input [31:0] dbg_mbx_data_i,
input dbg_mbx_write_i,
output [31:0] dbg_mbx_data_o
);
parameter g_with_hw_debug = 0;
reg [31:0] csr_mscratch;
reg [31:0] mbx_data;
reg [31:0] csr_in1;
reg [31:0] csr_in2;
......@@ -75,11 +87,12 @@ module urv_csr
`CSR_ID_MCAUSE: csr_in1 <= csr_mcause_i;
`CSR_ID_MIP: csr_in1 <= csr_mip_i;
`CSR_ID_MIE: csr_in1 <= csr_mie_i;
default: csr_in1 <= 32'hx;
`CSR_ID_DBGMBX: csr_in1 <= g_with_hw_debug ? mbx_data : 32'h0;
`CSR_ID_MIMPID: csr_in1 <= 32'h20190131;
default: csr_in1 <= 32'h0;
endcase // case (d_csr_sel_i)
always@*
x_rd_o <= csr_in1;
assign x_rd_o = csr_in1;
genvar i;
......@@ -95,8 +108,6 @@ module urv_csr
endcase // case (d_fun_i)
generate
for (i=0;i<32;i=i+1)
begin : gen_csr_bits
......@@ -115,28 +126,31 @@ module urv_csr
csr_out[i] <= 32'hx;
endcase // case (d_csr_op_i)
end // for (i=0;i<32;i=i+1)
endgenerate
always@(posedge clk_i)
if(rst_i)
begin
csr_mscratch <= 0;
else if(!x_stall_i && !x_kill_i && d_is_csr_i)
mbx_data <= 0;
end
else
begin
if (dbg_mbx_write_i && g_with_hw_debug)
mbx_data <= dbg_mbx_data_i;
if(!x_stall_i && !x_kill_i && d_is_csr_i)
case (d_csr_sel_i)
`CSR_ID_MSCRATCH:
csr_mscratch <= csr_out;
`CSR_ID_DBGMBX:
if(g_with_hw_debug)
mbx_data <= csr_out;
endcase // case (d_csr_sel_i)
end // else: !if(rst_i)
assign dbg_mbx_data_o = mbx_data;
assign x_csr_write_value_o = csr_out;
endmodule
......@@ -187,5 +187,3 @@ module urv_debug
end
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_decode
--
-- description: uRV CPU: instruction decode stage
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -49,32 +54,38 @@ module urv_decode
output [4:0] x_rs1_o,
output [4:0] x_rs2_o,
output [4:0] x_rd_o,
output reg [4:0] x_shamt_o,
output reg [2:0] x_fun_o,
output [4:0] x_opcode_o,
output reg x_shifter_sign_o,
output reg x_is_signed_compare_o,
output reg x_is_signed_alu_op_o,
output reg x_is_add_o,
output x_is_shift_o,
output reg x_is_load_o,
output reg x_is_store_o,
output reg x_is_undef_o,
output reg x_is_write_ecc_o,
output reg x_is_fix_ecc_o,
output reg [2:0] x_rd_source_o,
output x_rd_write_o,
output reg [11:0] x_csr_sel_o,
output reg [4:0] x_csr_imm_o,
output reg x_is_csr_o,
output reg x_is_eret_o,
output reg x_is_mret_o,
output reg x_is_ebreak_o,
output reg [31:0] x_imm_o,
output reg [31:0] x_alu_op1_o,
output reg [31:0] x_alu_op2_o,
output reg x_use_op1_o,
output reg x_use_op2_o,
output reg [1:0] x_op1_sel_o,
output reg [1:0] x_op2_sel_o
output reg x_use_rs1_o,
output reg x_use_rs2_o,
output reg x_is_divide_o,
output reg x_is_multiply_o
);
parameter g_with_hw_div = 0;
parameter g_with_hw_mul = 0;
parameter g_with_hw_debug = 0;
wire [4:0] f_rs1 = f_ir_i[19:15];
wire [4:0] f_rs2 = f_ir_i[24:20];
wire [4:0] f_rd = f_ir_i[11:7];
......@@ -102,13 +113,11 @@ module urv_decode
reg load_hazard;
// attempt to reuse ALU for jump address generation
wire d_is_shift = (d_fun == `FUNC_SL || d_fun == `FUNC_SR) &&
wire d_is_shift = !f_ir_i[25] && (d_fun == `FUNC_SL || d_fun == `FUNC_SR) &&
(d_opcode == `OPC_OP || d_opcode == `OPC_OP_IMM );
reg x_is_mul;
wire d_is_mul = (f_ir_i[25] && d_fun == `FUNC_MUL);
wire d_is_mul = (f_ir_i[25] && (d_fun == `FUNC_MUL || d_fun == `FUNC_MULH || d_fun == `FUNC_MULHU || d_fun == `FUNC_MULHSU) );
// hazzard detect combinatorial logic
always@*
......@@ -118,28 +127,26 @@ module urv_decode
`OPC_LOAD:
load_hazard <= 1;
`OPC_OP:
// 2 cycles instructions
load_hazard <= x_is_shift | x_is_mul;
`OPC_OP_IMM:
// 2 cycles instructions
load_hazard <= x_is_shift;
default:
load_hazard <= 0;
endcase // case (x_opcode)
end else
end
else
load_hazard <= 0;
reg inserting_nop;
// bubble insertion following a hazzard
// bubble insertion following a hazard (only 1 bubble).
always@(posedge clk_i)
if(rst_i)
inserting_nop <= 0;
else if (!d_stall_i)
begin
if (inserting_nop)
inserting_nop <= 0;
else
inserting_nop <= load_hazard;
end
inserting_nop <= load_hazard && !inserting_nop;
assign d_stall_req_o = load_hazard && !inserting_nop;
......@@ -151,7 +158,9 @@ module urv_decode
begin
x_pc_o <= 0;
x_valid <= 0;
end else if(!d_stall_i) begin
end
else if(!d_stall_i)
begin
x_pc_o <= f_pc_i;
if (load_hazard && !inserting_nop)
......@@ -163,11 +172,10 @@ module urv_decode
x_rs2 <= f_rs2;
x_rd <= f_rd;
x_opcode <= d_opcode;
x_shamt_o <= f_ir_i[24:20];
end
// ALU function decoding
// attempt to reuse ALU for jump address generation
always@(posedge clk_i)
if(!d_stall_i)
case (d_opcode)
......@@ -261,6 +269,31 @@ module urv_decode
end // if (!d_stall_i)
always@(posedge clk_i)
if(!d_stall_i)
case (d_opcode)
`OPC_JALR, `OPC_LOAD, `OPC_OP_IMM:
begin
x_use_rs1_o <= 1'b1;
x_use_rs2_o <= 1'b0;
end
`OPC_STORE, `OPC_BRANCH, `OPC_OP, `OPC_CUST2:
begin
x_use_rs1_o <= 1'b1;
x_use_rs2_o <= 1'b1;
end
`OPC_SYSTEM:
begin
x_use_rs1_o <= d_fun[2] == 1'b0 && d_fun[1:0] != 2'b0;
x_use_rs2_o <= 1'b0;
end
default:
begin
x_use_rs1_o <= 1'b0;
x_use_rs2_o <= 1'b0;
end
endcase
wire d_rd_nonzero = (f_rd != 0);
// misc decoding
......@@ -269,10 +302,13 @@ module urv_decode
begin
x_is_shift <= d_is_shift;
x_is_load_o <= ( d_opcode == `OPC_LOAD && !load_hazard) ? 1'b1 : 1'b0;
x_is_store_o <= ( d_opcode == `OPC_STORE && !load_hazard) ? 1'b1 : 1'b0;
x_is_load_o <= d_opcode == `OPC_LOAD && !load_hazard;
x_is_store_o <= d_opcode == `OPC_STORE && !load_hazard;
x_is_mul <= d_is_mul && g_with_hw_mul;
x_is_mul <= d_is_mul;
x_is_write_ecc_o <= d_opcode == `OPC_CUST2 && d_fun == `FUNC_WRECC;
x_is_fix_ecc_o <= d_opcode == `OPC_CUST2 && d_fun == `FUNC_FIXECC;
case (d_opcode)
`OPC_BRANCH:
......@@ -283,24 +319,73 @@ module urv_decode
case (d_opcode)
`OPC_OP:
x_is_add_o <= ~f_ir_i[30] && !(d_fun == `FUNC_SLT || d_fun == `FUNC_SLTU);
x_is_add_o <= ~f_ir_i[30];
`OPC_OP_IMM:
x_is_add_o <= !(d_fun == `FUNC_SLT || d_fun == `FUNC_SLTU);
x_is_add_o <= 1;
`OPC_BRANCH:
x_is_add_o <= 0;
default:
x_is_add_o <= 1;
endcase // case (d_opcode)
// all multiply/divide instructions except MUL
x_is_undef_o <= (d_opcode == `OPC_OP && f_ir_i[25] && d_fun != `FUNC_MUL);
// all multiply/divide instructions except
if( d_opcode == `OPC_OP && f_ir_i[25] )
begin
case (d_fun)
`FUNC_MUL:
begin
x_is_multiply_o <= g_with_hw_mul != 0;
x_is_divide_o <= 0;
x_is_undef_o <= g_with_hw_mul == 0;
end
`FUNC_MULH, `FUNC_MULHU, `FUNC_MULHSU:
begin
x_is_multiply_o <= g_with_hw_mul > 1;
x_is_divide_o <= 0;
x_is_undef_o <= g_with_hw_mul <= 1;
end
`FUNC_DIV, `FUNC_DIVU, `FUNC_REM, `FUNC_REMU:
begin
x_is_multiply_o <= 0;
x_is_divide_o <= 1;
x_is_undef_o <= !g_with_hw_div;
end
default:
begin
x_is_multiply_o <= 0;
x_is_divide_o <= 0;
x_is_undef_o <= 0;
end
endcase // case (d_fun)
end else begin // if ( d_opcode == `OPC_OP && f_ir_i[25] )
x_is_multiply_o <= 0;
x_is_divide_o <= 0;
x_is_undef_o <= 0;
end // else: !if( d_opcode == `OPC_OP && f_ir_i[25] )
if(d_is_shift)
x_rd_source_o <= `RD_SOURCE_SHIFTER;
else if (d_opcode == `OPC_SYSTEM)
x_rd_source_o <= `RD_SOURCE_CSR;
else if (d_opcode == `OPC_OP && !d_fun[2] && f_ir_i[25])
else if (d_opcode == `OPC_OP && f_ir_i[25])
begin
// mul/div
if( !d_fun[2] )
begin
if( d_fun == `FUNC_MUL )
x_rd_source_o <= `RD_SOURCE_MULTIPLY;
else
x_rd_source_o <= `RD_SOURCE_MULH;
end
else
x_rd_source_o <= `RD_SOURCE_DIVIDE;
end
else
x_rd_source_o <= `RD_SOURCE_ALU;
......@@ -310,6 +395,8 @@ module urv_decode
x_rd_write <= d_rd_nonzero;
`OPC_SYSTEM:
x_rd_write <= d_rd_nonzero && (d_fun != 0); // CSR instructions write to RD
`OPC_CUST2:
x_rd_write <= 1'b1;
default:
x_rd_write <= 0;
endcase // case (d_opcode)
......@@ -323,13 +410,14 @@ module urv_decode
x_csr_imm_o <= f_ir_i[19:15];
x_csr_sel_o <= f_ir_i[31:20];
x_is_csr_o <= (d_opcode == `OPC_SYSTEM) && (d_fun != 0);
x_is_eret_o <= (d_opcode == `OPC_SYSTEM) && (d_fun == 0) && (f_ir_i [31:20] == 12'b000100000000);
x_is_mret_o <= (d_opcode == `OPC_SYSTEM) && (d_fun == 0) && (f_ir_i [31:20] == `SYS_IMM_MRET);
if(g_with_hw_debug)
x_is_ebreak_o <= (d_opcode == `OPC_SYSTEM) && (d_fun == 0) && (f_ir_i [31:20] == `SYS_IMM_EBREAK);
else
x_is_ebreak_o <= 1'b0;
end
assign x_is_shift_o = x_is_shift;
assign x_rd_write_o = x_rd_write;
endmodule // rv_decode
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: na
--
-- description: uRV definitions
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_config.v"
// opcodes (bits[6:2], bits[1:0] == 2'b11)
`define OPC_LOAD 5'b00000
`define OPC_OP_IMM 5'b00100
`define OPC_LUI 5'b01101
`define OPC_AUIPC 5'b00101
`define OPC_STORE 5'b01000
`define OPC_OP 5'b01100
`define OPC_JAL 5'b11011
`define OPC_JALR 5'b11001
`define OPC_LUI 5'b01101
`define OPC_CUST2 5'b10110
`define OPC_BRANCH 5'b11000
`define OPC_LOAD 5'b00000
`define OPC_STORE 5'b01000
`define OPC_JALR 5'b11001
`define OPC_JAL 5'b11011
`define OPC_SYSTEM 5'b11100
`define OPC_MULDIV 5'b
// funct3 for OPC_BRANCH
`define BRA_EQ 3'b000
`define BRA_NEQ 3'b001
`define BRA_LT 3'b100
......@@ -40,12 +47,14 @@
`define BRA_LTU 3'b110
`define BRA_GEU 3'b111
// funct3 for OPC_LOAD and OPC_STORE
`define LDST_B 3'b000
`define LDST_H 3'b001
`define LDST_L 3'b010
`define LDST_BU 3'b100
`define LDST_HU 3'b101
// funct3 for OPC_OP and OPC_OP_IMM
`define FUNC_ADD 3'b000
`define FUNC_SLT 3'b010
`define FUNC_SLTU 3'b011
......@@ -55,21 +64,40 @@
`define FUNC_SL 3'b001
`define FUNC_SR 3'b101
// funct3 for OPC_OP, funct7=1
`define FUNC_MUL 3'b000
`define FUNC_MULH 3'b001
`define FUNC_MULHSU 3'b010
`define FUNC_MULHU 3'b011
`define FUNC_DIV 3'b100
`define FUNC_DIVU 3'b101
`define FUNC_REM 3'b110
`define FUNC_REMU 3'b111
// funct3 for OPC_SYSTEM
`define CSR_OP_PRIV 3'b000
`define CSR_OP_CSRRW 3'b001
`define CSR_OP_CSRRS 3'b010
`define CSR_OP_CSRRC 3'b011
`define CSR_OP_CSRRWI 3'b101
`define CSR_OP_CSRRSI 3'b110
`define CSR_OP_CSRRCI 3'b111
// funct3 for OPC_CUST2
// (they use shifter functions)
`define FUNC_WRECC `FUNC_SL
`define FUNC_FIXECC `FUNC_SR
// Imm for OPC_SYSTEM, fun3 = 0
`define SYS_IMM_MRET 12'b0011000_00010
`define SYS_IMM_EBREAK 12'b0000000_00001
`define RD_SOURCE_ALU 3'b000
`define RD_SOURCE_SHIFTER 3'b010
`define RD_SOURCE_MULTIPLY 3'b001
`define RD_SOURCE_DIVIDE 3'b011
`define RD_SOURCE_DIVIDE 3'b100
`define RD_SOURCE_CSR 3'b011
`define RD_SOURCE_MULH 3'b111
`define CSR_ID_CYCLESH 12'hc80
`define CSR_ID_CYCLESL 12'hc00
......@@ -81,23 +109,30 @@
`define CSR_ID_MCAUSE 12'h342
`define CSR_ID_MIP 12'h344
`define CSR_ID_MIE 12'h304
`define CSR_ID_DBGMBX 12'h7d0
`define CSR_ID_MIMPID 12'hf13
`define CSR_OP_CSRRW 3'b001
`define CSR_OP_CSRRS 3'b010
`define CSR_OP_CSRRC 3'b011
`define CSR_OP_CSRRWI 3'b101
`define CSR_OP_CSRRSI 3'b110
`define CSR_OP_CSRRCI 3'b111
/* History for MIMPID:
0000_0000: mimpid not implemented
2019_0125: mimpid added.
2019_0131: data memory wait state.
*/
`define URV_RESET_VECTOR 32'h00000000
`define URV_TRAP_VECTOR 32'h00000040
`define EXCEPT_ILLEGAL_INSN 2
`define EXCEPT_BREAKPOINT 3
`define EXCEPT_UNALIGNED_LOAD 4
`define EXCEPT_UNALIGNED_STORE 6
`define EXCEPT_TIMER 9
`define EXCEPT_IRQ 10
`define URV_TRAP_VECTOR 32'h00000008
// Bits in mie/mip for machine mode
`define EXCEPT_TIMER 7
`define EXCEPT_IRQ 11
// Cause
`define CAUSE_ILLEGAL_INSN 2
`define CAUSE_BREAKPOINT 3
`define CAUSE_UNALIGNED_LOAD 4
`define CAUSE_UNALIGNED_STORE 6
`define CAUSE_MACHINE_TIMER 7
`define CAUSE_MACHINE_IRQ 11
`define CAUSE_ECC_ERROR 15
`define OP_SEL_BYPASS_X 0
`define OP_SEL_BYPASS_W 1
......
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_divide
--
-- description: uRV division unit
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -61,8 +66,8 @@ module urv_divide
always@*
case(state) // synthesis full_case parallel_case
0: begin alu_op1 <= 'hx; alu_op2 <= 'hx; end
1: begin alu_op1 <= 0; alu_op2 <= d_rs1_i; end
2: begin alu_op1 <= 0; alu_op2 <= d_rs2_i; end
1: begin alu_op1 <= 0; alu_op2 <= n; end
2: begin alu_op1 <= 0; alu_op2 <= d; end
35: begin alu_op1 <= 0; alu_op2 <= q; end
36: begin alu_op1 <= 0; alu_op2 <= r; end
default: begin alu_op1 <= r_next; alu_op2 <= d; end
......@@ -73,16 +78,16 @@ module urv_divide
assign alu_result = alu_sub ? {1'b0, alu_op1} - {1'b0, alu_op2} : {1'b0, alu_op1} + {1'b0, alu_op2};
wire alu_ge = ~alu_result [32];
wire start_divide = !x_stall_i && !x_kill_i && d_valid_i && d_is_divide_i;
wire alu_eq = alu_result == 0;
wire done = (is_rem ? state == 37 : state == 36 );
wire busy = ( state != 0 && !done );
wire start_divide = !x_kill_i && d_valid_i && d_is_divide_i && !busy;
assign x_stall_req_o = (start_divide || !done);
assign x_stall_req_o = (d_valid_i && d_is_divide_i && !done);
always@*
case (state) // synthesis full_case parallel_case
case (state)
1:
alu_sub <= n_sign;
2:
......@@ -95,41 +100,56 @@ module urv_divide
alu_sub <= 1;
endcase // case (state)
always@(posedge clk_i)
if(rst_i || done)
state <= 0;
else if (state != 0 || start_divide)
state <= state + 1;
reg is_div_by_zero;
always@(posedge clk_i)
case ( state ) // synthesis full_case parallel_case
case ( state )
0:
if(start_divide)
begin
is_div_by_zero <= 0;
q <= 0;
r <= 0;
is_rem <= (d_fun_i == `FUNC_REM || d_fun_i ==`FUNC_REMU);
n <= d_rs1_i;
d <= d_rs2_i;
if( d_fun_i == `FUNC_DIVU || d_fun_i == `FUNC_REMU )
begin
n_sign <= 0;
d_sign <= 0;
end else begin
n_sign <= d_rs1_i[31];
d_sign <= d_rs2_i[31];
end
end
1:
n <= alu_result[31:0];
2:
begin
d <= alu_result[31:0];
is_div_by_zero <= alu_eq && (d_fun_i == `FUNC_DIV);
end
35:
x_rd_o <= alu_result; // quotient
x_rd_o <= is_div_by_zero ? -1 : alu_result; // quotient
36:
x_rd_o <= alu_result; // remainder
default: // 3..34: 32 divider iterations
default: // 3..345 32 divider iterations
begin
q <= { q[30:0], alu_ge };
......@@ -141,4 +161,3 @@ module urv_divide
endmodule // rv_divide
/*
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_ecc
--
-- description: uRV CPU: compute ecc
--
--------------------------------------------------------------------------------
-- Copyright CERN 2022
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`timescale 1ns/1ps
module urv_ecc
(
input [31:0] dat_i,
output [6:0] ecc_o
);
assign ecc_o[0] = ^(dat_i & 32'b11000001010010000100000011111111);
assign ecc_o[1] = ^(dat_i & 32'b00100001001001001111111110010000);
assign ecc_o[2] = ^(dat_i & 32'b01101100111111110000100000001000);
assign ecc_o[3] = ^(dat_i & 32'b11111111000000011010010001000100);
assign ecc_o[4] = ^(dat_i & 32'b00010110111100001001001010100110);
assign ecc_o[5] = ^(dat_i & 32'b00010000000111110111000101100001);
assign ecc_o[6] = ^(dat_i & 32'b10001010100000100000111100011011);
endmodule // urv_ecc
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_exceptions
--
-- description: uRV exceptions unit
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -32,26 +37,24 @@ module urv_exceptions
input x_kill_i,
input d_is_csr_i,
input d_is_eret_i,
input d_is_mret_i,
input [2:0] d_fun_i,
input [4:0] d_csr_imm_i,
input [11:0] d_csr_sel_i,
input exp_irq_i,
input exp_tick_i,
input exp_breakpoint_i,
input exp_unaligned_load_i,
input exp_unaligned_store_i,
input exp_invalid_insn_i,
output exp_ei_pending_o,
output exp_ti_pending_o,
input [31:0] x_csr_write_value_i,
output reg x_exception_o,
input x_exception_i,
input [3:0] x_exception_cause_i,
input x_interrupt_i,
input [31:0] x_exception_pc_i,
output [31:0] x_exception_pc_o,
output [31:0] x_exception_vector_o,
input x_exception_taken_i,
output [31:0] csr_mstatus_o,
output [31:0] csr_mip_o,
......@@ -60,150 +63,73 @@ module urv_exceptions
output [31:0] csr_mcause_o
);
reg [31:0] csr_mepc;
reg [31:0] csr_mie;
reg csr_ie;
reg [3:0] csr_mcause;
reg csr_status_mie;
reg csr_status_mpie;
reg [3:0] csr_mcause_code;
reg csr_mcause_interrupt;
reg exception;
reg [3:0] cause;
reg [5:0] except_vec_masked;
reg exception_pending;
reg [31:0] x_exception_pc_d;
assign csr_mcause_o = {28'h0, csr_mcause};
assign csr_mcause_o = {csr_mcause_interrupt, 27'h0, csr_mcause_code};
assign csr_mepc_o = csr_mepc;
assign csr_mie_o = csr_mie;
assign csr_mstatus_o[0] = csr_ie;
assign csr_mstatus_o[31:1] = 0;
reg [31:0] csr_mip;
always@*
begin
csr_mip <= 0;
csr_mip[`EXCEPT_ILLEGAL_INSN] <= except_vec_masked[0];
csr_mip[`EXCEPT_BREAKPOINT] <= except_vec_masked[1];
csr_mip[`EXCEPT_UNALIGNED_LOAD]<= except_vec_masked[2];
csr_mip[`EXCEPT_UNALIGNED_STORE] <= except_vec_masked[3];
csr_mip[`EXCEPT_TIMER] <= except_vec_masked[4];
csr_mip[`EXCEPT_IRQ] <= except_vec_masked[5];
end
assign csr_mstatus_o[2:0] = 0;
assign csr_mstatus_o[3] = csr_status_mie;
assign csr_mstatus_o[6:4] = 0;
assign csr_mstatus_o[7] = csr_status_mpie;
assign csr_mstatus_o[31:8] = 0;
assign csr_mip_o = 0;
assign csr_mip_o = csr_mip;
always@(posedge clk_i)
if (rst_i)
except_vec_masked <= 0;
else begin
if(!x_stall_i && !x_kill_i && d_is_csr_i && d_csr_sel_i == `CSR_ID_MIP) begin
except_vec_masked[0] <= x_csr_write_value_i [`EXCEPT_ILLEGAL_INSN];
except_vec_masked[1] <= x_csr_write_value_i [`EXCEPT_BREAKPOINT];
except_vec_masked[2] <= x_csr_write_value_i [`EXCEPT_UNALIGNED_LOAD];
except_vec_masked[3] <= x_csr_write_value_i [`EXCEPT_UNALIGNED_STORE];
except_vec_masked[4] <= x_csr_write_value_i [`EXCEPT_TIMER];
except_vec_masked[5] <= x_csr_write_value_i [`EXCEPT_IRQ];
end else begin
if ( exp_invalid_insn_i )
except_vec_masked[0] <= 1'b1;
if ( exp_breakpoint_i )
except_vec_masked[1] <= 1'b1;
if ( exp_unaligned_load_i )
except_vec_masked[2] <= 1'b1;
if ( exp_unaligned_store_i )
except_vec_masked[3] <= 1'b1;
if ( exp_tick_i )
except_vec_masked[4] <= csr_mie[`EXCEPT_TIMER] & csr_ie;
if( exp_irq_i )
except_vec_masked[5] <= csr_mie[`EXCEPT_IRQ] & csr_ie;
end // else: !if(!x_stall_i && !x_kill_i && d_is_csr_i && d_csr_sel_i == `CSR_ID_MIP)
end // else: !if(rst_i)
always@*
exception <= |except_vec_masked | exp_invalid_insn_i;
assign x_exception_vector_o = 'h8;
always@*
if(exp_invalid_insn_i || except_vec_masked[0])
cause <= `EXCEPT_ILLEGAL_INSN;
else if (except_vec_masked[1])
cause <= `EXCEPT_BREAKPOINT;
else if (except_vec_masked[2])
cause <= `EXCEPT_UNALIGNED_LOAD;
else if (except_vec_masked[3])
cause <= `EXCEPT_UNALIGNED_STORE;
else if (except_vec_masked[4])
cause <= `EXCEPT_TIMER;
else
cause <= `EXCEPT_IRQ;
assign exp_ei_pending_o = exp_irq_i & csr_mie[`EXCEPT_IRQ] & csr_status_mie;
assign exp_ti_pending_o = exp_tick_i & csr_mie[`EXCEPT_TIMER] & csr_status_mie;
always@(posedge clk_i)
if(rst_i)
begin
csr_mcause_code <= 0;
csr_mcause_interrupt <= 0;
csr_mepc <= 0;
csr_mie <= 0;
csr_ie <= 0;
exception_pending <= 0;
end else if(!x_stall_i && !x_kill_i) begin
x_exception_pc_d <= x_exception_pc_i;
if ( d_is_eret_i )
exception_pending <= 0;
else if ( x_exception_taken_i )
csr_status_mie <= 0;
csr_status_mpie <= 0;
end
else
begin
if (x_exception_i)
begin
csr_mepc <= x_exception_pc_d;
csr_mcause <= cause;
exception_pending <= 1;
csr_mepc <= x_exception_pc_i;
csr_mcause_code <= x_exception_cause_i;
csr_mcause_interrupt <= x_interrupt_i;
// Mask interrupts during exceptions
csr_status_mpie <= csr_status_mie;
csr_status_mie <= 0;
end
if(d_is_csr_i) begin
if (!x_stall_i && !x_kill_i)
begin
if (d_is_csr_i)
case (d_csr_sel_i)
`CSR_ID_MSTATUS:
csr_ie <= x_csr_write_value_i[0];
csr_status_mie <= x_csr_write_value_i[3];
`CSR_ID_MEPC:
csr_mepc <= x_csr_write_value_i;
`CSR_ID_MIE:
begin
csr_mie[`EXCEPT_ILLEGAL_INSN] <= 1;
csr_mie[`EXCEPT_BREAKPOINT] <= 1;
csr_mie[`EXCEPT_UNALIGNED_LOAD] <= 1;
csr_mie[`EXCEPT_UNALIGNED_STORE] <= 1;
csr_mie[`EXCEPT_TIMER] <= x_csr_write_value_i [`EXCEPT_TIMER];
csr_mie[`EXCEPT_IRQ] <= x_csr_write_value_i [`EXCEPT_IRQ];
csr_mie[`EXCEPT_TIMER] <=
x_csr_write_value_i[`EXCEPT_TIMER];
csr_mie[`EXCEPT_IRQ] <=
x_csr_write_value_i[`EXCEPT_IRQ];
end
endcase // case (d_csr_sel_i)
end // if (d_is_csr_i)
end // if (!x_stall_i && !x_kill_i)
endcase
if (d_is_mret_i)
csr_status_mie <= csr_status_mpie;
end
end
assign x_exception_pc_o = csr_mepc;
always@(posedge clk_i)
if (rst_i)
x_exception_o <= 0;
else if (x_exception_taken_i)
x_exception_o <= 0;
else if (exception && !exception_pending)
x_exception_o <= 1;
endmodule // urv_exceptions
This diff is collapsed.
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_fetch
--
-- description: uRV CPU: instruction fetch stage
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`timescale 1ns/1ps
......@@ -27,73 +32,151 @@ module urv_fetch
input rst_i,
input f_stall_i,
input f_kill_i,
// Instruction memory
// im_rd_o is maintained as long as the instruction is needed.
output [31:0] im_addr_o,
output im_rd_o,
input [31:0] im_data_i,
input im_valid_i,
// Fetched instruction - set on the next cycle.
output reg f_valid_o,
output [31:0] f_ir_o,
output reg [31:0] f_ir_o,
output reg [31:0] f_pc_o,
output reg [31:0] f_pc_plus_4_o,
// Branch control
input [31:0] x_pc_bra_i,
input x_bra_i
input x_bra_i,
// Debug mode
input dbg_force_i,
output dbg_enabled_o,
input [31:0] dbg_insn_i,
input dbg_insn_set_i,
output dbg_insn_ready_o,
input x_dbg_toggle_i
);
parameter g_with_compressed_insns = 0;
parameter g_with_hw_debug = 0;
reg [31:0] pc;
reg [31:0] ir ,ir_prev;
reg rst_d;
reg [31:0] pc_next;
reg [31:0] pc_plus_4;
reg dbg_mode;
reg [2:0] pipeline_cnt;
wire frozen;
// Set by x_bra_i until the next instruction has been fetched.
// The instruction being fetched before the branch has to be discarded.
reg f_kill;
// Set as long as no instruction has to be fetched.
assign frozen = (f_stall_i
|| dbg_mode || dbg_force_i || pipeline_cnt != 0);
always@*
if( x_bra_i )
if (x_bra_i)
pc_next <= x_pc_bra_i;
else if (!rst_d || f_stall_i || !im_valid_i)
else if (rst_d || frozen || f_kill || !im_valid_i)
pc_next <= pc;
else
pc_next <= pc_plus_4;
pc_next <= pc + 4;
assign f_ir_o = ir;
// Start fetching the next instruction
assign im_addr_o = pc_next;
assign im_rd_o = x_bra_i || !(frozen || rst_i);
assign dbg_enabled_o = dbg_mode;
assign dbg_insn_ready_o = pipeline_cnt == 4;
always@(posedge clk_i)
if (rst_i) begin
if (rst_i)
begin
// PC = 0 at reset.
pc <= 0;
pc_plus_4 <= 4;
ir <= 0;
f_pc_o <= 0;
f_ir_o <= 0;
f_valid_o <= 0;
rst_d <= 0;
f_kill <= 0;
end else begin
rst_d <= 1;
// Allow to start in debug mode.
dbg_mode <= dbg_force_i;
if (!f_stall_i) begin
pipeline_cnt <= 0;
if(im_valid_i)
pc_plus_4 <= (x_bra_i ? x_pc_bra_i : pc_plus_4) + 4;
// The instruction won't be valid on the next cycle, as the
// instruction memory is registered.
rst_d <= 1;
end
else
begin
rst_d <= 0;
if (!f_stall_i)
begin
f_pc_o <= pc;
pc <= pc_next;
f_pc_o <= pc;
if(g_with_hw_debug
&& !dbg_mode
&& (dbg_force_i || x_dbg_toggle_i || pipeline_cnt != 0))
begin
// Enter or entering in debug mode
if(im_valid_i) begin
ir <= im_data_i;
f_valid_o <= (rst_d && !f_kill_i);
end else begin// if (i_valid_i)
// Stall until the debug mode is set (pipeline flushed).
f_valid_o <= 0;
// Ebreak enters directly in the debug mode. As it is
// considered as a branch, stages are killed.
if (pipeline_cnt == 4 || x_dbg_toggle_i)
begin
dbg_mode <= 1;
pipeline_cnt <= 0;
end
else
pipeline_cnt <= pipeline_cnt + 1'b1;
end
else if(g_with_hw_debug && dbg_mode)
begin
// In debug mode
if (x_dbg_toggle_i)
begin
// Leave debug mode immediately.
dbg_mode <= 0;
f_valid_o <= 0;
end
else
begin
// Use instruction from the debug port.
f_ir_o <= dbg_insn_i;
f_valid_o <= 1;
end
if (x_dbg_toggle_i || dbg_insn_set_i)
pipeline_cnt <= 0;
else if (pipeline_cnt != 4)
pipeline_cnt <= pipeline_cnt + 1'b1;
end
else if(im_valid_i)
begin
f_ir_o <= im_data_i;
// A branch invalidate the current instruction.
// Not valid on the first cycle
f_valid_o <= (!rst_d && !x_bra_i && !f_kill);
// The instruction has been killed.
f_kill <= 0;
end
else
begin
// If a branch has been executed, the instruction being
// fetch must not be executed. Kill it.
f_kill <= f_kill | x_bra_i;
f_valid_o <= 0;
end
end
end
end // else: !if(rst_i)
endmodule // urv_fetch
......@@ -241,8 +241,7 @@ module urv_iram
integer f, addr;
integer tmp, f, addr;
reg[31:0] data;
reg [8*20-1:0] cmd;
......@@ -268,7 +267,7 @@ module urv_iram
begin
$fscanf(f,"%s %08x %08x", cmd,addr,data);
tmp = $fscanf(f, "%s %08x %08x", cmd, addr, data);
if(cmd == "write")
begin
mem[addr % g_size][31:24] = data[31:24];
......@@ -454,4 +453,3 @@ endmodule // urv_iram
`endif // `ifdef URV_PLATFORM_ALTERA
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_multiply
--
-- description: uRV multiplication unit
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -67,9 +72,9 @@ module urv_mult18x18
.C(48'h0),
.CARRYIN(),
.D(18'b0),
.CEA(1'b0),
.CEB(1'b0),
.CEC(1'b0),
.CEA(1'b1),
.CEB(1'b1),
.CEC(1'b1),
.CECARRYIN(1'b0),
.CED(1'b0),
.CEM(~stall_i),
......@@ -90,6 +95,7 @@ module urv_mult18x18
initial force D1.OPMODE_dly = 8'd1;
// synthesis translate_on
endmodule // urv_mult18x18
`endif // `ifdef PLATFORM_SPARTAN6
......@@ -102,10 +108,10 @@ module urv_mult18x18
input stall_i,
input [17:0] x_i,
input [17:0] y_i,
input signed [17:0] x_i,
input signed [17:0] y_i,
output reg [35:0] q_o
output reg signed [35:0] q_o
);
......@@ -160,31 +166,48 @@ module urv_multiply
input clk_i,
input rst_i,
input x_stall_i,
input x_kill_i,
output x_stall_req_o,
input [31:0] d_rs1_i,
input [31:0] d_rs2_i,
input [2:0] d_fun_i,
input d_is_multiply_i,
output reg [31:0] w_rd_o
// multiply result for MUL instructions, bypassed to W-stage to achieve 1-cycle performance
// without much penalty on clock speed
output [31:0] w_rd_o,
// multiply result for MULH(S)(U) instructions. Goes to the X stage
// destination value mux.
output reg [31:0] x_rd_o
);
parameter g_with_hw_mulh = 0;
wire[17:0] xl_u = {1'b0, d_rs1_i[16:0] };
wire[17:0] xl_u = {1'b0, d_rs1_i[16:0] }; // 17 bits
wire[17:0] yl_u = {1'b0, d_rs2_i[16:0] };
wire[17:0] xl_s = {d_rs1_i[16], d_rs1_i[16:0] };
wire[17:0] yl_s = {d_rs2_i[16], d_rs2_i[16:0] };
wire[17:0] xh = { {3{d_rs1_i[31]}}, d_rs1_i[31:17] };
wire[17:0] yh = { {3{d_rs2_i[31]}}, d_rs2_i[31:17] };
wire sign_extend_xh = (d_fun_i == `FUNC_MULH || d_fun_i == `FUNC_MULHSU) ? d_rs1_i[31] : 1'b0 ;
wire sign_extend_yh = (d_fun_i == `FUNC_MULH) ? d_rs2_i[31] : 1'b0 ;
wire signed [17:0] xh = { {3{sign_extend_xh}}, d_rs1_i[31:17] }; // 15 bits
wire signed [17:0] yh = { {3{sign_extend_yh}}, d_rs2_i[31:17] };
wire signed [35:0] xh_yh;
wire signed [35:0] yl_xl, yl_xh, yh_xl;
wire mul_stall_req;
reg mul_stall_req_d0;
reg mul_stall_req_d1;
wire [35:0] yl_xl, yl_xh, yh_xl;
urv_mult18x18 mul0
(
.clk_i(clk_i),
.rst_i(rst_i),
.stall_i(x_stall_i),
.stall_i(1'b0),
.x_i(xl_u),
.y_i(yl_u),
......@@ -195,9 +218,9 @@ module urv_multiply
(
.clk_i(clk_i),
.rst_i(rst_i),
.stall_i(x_stall_i),
.stall_i(1'b0),
.x_i(xl_s),
.x_i(xl_u),
.y_i(yh),
.q_o(yh_xl)
);
......@@ -206,19 +229,69 @@ module urv_multiply
(
.clk_i(clk_i),
.rst_i(rst_i),
.stall_i(x_stall_i),
.stall_i(1'b0),
.x_i(yl_s),
.x_i(yl_u),
.y_i(xh),
.q_o(yl_xh)
);
always@*
w_rd_o <= yl_xl + {yl_xh[14:0], 17'h0} + {yh_xl[14:0], 17'h0};
generate
if (g_with_hw_mulh)
begin
endmodule // urv_multiply
urv_mult18x18 mul3
(
.clk_i(clk_i),
.rst_i(rst_i),
.stall_i(1'b0),
.x_i(yh),
.y_i(xh),
.q_o(xh_yh)
);
end
endgenerate
wire [63:0] mul_result;
wire [63:0] yl_xl_ext = yl_xl;
wire [63:0] yh_xl_ext = { {15{yh_xl[35] } }, yh_xl, 17'h0 };
wire [63:0] yl_xh_ext = { {15{yl_xh[35] } }, yl_xh, 17'h0 };
wire [63:0] yh_xh_ext = { xh_yh, 34'h0 };
generate
if (g_with_hw_mulh)
begin
assign mul_result = yl_xl_ext + yh_xl_ext + yl_xh_ext + yh_xh_ext;
assign mul_stall_req = !x_kill_i && !mul_stall_req_d1 && d_is_multiply_i && d_fun_i != `FUNC_MUL;
always@(posedge clk_i)
x_rd_o <= mul_result[63:32];
always@(posedge clk_i)
if (rst_i)
begin
mul_stall_req_d0 <= 0;
mul_stall_req_d1 <= 0;
end else begin
mul_stall_req_d0 <= mul_stall_req;
mul_stall_req_d1 <= mul_stall_req_d0;
end
end
else // no hardware multiply high
begin
assign mul_result = yl_xl + {yl_xh[14:0], 17'h0} + {yh_xl[14:0], 17'h0};
assign mul_stall_req = 1'b0;
end // else: !if(g_with_hw_mulh)
endgenerate
assign x_stall_req_o = mul_stall_req;
assign w_rd_o = mul_result[31:0];
endmodule // urv_multiply
library ieee;
use ieee.std_logic_1164.all;
package urv_pkg is
component urv_cpu is
generic (
g_timer_frequency : natural := 1000;
g_clock_frequency : natural := 100000000;
g_with_hw_div : natural := 1;
g_with_hw_mul : natural := 1;
g_with_hw_debug : natural := 0;
g_with_compressed_insns : natural := 0);
port (
clk_i : in std_logic;
rst_i : in std_logic;
irq_i : in std_logic;
-- instruction mem I/F
im_addr_o : out std_logic_vector (31 downto 0);
im_rd_o : out std_logic;
im_data_i : in std_logic_vector (31 downto 0);
im_valid_i : in std_logic;
-- data mem I/F
-- The interface is pipelined: store/load are asserted for one cycle
-- and then store_done/load_done is awaited.
dm_addr_o : out std_logic_vector (31 downto 0);
dm_data_s_o : out std_logic_vector (31 downto 0);
dm_data_l_i : in std_logic_vector (31 downto 0);
dm_data_select_o : out std_logic_vector (3 downto 0);
dm_store_o : out std_logic;
dm_load_o : out std_logic;
dm_load_done_i : in std_logic;
dm_store_done_i : in std_logic;
-- Debug I/F
-- Debug mode is entered either when dbg_force_i is set, or when the ebreak
-- instructions is executed. Debug mode is left when the ebreak instruction
-- is executed (from the dbg_insn_i port).
-- When debug mode is entered, dbg_enabled_o is set. This may not be
-- immediate. Interrupts are disabled in debug mode.
-- In debug mode, instructions are executed from dbg_insn_i.
-- As instructions are always fetched, they must be always valid. Use
-- a nop (0x13) if nothing should be executed.
dbg_force_i : in std_logic;
dbg_enabled_o : out std_logic;
dbg_insn_i : in std_logic_vector (31 downto 0);
dbg_insn_set_i : in std_logic;
dbg_insn_ready_o : out std_logic;
dbg_mbx_data_i : in std_logic_vector (31 downto 0);
dbg_mbx_write_i : in std_logic;
dbg_mbx_data_o : out std_logic_vector (31 downto 0));
end component;
end urv_pkg;
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_regfile
--
-- description: uRV CPU: register file
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -24,20 +29,22 @@
`timescale 1ns/1ps
module urv_regmem
#(
parameter g_width = 32
)
(
input clk_i,
input rst_i,
input en1_i,
input [4:0] a1_i,
output reg [31:0] q1_o,
output reg [g_width-1:0] q1_o,
input [4:0] a2_i,
input [31:0] d2_i,
input [g_width-1:0] d2_i,
input we2_i
);
reg [31:0] ram [0:31];
reg [g_width-1:0] ram [0:31];
always@(posedge clk_i)
if(en1_i)
......@@ -52,7 +59,7 @@ module urv_regmem
integer i;
for(i=0;i<32; i=i+1) begin
ram[i] = 0;
ram[i] = 32'h0;
end
end
// synthesis translate_on
......@@ -60,7 +67,10 @@ module urv_regmem
endmodule
module urv_regfile
(
#(
parameter g_with_ecc = 0
)
(
input clk_i,
input rst_i,
......@@ -74,47 +84,91 @@ module urv_regfile
output reg [31:0] x_rs1_value_o,
output reg [31:0] x_rs2_value_o,
output reg x_rs1_ecc_err_o,
output reg x_rs2_ecc_err_o,
input [4:0] w_rd_i,
input [31:0] w_rd_value_i,
input [6:0] w_rd_ecc_i,
input [1:0] w_rd_ecc_flip_i,
input w_rd_store_i,
input w_bypass_rd_write_i,
input [31:0] w_bypass_rd_value_i
);
localparam g_width = 32 + (g_with_ecc ? 7 : 0);
wire [31:0] rs1_regfile;
wire [31:0] rs2_regfile;
wire write = (w_rd_store_i && (w_rd_i != 0));
wire [g_width-1:0] w_rd_value_1;
wire [g_width-1:0] w_rd_value_2;
wire [g_width-1:0] rs1_regfile;
wire [g_width-1:0] rs2_regfile;
wire write = w_rd_store_i;
urv_regmem bank0
wire rs1_ecc_err;
wire rs2_ecc_err;
// Value to be written in the register file
wire [g_width-1:0] w_rd_value;
generate
if (g_with_ecc) begin
assign w_rd_value_1 = {w_rd_ecc_i ^ w_rd_ecc_flip_i[0], w_rd_value_i};
assign w_rd_value_2 = {w_rd_ecc_i ^ w_rd_ecc_flip_i[1], w_rd_value_i};
end
else begin
assign w_rd_value_1 = w_rd_value_i;
assign w_rd_value_2 = w_rd_value_i;
end
endgenerate
urv_regmem
#(.g_width(g_width))
bank1
(
.clk_i(clk_i),
.rst_i (rst_i ),
.en1_i(!d_stall_i),
.a1_i(rf_rs1_i),
.q1_o(rs1_regfile),
.a2_i(w_rd_i),
.d2_i(w_rd_value_i),
.d2_i(w_rd_value_1),
.we2_i (write));
urv_regmem bank1
urv_regmem
#(.g_width(g_width))
bank2
(
.clk_i(clk_i),
.rst_i (rst_i ),
.en1_i(!d_stall_i),
.a1_i(rf_rs2_i),
.q1_o(rs2_regfile),
.a2_i (w_rd_i),
.d2_i (w_rd_value_i),
.d2_i (w_rd_value_2),
.we2_i (write)
);
generate
if (g_with_ecc) begin
wire [6:0] rs1_ecc;
wire [6:0] rs2_ecc;
urv_ecc ecc_rs1
(.dat_i(rs1_regfile[31:0]),
.ecc_o(rs1_ecc));
urv_ecc ecc_rs2
(.dat_i(rs2_regfile[31:0]),
.ecc_o(rs2_ecc));
assign rs1_ecc_err = |(rs1_ecc ^ rs1_regfile[38:32]);
assign rs2_ecc_err = |(rs2_ecc ^ rs2_regfile[38:32]);
end
else begin
assign rs1_ecc_err = 1'b0;
assign rs2_ecc_err = 1'b0;
end
endgenerate
wire rs1_bypass_x = w_bypass_rd_write_i && (w_rd_i == d_rs1_i) && (w_rd_i != 0);
wire rs2_bypass_x = w_bypass_rd_write_i && (w_rd_i == d_rs2_i) && (w_rd_i != 0);
......@@ -140,22 +194,39 @@ module urv_regfile
begin
case ( {rs1_bypass_x, rs1_bypass_w } ) // synthesis parallel_case full_case
2'b10, 2'b11:
begin
x_rs1_value_o <= w_bypass_rd_value_i;
x_rs1_ecc_err_o <= 1'b0;
end
2'b01:
begin
x_rs1_value_o <= bypass_w;
x_rs1_ecc_err_o <= 1'b0;
end
default:
x_rs1_value_o <= rs1_regfile;
begin
x_rs1_value_o <= rs1_regfile[31:0];
x_rs1_ecc_err_o <= rs1_ecc_err;
end
endcase // case ( {rs1_bypass_x, rs1_bypass_w } )
case ( {rs2_bypass_x, rs2_bypass_w } ) // synthesis parallel_case full_case
2'b10, 2'b11:
begin
x_rs2_value_o <= w_bypass_rd_value_i;
x_rs2_ecc_err_o <= 1'b0;
end
2'b01:
begin
x_rs2_value_o <= bypass_w;
x_rs2_ecc_err_o <= 1'b0;
end
default:
x_rs2_value_o <= rs2_regfile;
begin
x_rs2_value_o <= rs2_regfile[31:0];
x_rs2_ecc_err_o <= rs2_ecc_err;
end
endcase // case ( {rs2_bypass_x, rs2_bypass_w } )
end // always@ *
endmodule // urv_regfile
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_shifter
--
-- description: uRV shifter unit
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -42,8 +47,7 @@ module urv_shifter
input [4:0] d_shamt_i,
input [2:0] d_fun_i,
input d_shifter_sign_i,
input d_is_shift_i
input d_shifter_sign_i
);
wire extend_sign = ((d_fun_i == `FUNC_SR) && d_shifter_sign_i) ? d_rs1_i[31] : 1'b0;
......@@ -89,4 +93,3 @@ module urv_shifter
w_rd_o <= shift_post;
endmodule // urv_shifter
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_timer
--
-- description: uRV timer unit
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- uRV - a tiny and dumb RISC-V core
-- https://www.ohwr.org/projects/urv-core
--------------------------------------------------------------------------------
--
-- unit name: urv_writeback
--
-- description: uRV CPU: instruction write-back stage
--
--------------------------------------------------------------------------------
-- Copyright CERN 2015-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
*/
`include "urv_defs.v"
......@@ -24,11 +29,13 @@
`timescale 1ns/1ps
module urv_writeback
#(
parameter g_with_ecc = 0
)
(
input clk_i,
input rst_i,
input w_stall_i,
output w_stall_req_o,
input [2:0] x_fun_i,
......@@ -45,6 +52,7 @@ module urv_writeback
input [31:0] x_shifter_rd_value_i,
input [31:0] x_multiply_rd_value_i,
input [1:0] x_rd_source_i,
input [1:0] x_ecc_flip_i,
input [31:0] dm_data_l_i,
input dm_load_done_i,
......@@ -52,6 +60,8 @@ module urv_writeback
output [31:0] rf_rd_value_o,
output [4:0] rf_rd_o,
output [6:0] rf_rd_ecc_o,
output [1:0] rf_rd_ecc_flip_o,
output rf_rd_write_o
);
......@@ -59,7 +69,6 @@ module urv_writeback
// generate load value
always@*
begin
case (x_fun_i)
`LDST_B:
case ( x_dm_addr_i [1:0] )
......@@ -80,16 +89,16 @@ module urv_writeback
endcase // case ( x_dm_addr_i [1:0] )
`LDST_H:
case ( x_dm_addr_i [1:0] )
2'b00, 2'b01: load_value <= {{16{dm_data_l_i[15]}}, dm_data_l_i[15:0] };
2'b10, 2'b11: load_value <= {{16{dm_data_l_i[31]}}, dm_data_l_i[31:16] };
case ( x_dm_addr_i [1] )
1'b0: load_value <= {{16{dm_data_l_i[15]}}, dm_data_l_i[15:0] };
1'b1: load_value <= {{16{dm_data_l_i[31]}}, dm_data_l_i[31:16] };
default: load_value <= 32'hx;
endcase // case ( x_dm_addr_i [1:0] )
`LDST_HU:
case ( x_dm_addr_i [1:0] )
2'b00, 2'b01: load_value <= {16'h0, dm_data_l_i[15:0] };
2'b10, 2'b11: load_value <= {16'h0, dm_data_l_i[31:16] };
case ( x_dm_addr_i [1] )
1'b0: load_value <= {16'h0, dm_data_l_i[15:0] };
1'b1: load_value <= {16'h0, dm_data_l_i[31:16] };
default: load_value <= 32'hx;
endcase // case ( x_dm_addr_i [1:0] )
......@@ -97,7 +106,6 @@ module urv_writeback
default: load_value <= 32'hx;
endcase // case (d_fun_i)
end // always@ *
reg rf_rd_write;
reg [31:0] rf_rd_value;
......@@ -113,13 +121,31 @@ module urv_writeback
rf_rd_value <= x_rd_value_i;
always@*
if (w_stall_i)
rf_rd_write <= 0;
else if (x_load_i && dm_load_done_i)
if (x_load_i && dm_load_done_i)
rf_rd_write <= x_valid_i;
else
rf_rd_write <= x_rd_write_i & x_valid_i;
// synthesis translate_off
always@(posedge clk_i)
if(!rst_i)
if(rf_rd_write && (^rf_rd_value === 1'hx) )
$error("Attempt to write unknown value to reg %x", x_rd_i);
// synthesis translate_on
generate
if (g_with_ecc) begin
wire [6:0] rf_rd_ecc;
urv_ecc gen_ecc
(.dat_i(rf_rd_value),
.ecc_o(rf_rd_ecc));
assign rf_rd_ecc_o = rf_rd_ecc;
assign rf_rd_ecc_flip_o = x_ecc_flip_i;
end
else
assign rf_rd_ecc_o = 6'bx;
endgenerate
assign rf_rd_write_o = rf_rd_write;
assign rf_rd_value_o = rf_rd_value;
......
......@@ -296,5 +296,3 @@ begin
end wrapper;
# and don't touch the rest unless you know what you're doing.
CROSS_COMPILE ?= /opt/gcc-riscv/bin/riscv64-unknown-elf-
CC = $(CROSS_COMPILE)gcc
XCC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJDUMP = $(CROSS_COMPILE)objdump
OBJCOPY = $(CROSS_COMPILE)objcopy
SIZE = $(CROSS_COMPILE)size
CFLAGS = -m32
OBJS = crt0.o main.o
LDS = ram.ld
OUTPUT=hello
$(OUTPUT): $(LDS) $(OBJS)
${CC} -m32 -o $(OUTPUT).elf -nostartfiles $(OBJS) -T $(LDS)
CFLAGS = -mabi=ilp32 -march=rv32im
OBJS = crt0.o $(OUTPUT).o
LDS = ram.ld
$(OUTPUT): $(LDS) $(OBJS) genraminit
${XCC} $(CFLAGS) -o $(OUTPUT).elf -nostartfiles $(OBJS) -T $(LDS)
${OBJCOPY} -O binary $(OUTPUT).elf $(OUTPUT).bin
${OBJDUMP} -D $(OUTPUT).elf > disasm.S
$(SIZE) $(OUTPUT).elf
......@@ -24,4 +26,10 @@ clean:
rm -f $(OUTPUT).elf $(OUTPUT).bin $(OBJS)
%.o: %.S
${CC} -c -m32 $^ -o $@
\ No newline at end of file
${XCC} -c $(CFLAGS) $< -o $@
%.o: %.c
${XCC} -c $(CFLAGS) $< -o $@
genraminit: genraminit.c
$(CC) -o $@ $<
......@@ -26,7 +26,12 @@ void undefined_insn_handler( struct rv_trap_context *ctx )
else if ( (insn & 0xfe00707f) == 0x2003033 ) // MULHU
ctx->r[rdi] = ((uint64_t) rs1 * (uint64_t) rs2) >> 32;
else if ( (insn & 0xfe00707f) == 0x2004033 ) // DIV
{
if( rs2 == 0 )
ctx->r[rdi] = 0xffffffff;
else
ctx->r[rdi] = (int32_t)rs1 / (int32_t) rs2;
}
else if ( (insn & 0xfe00707f) == 0x2005033 ) // DIVU
ctx->r[rdi] = (uint32_t)rs1 / (uint32_t) rs2;
else if ( (insn & 0xfe00707f) == 0x2006033 ) // REM
......
.section .text
.global trap_entry
.global trap_entry
.weak trap_entry
trap_entry:
csrrw sp,mscratch,sp
addi sp,sp,-320
......@@ -48,35 +49,19 @@ trap_entry:
sw t0,144(sp)
mv a0,sp
bgez t3, .Lexcept
jal irq_handler
j .Lret
.Lexcept:
la t0, jump_table
sll t3, t3, 2
add t0, t0, t3
lw t0, 0(t0)
la ra, jump_table_return
jr t0
jump_table:
.word undefined_handler
.word undefined_handler
.word undefined_insn_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
jump_table_return:
jalr t0
.Lret:
mv a0,sp
lw t1,128(a0)
lw t2,132(a0)
addi sp,sp,320
......@@ -113,12 +98,38 @@ jump_table_return:
lw t5,120(a0)
lw t6,124(a0)
lw a0,40(a0)
eret
mret
.weak undefined_handler
.text
.weak undefined_handler
undefined_handler:
j undefined_handler
.weak undefined_insn_handler
.weak undefined_insn_handler
undefined_insn_handler:
j undefined_insn_handler
.data
jump_table:
.word undefined_handler # 0: Insn address misaligned
.word undefined_handler
.word undefined_insn_handler # 2: Illegal insn
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.weak irq_handler
irq_handler:
j irq_handler
#include <stdint.h>
static const char hex[] = "0123456789abcdef";
static void uart_write_byte(int b)
{
*(volatile int *)0x100000 = b;
}
int puts(const char *s)
{
char c;
while(c=*s++)
uart_write_byte(c);
}
void rv_test_pass(int num)
{
pp_printf("Test passed\n");
puts("Test passed\n");
}
void rv_test_fail(int num)
{
pp_printf("Test %d failed\n", num);
puts ("Test 0x");
uart_write_byte(hex[(num >> 4) & 0xf]);
uart_write_byte(hex[(num >> 0) & 0xf]);
puts (" failed\n");
}
......@@ -46,18 +46,10 @@ void uart_init_hw()
}
volatile int *TX_REG = 0x100000;
void putc(char c)
{
*TX_REG = c;
}
void uart_write_byte(int b)
{
#ifdef SIM
putc(b);
*(volatile int *)0x100000 = b;
#else
if (b == '\n')
uart_write_byte('\r');
......@@ -85,4 +77,3 @@ int puts(const char *s)
while(c=*s++)
uart_write_byte(c);
}
hello.elf: file format elf32-littleriscv
Disassembly of section .boot:
00000000 <_start>:
0: 00000197 auipc gp,0x0
4: 07018193 addi gp,gp,112 # 70 <_gp>
8: 00010117 auipc sp,0x10
c: ff410113 addi sp,sp,-12 # fffc <_fstack>
10: 00000297 auipc t0,0x0
14: 07828293 addi t0,t0,120 # 88 <_fbss>
18: 00000317 auipc t1,0x0
1c: 0b030313 addi t1,t1,176 # c8 <_ebss>
20: 0002a023 sw zero,0(t0)
24: 00428293 addi t0,t0,4
28: fe62ece3 bltu t0,t1,20 <_start+0x20>
2c: 004000ef jal 30 <main>
Disassembly of section .text:
00000030 <main>:
30: fe010113 addi sp,sp,-32
34: 00812e23 sw s0,28(sp)
38: 02010413 addi s0,sp,32
3c: 08002783 lw a5,128(zero)
40: fef42623 sw a5,-20(s0)
44: 01c0006f j 60 <main+0x30>
48: 08402703 lw a4,132(zero)
4c: fec42783 lw a5,-20(s0)
50: 00178693 addi a3,a5,1
54: fed42623 sw a3,-20(s0)
58: 0007c783 lbu a5,0(a5)
5c: 00f72023 sw a5,0(a4)
60: fec42783 lw a5,-20(s0)
64: 0007c783 lbu a5,0(a5)
68: fe0790e3 bnez a5,48 <main+0x18>
6c: 0000006f j 6c <main+0x3c>
Disassembly of section .rodata:
00000070 <.rodata>:
70: 6548 add a0,a0,s2
72: 6c6c add s8,s8,s11
74: 77202c6f jal s8,27e6 <_ebss+0x271e>
78: 646c726f jal tp,c76be <_fstack+0xb76c2>
...
Disassembly of section .sdata:
00000080 <hello>:
80: 0070 li zero,28
...
00000084 <TX_REG>:
84: 0000 unimp
86: 0010 li zero,4
Disassembly of section .bss:
00000088 <_fbss>:
...
Disassembly of section .comment:
00000000 <.comment>:
0: 3a434347 fmsub.d ft6,ft6,ft4,ft7,rmm
4: 2820 lui a6,0x8
6: 29554e47 fmsub.s ft8,fa0,fs5,ft5,rmm
a: 3520 lui a0,0xfffe8
c: 312e beqz a1,b4 <_fbss+0x2c>
e: 302e beqz a1,36 <main+0x6>
...
......@@ -2,10 +2,12 @@ char dupa[64];
const char *hello="Hello, world";
volatile int *TX_REG = 0x100000;
main()
volatile int *TX_REG = (volatile int *)0x100000;
void
main(void)
{
char *s = hello;
const char *s = hello;
while(*s) { *TX_REG = *s++; }
for(;;);
}
# and don't touch the rest unless you know what you're doing.
CROSS_COMPILE ?= /opt/gcc-riscv/bin/riscv64-unknown-elf-
XCC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJDUMP = $(CROSS_COMPILE)objdump
OBJCOPY = $(CROSS_COMPILE)objcopy
SIZE = $(CROSS_COMPILE)size
OUTPUT=test_irq
CFLAGS = -mabi=ilp32 -march=rv32im
OBJS = ../common/crt0.o ../common/irq.o $(OUTPUT).o
LDS = ../common/ram2.ld
$(OUTPUT): $(LDS) $(OBJS) ../genraminit
${XCC} $(CFLAGS) -o $(OUTPUT).elf -nostartfiles $(OBJS) -T $(LDS)
${OBJCOPY} -O binary $(OUTPUT).elf $(OUTPUT).bin
${OBJDUMP} -D $(OUTPUT).elf > disasm.S
$(SIZE) $(OUTPUT).elf
# ../genramvhd -p wrc_simulation_firmware $(OUTPUT).bin > wrc_simulation_firmware_pkg.vhd
../genraminit $(OUTPUT).bin 1000 > $(OUTPUT).ram
clean:
rm -f $(OUTPUT).elf $(OUTPUT).bin $(OBJS)
%.o: %.S
${XCC} -c $(CFLAGS) $< -o $@
%.o: %.c
${XCC} -c $(CFLAGS) $< -o $@
static const char *hello="Hello, world";
static const char *ptr;
static int irq_cnt = 0;
volatile int *TX_REG = (volatile int *)0x100000;
volatile int *IRQ_REG = (volatile int *)0x100004;
void
irq_handler(void)
{
irq_cnt++;
if (*ptr) {
*TX_REG = *ptr++;
if (irq_cnt < 2)
*IRQ_REG = 100;
else
*IRQ_REG = 10;
}
else
*IRQ_REG = 0;
}
void
main(void)
{
unsigned t;
ptr = hello;
/* Enable irq: set mie.meie */
asm volatile ("csrrs %0, mie, %1" : "=r"(t) : "r"(1 << 11));
/* Enable interrupts: set mstatus.mie */
asm volatile ("csrrsi %0, mstatus, %1" : "=r"(t) : "i"(1 << 3));
/* Generate an interrupt after 10 cycles. */
*IRQ_REG = 10;
for(;;);
}
......@@ -619,6 +619,7 @@
#define CAUSE_SUPERVISOR_ECALL 0x9
#define CAUSE_HYPERVISOR_ECALL 0xa
#define CAUSE_MACHINE_ECALL 0xb
#define CAUSE_ECC_ERROR 0xf // urv specific
#endif
#ifdef DECLARE_INSN
DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
......
......@@ -121,11 +121,11 @@ ecall: ecall; \
#define RVTEST_PASS \
la sp, _fstack; la gp, _gp; jal rv_test_pass; \
la t0, 0x100004; sw t0, 0(t0); j ecall;
lui t0, %hi(0x100004); sw t0, %lo(0x100004)(t0); j ecall;
#define RVTEST_FAIL \
la sp, _fstack; la gp, _gp; mv a0, TESTNUM; jal rv_test_fail;\
la t0, 0x100004; sw t0, 0(t0); j ecall;
lui t0, %hi(0x100004); sw t0, %lo(0x100004)(t0); j ecall;
//-----------------------------------------------------------------------
// Data Section Macro
......
......@@ -13,6 +13,7 @@ isa_src_dir := .
include $(isa_src_dir)/rv32ui/Makefrag
#include $(isa_src_dir)/rv32si/Makefrag
include $(isa_src_dir)/rv32mi/Makefrag
include $(isa_src_dir)/urv/Makefrag
default: all
......@@ -20,23 +21,26 @@ default: all
# Build rules
#--------------------------------------------------------------------
RISCV_PREFIX=riscv64-unknown-elf-
RISCV_PREFIX=riscv32-elf-
RISCV_GCC = $(RISCV_PREFIX)gcc
ENTROPY = -DENTROPY=$(shell echo $$$$)
RISCV_GCC_OPTS = $(ENTROPY) -mcmodel=medany -nostartfiles -fvisibility=hidden -Wa,-march=RV32IM -DSIM -I../../common
RISCV_GCC_OPTS = $(ENTROPY) -mcmodel=medany -nostartfiles -fvisibility=hidden -march=rv32im -mabi=ilp32 -DSIM -I../../common
RISCV_OBJDUMP = $(RISCV_PREFIX)objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.text.init --section=.data
RISCV_SIM = spike --extension=hwacha
COMMON_SRCS = ../../common/crt0.S ../../common/irq.S ../../common/_emulate.o ../../common/test-common.c ../../common/printf.c ../../common/uart.c ../../common/vsprintf-xint.c
COMMON_SRCS = ../../common/crt0.S ../../common/irq.S emulate.o ../../common/test-common.c
vpath %.S $(isa_src_dir)
emulate.o: ../../common/emulate.c
$(RISCV_GCC) -c $(RISCV_GCC_OPTS) -mabi=ilp32 -march=rv32i -o $@ $<
#------------------------------------------------------------
# Build assembly tests
%.ram: %
riscv64-unknown-elf-objcopy -O binary $< tmp.bin
../../genraminit tmp.bin 16384 > $@
$(RISCV_PREFIX)objcopy -O binary $< tmp.bin
../../genraminit tmp.bin 4096 > $@
%.dump: %
$(RISCV_OBJDUMP) $< > $@
......@@ -49,7 +53,7 @@ vpath %.S $(isa_src_dir)
define compile_template
$$($(1)_p_tests): $(1)-p-%: $(1)/%.S
$$($(1)_p_tests): $(1)-p-%: $(1)/%.S emulate.o
$$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) -I$(isa_src_dir)/../env/p -I$(isa_src_dir)/macros/scalar $(COMMON_SRCS) -T ../../common/ram2.ld $$< -o $$@
$(1)_tests += $$($(1)_p_tests)
......@@ -64,7 +68,8 @@ tests += $$($(1)_tests)
endef
$(eval $(call compile_template,rv32ui,-m32))
$(eval $(call compile_template,rv32ui,))
$(eval $(call compile_template,urv,))
tests_dump = $(addsuffix .dump, $(tests))
tests_ram = $(addsuffix .ram, $(tests))
......
......@@ -249,7 +249,7 @@ test_ ## testnum: \
#define TEST_ST_OP( testnum, load_inst, store_inst, result, offset, base ) \
TEST_CASE( testnum, x3, result, \
la x1, base; \
lui x1, %hi(base); addi x1, x1, %lo(base) ; \
li x2, result; \
store_inst x2, offset(x1); \
load_inst x3, offset(x1); \
......@@ -286,9 +286,9 @@ test_ ## testnum: \
test_ ## testnum: \
li TESTNUM, testnum; \
li x4, 0; \
1: la x1, result; \
1: lui x1, %hi(result); addi x1, x1, %lo(result) ; \
TEST_INSERT_NOPS_ ## src1_nops \
la x2, base; \
lui x2, %hi(base); addi x2, x2, %lo(base) ; \
TEST_INSERT_NOPS_ ## src2_nops \
store_inst x1, offset(x2); \
load_inst x3, offset(x2); \
......@@ -302,9 +302,9 @@ test_ ## testnum: \
test_ ## testnum: \
li TESTNUM, testnum; \
li x4, 0; \
1: la x2, base; \
1: lui x2, %hi(base); addi x2, x2, %lo(base) ; \
TEST_INSERT_NOPS_ ## src1_nops \
la x1, result; \
lui x1, %hi(result); addi x1, x1, %lo(result) ; \
TEST_INSERT_NOPS_ ## src2_nops \
store_inst x1, offset(x2); \
load_inst x3, offset(x2); \
......
......@@ -22,7 +22,8 @@ rv32ui_sc_tests = \
srl srli \
sub \
xor xori \
csr
csr \
urv-mul-mulh
rv32ui_mc_tests =
# lrsc
......
......@@ -22,10 +22,10 @@ RVTEST_CODE_BEGIN
TEST_RR_OP( 4, div, -3, 20, -6 );
TEST_RR_OP( 5, div, 3, -20, -6 );
TEST_RR_OP( 6, div, -1<<63, -1<<63, 1 );
TEST_RR_OP( 7, div, -1<<63, -1<<63, -1 );
TEST_RR_OP( 6, div, -1<<31, -1<<31, 1 );
TEST_RR_OP( 7, div, -1<<31, -1<<31, -1 );
TEST_RR_OP( 8, div, -1, -1<<63, 0 );
TEST_RR_OP( 8, div, -1, -1<<31, 0 );
TEST_RR_OP( 9, div, -1, 1, 0 );
TEST_RR_OP(10, div, -1, 0, 0 );
......
......@@ -22,10 +22,10 @@ RVTEST_CODE_BEGIN
TEST_RR_OP( 4, rem, 2, 20, -6 );
TEST_RR_OP( 5, rem, -2, -20, -6 );
TEST_RR_OP( 6, rem, 0, -1<<63, 1 );
TEST_RR_OP( 7, rem, 0, -1<<63, -1 );
TEST_RR_OP( 6, rem, 0, -1<<31, 1 );
TEST_RR_OP( 7, rem, 0, -1<<31, -1 );
TEST_RR_OP( 8, rem, -1<<63, -1<<63, 0 );
TEST_RR_OP( 8, rem, -1<<31, -1<<31, 0 );
TEST_RR_OP( 9, rem, 1, 1, 0 );
TEST_RR_OP(10, rem, 0, 0, 0 );
......
......@@ -22,10 +22,10 @@ RVTEST_CODE_BEGIN
TEST_RR_OP( 4, remu, 20, 20, -6 );
TEST_RR_OP( 5, remu, -20, -20, -6 );
TEST_RR_OP( 6, remu, 0, -1<<63, 1 );
TEST_RR_OP( 7, remu, -1<<63, -1<<63, -1 );
TEST_RR_OP( 6, remu, 0, -1<<31, 1 );
TEST_RR_OP( 7, remu, -1<<31, -1<<31, -1 );
TEST_RR_OP( 8, remu, -1<<63, -1<<63, 0 );
TEST_RR_OP( 8, remu, -1<<31, -1<<31, 0 );
TEST_RR_OP( 9, remu, 1, 1, 0 );
TEST_RR_OP(10, remu, 0, 0, 0 );
......
......@@ -19,13 +19,7 @@ RVTEST_CODE_BEGIN
TEST_ST_OP( 2, lb, sb, 0xffffffaa, 0, tdat );
TEST_ST_OP( 3, lb, sb, 0x00000000, 1, tdat );
#ifdef __RISCVEL
TEST_ST_OP( 4, lh, sb, 0xffffefa0, 2, tdat );
#elif defined(__RISCVEB)
#else
TEST_ST_OP( 4, lh, sb, 0xffffa0ef, 2, tdat );
#error unknown endianness!
#endif
TEST_ST_OP( 5, lb, sb, 0x0000000a, 3, tdat );
# Test with negative offset
......
......@@ -19,13 +19,7 @@ RVTEST_CODE_BEGIN
TEST_ST_OP( 2, lh, sh, 0x000000aa, 0, tdat );
TEST_ST_OP( 3, lh, sh, 0xffffaa00, 2, tdat );
#ifdef __RISCVEL
TEST_ST_OP( 4, lw, sh, 0xbeef0aa0, 4, tdat );
#elif defined(__RISCVEB)
#else
TEST_ST_OP( 4, lw, sh, 0x0aa0beef, 4, tdat );
#error unknown endianness!
#endif
TEST_ST_OP( 5, lh, sh, 0xffffa00a, 6, tdat );
# Test with negative offset
......
#*****************************************************************************
# urv-mul-mulh.S
#-----------------------------------------------------------------------------
#
# Test mul/mulh stall condition (a.k.a. John's bug)
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
# before the multiply:
# a2 = 0x2833
# a3 = 0x3
# a5 = 0xcafebabe
li a2, 0x2833
li a3, 0x3
li a5, 0xcafebabe
mul a5,a3,a5
mulhu a3,a3,a2
#after the multiply (correct case)
# a3 = 0x0
# a5 = 0x60fc303a
li s0, 0x60fc303a
bne a3, zero, fail
bne a5, s0, fail
j pass
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END
urv-p-write_ecc.ram
urv-p-fix_ecc_1.ram
urv-p-fix_ecc_2.ram
urv-p-fix_ecc_dbl_err.ram
urv-p-ecc_ori.ram
......@@ -44,3 +44,4 @@ rv32ui-p-sub.ram
rv32ui-p-sw.ram
rv32ui-p-xori.ram
rv32ui-p-xor.ram
rv32ui-p-urv-mul-mulh.ram
\ No newline at end of file
#=======================================================================
# Makefrag for rv32ui tests
#-----------------------------------------------------------------------
urv_ecc_tests = \
write_ecc \
fix_ecc_1 \
fix_ecc_2 \
fix_ecc_dbl_err \
ecc_ori
urv_p_tests = $(addprefix urv-p-, $(urv_ecc_tests))
spike_tests += $(urv_p_tests)
# See LICENSE for license details.
#*****************************************************************************
# write_ecc.S
#-----------------------------------------------------------------------------
#
# Test write_ecc trap.
#
#include "riscv_test.h"
#include "test_macros.h"
#include "urv_asm.h"
RVTEST_RV32S
RVTEST_CODE_BEGIN
li a0, 0xff00ff00
# Corrupt a0 (bank 1)
li t1, 1
write_ecc a0, a0, t1
nop
nop
nop
# Test ori
ori a1, a0, 0xffffff0f
# Check result
li a2, 0xffffff0f
bne a1, a2, fail
# Check handler was called
bne t1, zero, fail
li a0, 0xff00ff00
# Corrupt a0 (bank 2)
li t1, 2
write_ecc a0, a0, t1
nop
nop
nop
# Test ori
ori a1, a0, 0xffffff0f
# Check result
li a2, 0xffffff0f
bne a1, a2, fail
# Check handler was not called
beq t1, zero, fail
j pass
TEST_PASSFAIL
.globl trap_entry
trap_entry:
fix_ecc x0,x0,x0
fix_ecc x1,x1,x1
fix_ecc x2,x2,x2
fix_ecc x3,x3,x3
fix_ecc x4,x4,x4
fix_ecc x5,x5,x5
fix_ecc x6,x6,x6
fix_ecc x7,x7,x7
fix_ecc x8,x8,x8
fix_ecc x9,x9,x9
fix_ecc x10,x10,x10
fix_ecc x11,x11,x11
fix_ecc x12,x12,x12
fix_ecc x13,x13,x13
fix_ecc x14,x14,x14
fix_ecc x15,x15,x15
fix_ecc x16,x16,x16
fix_ecc x17,x17,x17
fix_ecc x18,x18,x18
fix_ecc x19,x19,x19
fix_ecc x20,x20,x20
fix_ecc x21,x21,x21
fix_ecc x22,x22,x22
fix_ecc x23,x23,x23
fix_ecc x24,x24,x24
fix_ecc x25,x25,x25
fix_ecc x26,x26,x26
fix_ecc x27,x27,x27
fix_ecc x28,x28,x28
fix_ecc x29,x29,x29
fix_ecc x30,x30,x30
fix_ecc x31,x31,x31
# Clear t1
lui t1,0
mret
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END
# See LICENSE for license details.
#*****************************************************************************
# write_ecc.S
#-----------------------------------------------------------------------------
#
# Test write_ecc trap.
#
#include "riscv_test.h"
#include "test_macros.h"
#include "urv_asm.h"
RVTEST_RV32S
RVTEST_CODE_BEGIN
li TESTNUM, 2
li t2, 2
li t1, 1
# Write bad ECC for t2
write_ecc t2,t2,t1
nop # avoid bypass
nop
nop
# Use t2
addi t2,t2,1
j fail # Skipped by handler
# Check t2 has not been modified
addi t2,t2,1
j fail # Skipped by handler
# Fix t2
fix_ecc t2,t2,t2
j 1f # Handler not executed, so this is executed
j fail
1: addi t2,t2,1
j 1f
j fail
1: j pass
TEST_PASSFAIL
.globl trap_entry
trap_entry:
# Destroy t1, t0
li t1, CAUSE_ECC_ERROR
csrr t0, mcause
bne t0, t1, fail
# Inc address by 8
csrr t0, mepc
addi t0, t0, 8
csrw mepc, t0
mret
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END
# See LICENSE for license details.
#*****************************************************************************
# write_ecc.S
#-----------------------------------------------------------------------------
#
# Test write_ecc trap.
#
#include "riscv_test.h"
#include "test_macros.h"
#include "urv_asm.h"
RVTEST_RV32S
RVTEST_CODE_BEGIN
li TESTNUM, 2
li t2, 2
li t1, 2
# Write bad ECC for t2
write_ecc t2,t2,t1
nop # avoid bypass
nop
nop
# Use t2
add t3,t1,t2
j fail # Skipped by handler
# Check t2 has not been modified
add t3,t1,t2
j fail # Skipped by handler
# Fix t2
fix_ecc t2,t2,t2
j 1f # Handler not executed, so this is executed
j fail
1: add t3,t2,t2
j 1f
j fail
1: j pass
TEST_PASSFAIL
.globl trap_entry
trap_entry:
# Destroy t1, t0
li t1, CAUSE_ECC_ERROR
csrr t0, mcause
bne t0, t1, fail
# Inc address by 8
csrr t0, mepc
addi t0, t0, 8
csrw mepc, t0
mret
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END
# See LICENSE for license details.
#*****************************************************************************
# write_ecc.S
#-----------------------------------------------------------------------------
#
# Test write_ecc trap.
#
#include "riscv_test.h"
#include "test_macros.h"
#include "urv_asm.h"
RVTEST_RV32S
RVTEST_CODE_BEGIN
li TESTNUM, 2
li t2, 2
li t1, 3
# Write bad ECC for t2
write_ecc t2,t2,t1
nop # avoid bypass
nop
nop
# Use t2
add t3,t1,t2
j fail # Skipped by handler
# Check t2 has not been modified
add t3,t1,t2
j fail # Skipped by handler
# Expect error from fix_ecc
lui t0, %hi(0x100008)
sw t0, %lo(0x100008)(t0)
# Try to fix t2
fix_ecc t2,t2,t2
nop # Handler not executed, so this is executed
# Double error must have been detected
j fail
TEST_PASSFAIL
.globl trap_entry
trap_entry:
# Destroy t1, t0
li t1, CAUSE_ECC_ERROR
csrr t0, mcause
bne t0, t1, fail
# Inc address by 8
csrr t0, mepc
addi t0, t0, 8
csrw mepc, t0
mret
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END
.macro write_ecc rd rs1 rs2
.insn r 0x5b, 0x1, 0, \rd, \rs1, \rs2
.endm
.macro fix_ecc rd rs1 rs2
.insn r 0x5b, 0x5, 0, \rd, \rs1, \rs2
.endm
# See LICENSE for license details.
#*****************************************************************************
# write_ecc.S
#-----------------------------------------------------------------------------
#
# Test write_ecc trap.
#
#include "riscv_test.h"
#include "test_macros.h"
#include "urv_asm.h"
RVTEST_RV32S
RVTEST_CODE_BEGIN
li TESTNUM, 2
li t2, 0
# No bad ECC
write_ecc t2,t2,t2
nop # avoid bypass
nop
nop
# Use t2
addi t2,t2,1
j 1f # Not skipped
j fail
1: li t2, 2
li t1, 1 #t1 is reg 6
# Write bad ECC for t2
write_ecc t2,t2,t1
nop # avoid bypass
nop
nop
# Use t2
addi t2,t2,1
j fail # Skipped by handler
li t1, 2
li t2, 3
# Write bad ECC for t2
write_ecc t2,t2,t1
nop # avoid bypass
nop
nop
# Use t2
add t3,t1,t2
j fail # Skipped by handler
j pass
TEST_PASSFAIL
.globl trap_entry
trap_entry:
# Destroy t1, t0
li t1, CAUSE_ECC_ERROR
csrr t0, mcause
bne t0, t1, fail
# Inc address by 8
csrr t0, mepc
addi t0, t0, 8
csrw mepc, t0
mret
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END
sim_tool = "modelsim"
top_module="main"
sim_top="main"
syn_device="xc6slx150t"
action = "simulation"
target = "xilinx"
include_dirs=["../../rtl"]
fetchto = "../../ip_cores"
vcom_opt="-mixedsvvh l"
files = [ "main.sv" ];
modules = {"local" : [ "../../rtl" ] }
\ No newline at end of file
modules = {"local" : [ "../../rtl"],
"git" : ["https://ohwr.org/project/general-cores.git"]}
This diff is collapsed.
This diff is collapsed.
RISCV_PREFIX=riscv32-elf-
RISCV_GCC = $(RISCV_PREFIX)gcc
SW_DIR=../../sw
CFLAGS = -march=rv32im -mabi=ilp32 -O
all: app1.bin
app1: crt0.o app1.o
$(RISCV_GCC) -o $@ $^ -nostdlib -T $(SW_DIR)/common/ram2.ld -Wl,-Map,$@.map
app1.bin: app1
$(RISCV_PREFIX)objcopy -O binary $< $<.bin
crt0.o: $(SW_DIR)/crt0.S
$(RISCV_GCC) -c $(CFLAGS) -o $@ $<
uart.o: $(SW_DIR)/common/uart.c
$(RISCV_GCC) -c $(CFLAGS) -o $@ $<
app1.o: app1.c
$(RISCV_GCC) -c $(CFLAGS) -o $@ $<
clean:
$(RM) -f app1 *.o *.bin
sim_tool = "modelsim"
sim_top="main"
syn_device="xc6slx150t"
action = "simulation"
target = "xilinx"
include_dirs=["../../rtl"]
vcom_opt="-mixedsvvh l"
files = [ "main.sv" ];
modules = {"local" : [ "../../rtl", "../../ip_cores/general-cores" ] }
static int cnt;
int puts(const char *s);
int putchar(int b)
{
*(volatile int *)0x100000 = b;
return 0;
}
int main(void)
{
puts("Hello world\n");
asm volatile("nop; nop; ebreak");
while (1)
{
cnt++;
putchar('0' + (cnt & 0x7));
puts(" count\n");
}
return 0;
}
int puts(const char *s)
{
char c;
while (c = *s++)
putchar (c);
}
.text
# Set dest address
li a0, 0
# Read count (in bytes)
1: csrr t0, 0x7c0 # dbg status
andi t0, t0, 1
beq t0, zero, 1b
csrr a1, 0x7d0 # mbxi
# Read data
1: csrr t0, 0x7c0 # dbg status
andi t0, t0, 1
beq t0, zero, 1b
csrr t1, 0x7d0 # mbxi
sw t1, 0(a0)
addi a0, a0, 4
blt a0, a1, 1b
# Start at 0
done: li a0, 0
jr a0
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -4,6 +4,6 @@ vsim -L unisim -t 1ps work.main -novopt
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
do wave.do
#do wave.do
radix -hexadecimal
run 1.7us
\ No newline at end of file
run 8ms
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment