mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 05:37:16 -04:00
:Fix: Misaligned page exceptions, add dirty test
This commit is contained in:
parent
8352e83ed1
commit
1701a8a784
10 changed files with 193 additions and 136 deletions
2
Makefile
2
Makefile
|
@ -42,7 +42,7 @@ riscv-tests = rv64ui-p-add rv64ui-p-addi rv64ui-p-slli rv64ui-p-addiw rv64ui-p-a
|
|||
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 \
|
||||
rv64uc-p-rvc
|
||||
rv64uc-p-rvc rv64si-p-dirty
|
||||
|
||||
|
||||
riscv-test = rv64ui-p-add
|
||||
|
|
|
@ -82,7 +82,7 @@ Check out the [contribution guide](CONTRIBUTING.md)
|
|||
|
||||
| **Test Name** | **P/F/U** | **Test Name** | **P/F/U** | **Test Name** | **P/F/U** |
|
||||
|---------------|--------------------|---------------|--------------------|---------------|--------------------|
|
||||
| csr | :white_check_mark: | dirty | :x: | ma_fetch | :white_check_mark: |
|
||||
| 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: |
|
||||
|
||||
|
||||
|
|
38
src/alu.sv
38
src/alu.sv
|
@ -1,17 +1,27 @@
|
|||
/* Ariane ALU
|
||||
* File: scoreboard.sv
|
||||
* Author: Matthias Baer <baermatt@student.ethz.ch>
|
||||
* Author: Igor Loi <igor.loi@unibo.it>
|
||||
* Author: Andreas Traber <atraber@student.ethz.ch>
|
||||
* Author: Lukas Mueller <lukasmue@student.ethz.ch>
|
||||
* Author: Florian Zaruba <zaruabf@ethz.ch>
|
||||
* Date: 19.3.2017
|
||||
*
|
||||
* Description: Minimal version of the ALU, 64-bit compatible
|
||||
*
|
||||
* Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
* All rights reserved.
|
||||
*/
|
||||
// Author: Matthias Baer <baermatt@student.ethz.ch>
|
||||
// Author: Igor Loi <igor.loi@unibo.it>
|
||||
// Author: Andreas Traber <atraber@student.ethz.ch>
|
||||
// Author: Lukas Mueller <lukasmue@student.ethz.ch>
|
||||
// Author: Florian Zaruba <zaruabf@ethz.ch>
|
||||
//
|
||||
// Date: 19.03.2017
|
||||
// Description: Ariane ALU
|
||||
//
|
||||
//
|
||||
// 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 alu
|
||||
|
|
119
src/ariane.sv
119
src/ariane.sv
|
@ -193,6 +193,7 @@ module ariane
|
|||
// CSR <-> *
|
||||
// --------------
|
||||
logic enable_translation_csr_ex;
|
||||
logic en_ld_st_translation_csr_ex;
|
||||
priv_lvl_t ld_st_priv_lvl_csr_ex;
|
||||
logic sum_csr_ex;
|
||||
logic mxr_csr_ex;
|
||||
|
@ -328,68 +329,69 @@ module ariane
|
|||
// EX
|
||||
// ---------
|
||||
ex_stage ex_stage_i (
|
||||
.flush_i ( flush_ctrl_ex ),
|
||||
.fu_i ( fu_id_ex ),
|
||||
.operator_i ( operator_id_ex ),
|
||||
.operand_a_i ( operand_a_id_ex ),
|
||||
.operand_b_i ( operand_b_id_ex ),
|
||||
.imm_i ( imm_id_ex ),
|
||||
.trans_id_i ( trans_id_id_ex ),
|
||||
.pc_i ( pc_id_ex ),
|
||||
.is_compressed_instr_i ( is_compressed_instr_id_ex ),
|
||||
.flush_i ( flush_ctrl_ex ),
|
||||
.fu_i ( fu_id_ex ),
|
||||
.operator_i ( operator_id_ex ),
|
||||
.operand_a_i ( operand_a_id_ex ),
|
||||
.operand_b_i ( operand_b_id_ex ),
|
||||
.imm_i ( imm_id_ex ),
|
||||
.trans_id_i ( trans_id_id_ex ),
|
||||
.pc_i ( pc_id_ex ),
|
||||
.is_compressed_instr_i ( is_compressed_instr_id_ex ),
|
||||
// ALU
|
||||
.alu_ready_o ( alu_ready_ex_id ),
|
||||
.alu_valid_i ( alu_valid_id_ex ),
|
||||
.alu_result_o ( alu_result_ex_id ),
|
||||
.alu_trans_id_o ( alu_trans_id_ex_id ),
|
||||
.alu_valid_o ( alu_valid_ex_id ),
|
||||
.alu_exception_o ( ),
|
||||
.alu_ready_o ( alu_ready_ex_id ),
|
||||
.alu_valid_i ( alu_valid_id_ex ),
|
||||
.alu_result_o ( alu_result_ex_id ),
|
||||
.alu_trans_id_o ( alu_trans_id_ex_id ),
|
||||
.alu_valid_o ( alu_valid_ex_id ),
|
||||
.alu_exception_o ( ),
|
||||
// Branches and Jumps
|
||||
.branch_ready_o ( branch_ready_ex_id ),
|
||||
.branch_valid_o ( branch_valid_ex_id ),
|
||||
.branch_valid_i ( branch_valid_id_ex ),
|
||||
.branch_trans_id_o ( branch_trans_id_ex_id ),
|
||||
.branch_result_o ( branch_result_ex_id ),
|
||||
.branch_exception_o ( branch_exception_ex_id ),
|
||||
.branch_predict_i ( branch_predict_id_ex ), // branch predict to ex
|
||||
.resolved_branch_o ( resolved_branch ),
|
||||
.resolve_branch_o ( resolve_branch_ex_id ),
|
||||
.branch_ready_o ( branch_ready_ex_id ),
|
||||
.branch_valid_o ( branch_valid_ex_id ),
|
||||
.branch_valid_i ( branch_valid_id_ex ),
|
||||
.branch_trans_id_o ( branch_trans_id_ex_id ),
|
||||
.branch_result_o ( branch_result_ex_id ),
|
||||
.branch_exception_o ( branch_exception_ex_id ),
|
||||
.branch_predict_i ( branch_predict_id_ex ), // branch predict to ex
|
||||
.resolved_branch_o ( resolved_branch ),
|
||||
.resolve_branch_o ( resolve_branch_ex_id ),
|
||||
// LSU
|
||||
.lsu_ready_o ( lsu_ready_ex_id ),
|
||||
.lsu_valid_i ( lsu_valid_id_ex ),
|
||||
.lsu_result_o ( lsu_result_ex_id ),
|
||||
.lsu_trans_id_o ( lsu_trans_id_ex_id ),
|
||||
.lsu_valid_o ( lsu_valid_ex_id ),
|
||||
.lsu_commit_i ( lsu_commit_commit_ex ), // from commit
|
||||
.lsu_exception_o ( lsu_exception_ex_id ),
|
||||
.no_st_pending_o ( no_st_pending_ex_commit ),
|
||||
.lsu_ready_o ( lsu_ready_ex_id ),
|
||||
.lsu_valid_i ( lsu_valid_id_ex ),
|
||||
.lsu_result_o ( lsu_result_ex_id ),
|
||||
.lsu_trans_id_o ( lsu_trans_id_ex_id ),
|
||||
.lsu_valid_o ( lsu_valid_ex_id ),
|
||||
.lsu_commit_i ( lsu_commit_commit_ex ), // from commit
|
||||
.lsu_exception_o ( lsu_exception_ex_id ),
|
||||
.no_st_pending_o ( no_st_pending_ex_commit ),
|
||||
|
||||
// CSR
|
||||
.csr_ready_o ( csr_ready_ex_id ),
|
||||
.csr_valid_i ( csr_valid_id_ex ),
|
||||
.csr_trans_id_o ( csr_trans_id_ex_id ),
|
||||
.csr_result_o ( csr_result_ex_id ),
|
||||
.csr_valid_o ( csr_valid_ex_id ),
|
||||
.csr_addr_o ( csr_addr_ex_csr ),
|
||||
.csr_commit_i ( csr_commit_commit_ex ), // from commit
|
||||
.csr_ready_o ( csr_ready_ex_id ),
|
||||
.csr_valid_i ( csr_valid_id_ex ),
|
||||
.csr_trans_id_o ( csr_trans_id_ex_id ),
|
||||
.csr_result_o ( csr_result_ex_id ),
|
||||
.csr_valid_o ( csr_valid_ex_id ),
|
||||
.csr_addr_o ( csr_addr_ex_csr ),
|
||||
.csr_commit_i ( csr_commit_commit_ex ), // from commit
|
||||
// Memory Management
|
||||
.enable_translation_i ( enable_translation_csr_ex ), // from CSR
|
||||
.flush_tlb_i ( flush_tlb_ctrl_ex ),
|
||||
.fetch_req_i ( fetch_req_if_ex ),
|
||||
.fetch_gnt_o ( fetch_gnt_ex_if ),
|
||||
.fetch_valid_o ( fetch_valid_ex_if ),
|
||||
.fetch_vaddr_i ( fetch_vaddr_if_ex ),
|
||||
.fetch_rdata_o ( fetch_rdata_ex_if ),
|
||||
.fetch_ex_o ( fetch_ex_ex_if ), // fetch exception to IF
|
||||
.priv_lvl_i ( priv_lvl ), // from CSR
|
||||
.ld_st_priv_lvl_i ( ld_st_priv_lvl_csr_ex ), // from CSR
|
||||
.sum_i ( sum_csr_ex ), // from CSR
|
||||
.mxr_i ( mxr_csr_ex ), // from CSR
|
||||
.satp_ppn_i ( satp_ppn_csr_ex ), // from CSR
|
||||
.asid_i ( asid_csr_ex ), // from CSR
|
||||
.enable_translation_i ( enable_translation_csr_ex ), // from CSR
|
||||
.en_ld_st_translation_i ( en_ld_st_translation_csr_ex ),
|
||||
.flush_tlb_i ( flush_tlb_ctrl_ex ),
|
||||
.fetch_req_i ( fetch_req_if_ex ),
|
||||
.fetch_gnt_o ( fetch_gnt_ex_if ),
|
||||
.fetch_valid_o ( fetch_valid_ex_if ),
|
||||
.fetch_vaddr_i ( fetch_vaddr_if_ex ),
|
||||
.fetch_rdata_o ( fetch_rdata_ex_if ),
|
||||
.fetch_ex_o ( fetch_ex_ex_if ), // fetch exception to IF
|
||||
.priv_lvl_i ( priv_lvl ), // from CSR
|
||||
.ld_st_priv_lvl_i ( ld_st_priv_lvl_csr_ex ), // from CSR
|
||||
.sum_i ( sum_csr_ex ), // from CSR
|
||||
.mxr_i ( mxr_csr_ex ), // from CSR
|
||||
.satp_ppn_i ( satp_ppn_csr_ex ), // from CSR
|
||||
.asid_i ( asid_csr_ex ), // from CSR
|
||||
|
||||
.mult_ready_o ( mult_ready_ex_id ),
|
||||
.mult_valid_i ( mult_valid_id_ex ),
|
||||
.mult_ready_o ( mult_ready_ex_id ),
|
||||
.mult_valid_i ( mult_valid_id_ex ),
|
||||
.*
|
||||
);
|
||||
|
||||
|
@ -436,7 +438,8 @@ module ariane
|
|||
.trap_vector_base_o ( trap_vector_base_commit_pcgen ),
|
||||
.priv_lvl_o ( priv_lvl ),
|
||||
.ld_st_priv_lvl_o ( ld_st_priv_lvl_csr_ex ),
|
||||
.enable_translation_o ( enable_translation_csr_ex ),
|
||||
.en_translation_o ( enable_translation_csr_ex ),
|
||||
.en_ld_st_translation_o ( en_ld_st_translation_csr_ex ),
|
||||
.sum_o ( sum_csr_ex ),
|
||||
.mxr_o ( mxr_csr_ex ),
|
||||
.satp_ppn_o ( satp_ppn_csr_ex ),
|
||||
|
@ -509,6 +512,10 @@ module ariane
|
|||
initial begin
|
||||
it.trace();
|
||||
end
|
||||
|
||||
final begin
|
||||
it.close();
|
||||
end
|
||||
endprogram
|
||||
|
||||
instr_tracer instr_tracer_i (tracer_if);
|
||||
|
|
|
@ -22,47 +22,47 @@ import ariane_pkg::*;
|
|||
module csr_regfile #(
|
||||
parameter int ASID_WIDTH = 1
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rtc_i, // Real Time clock in
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic clk_i, // Clock
|
||||
input logic rtc_i, // Real Time clock in
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
// send a flush request out if a CSR with a side effect has changed (e.g. written)
|
||||
output logic flush_o,
|
||||
// commit acknowledge
|
||||
input logic commit_ack_i, // Commit acknowledged a instruction -> increase instret CSR
|
||||
input logic commit_ack_i, // Commit acknowledged a instruction -> increase instret CSR
|
||||
// Core and Cluster ID
|
||||
input logic [3:0] core_id_i, // Core ID is considered static
|
||||
input logic [5:0] cluster_id_i, // Cluster ID is considered static
|
||||
input logic [63:0] boot_addr_i, // Address from which to start booting, mtvec is set to the same address
|
||||
input logic [3:0] core_id_i, // Core ID is considered static
|
||||
input logic [5:0] cluster_id_i, // Cluster ID is considered static
|
||||
input logic [63:0] boot_addr_i, // Address from which to start booting, mtvec is set to the same address
|
||||
// we are taking an exception
|
||||
input exception ex_i, // We've got an exception from the commit stage, take its
|
||||
input exception ex_i, // We've got an exception from the commit stage, take its
|
||||
|
||||
input fu_op csr_op_i, // Operation to perform on the CSR file
|
||||
input logic [11:0] csr_addr_i, // Address of the register to read/write
|
||||
input logic [63:0] csr_wdata_i, // Write data in
|
||||
output logic [63:0] csr_rdata_o, // Read data out
|
||||
input logic [63:0] pc_i, // PC of instruction accessing the CSR
|
||||
output exception csr_exception_o, // attempts to access a CSR without appropriate privilege
|
||||
// level or to write a read-only register also
|
||||
// raises illegal instruction exceptions.
|
||||
input fu_op csr_op_i, // Operation to perform on the CSR file
|
||||
input logic [11:0] csr_addr_i, // Address of the register to read/write
|
||||
input logic [63:0] csr_wdata_i, // Write data in
|
||||
output logic [63:0] csr_rdata_o, // Read data out
|
||||
input logic [63:0] pc_i, // PC of instruction accessing the CSR
|
||||
output exception csr_exception_o, // attempts to access a CSR without appropriate privilege
|
||||
// level or to write a read-only register also
|
||||
// raises illegal instruction exceptions.
|
||||
// Interrupts/Exceptions
|
||||
output logic [63:0] epc_o, // Output the exception PC to PC Gen, the correct CSR (mepc, sepc) is set accordingly
|
||||
output logic eret_o, // Return from exception, set the PC of epc_o
|
||||
output logic [63:0] trap_vector_base_o, // Output base of exception vector, correct CSR is output (mtvec, stvec)
|
||||
output priv_lvl_t priv_lvl_o, // Current privilege level the CPU is in
|
||||
output logic [63:0] epc_o, // Output the exception PC to PC Gen, the correct CSR (mepc, sepc) is set accordingly
|
||||
output logic eret_o, // Return from exception, set the PC of epc_o
|
||||
output logic [63:0] trap_vector_base_o, // Output base of exception vector, correct CSR is output (mtvec, stvec)
|
||||
output priv_lvl_t priv_lvl_o, // Current privilege level the CPU is in
|
||||
// MMU
|
||||
output logic enable_translation_o, // Enable VA translation
|
||||
output priv_lvl_t ld_st_priv_lvl_o, // Privilege level at which load and stores should happen
|
||||
output logic en_translation_o, // enable VA translation
|
||||
output logic en_ld_st_translation_o, // enable VA translation for load and stores
|
||||
output priv_lvl_t ld_st_priv_lvl_o, // Privilege level at which load and stores should happen
|
||||
output logic sum_o,
|
||||
output logic mxr_o,
|
||||
// input logic flag_mprv_i,
|
||||
output logic [43:0] satp_ppn_o,
|
||||
output logic [ASID_WIDTH-1:0] asid_o,
|
||||
// external interrupts
|
||||
input logic [1:0] irq_i, // external interrupt in
|
||||
input logic [1:0] irq_i, // external interrupt in
|
||||
// Visualization Support
|
||||
output logic tvm_o, // trap virtual memory
|
||||
output logic tw_o, // timeout wait
|
||||
output logic tsr_o // trap sret
|
||||
output logic tvm_o, // trap virtual memory
|
||||
output logic tw_o, // timeout wait
|
||||
output logic tsr_o // trap sret
|
||||
// Performance Counter
|
||||
);
|
||||
|
||||
|
@ -76,13 +76,14 @@ module csr_regfile #(
|
|||
logic read_access_exception, update_access_exception;
|
||||
logic csr_we, csr_read;
|
||||
logic [63:0] csr_wdata, csr_rdata;
|
||||
priv_lvl_t trap_to_priv_lvl;
|
||||
|
||||
priv_lvl_t trap_to_priv_lvl;
|
||||
// register for enabling load store address translation, this is critical, hence the register
|
||||
logic en_ld_st_translation_n, en_ld_st_translation_q;
|
||||
// ----------------------
|
||||
// LD/ST Privilege Level
|
||||
// ----------------------
|
||||
assign ld_st_priv_lvl_o = (mstatus_q.mprv) ? mstatus_q.mpp : priv_lvl_o;
|
||||
|
||||
assign en_ld_st_translation_o = en_ld_st_translation_q;
|
||||
// ----------------
|
||||
// CSR Registers
|
||||
// ----------------
|
||||
|
@ -223,12 +224,13 @@ module csr_regfile #(
|
|||
sscratch_n = sscratch_q;
|
||||
stval_n = stval_q;
|
||||
satp_n = satp_q;
|
||||
en_ld_st_translation_n = en_ld_st_translation_q;
|
||||
|
||||
// check for correct access rights and that we are writing
|
||||
if(csr_we) begin
|
||||
case (csr_addr.address)
|
||||
// sstatus is a subset of mstatus - mask it accordingly
|
||||
CSR_SSTATUS: mstatus_n = csr_wdata & 64'h3fffe1fee;
|
||||
CSR_SSTATUS: mstatus_n = csr_wdata & 64'h3fffe1fee;
|
||||
// even machine mode interrupts can be visible and set-able to supervisor
|
||||
// if the corresponding bit in mideleg is set
|
||||
CSR_SIE: mie_n = csr_wdata & 64'hBBB & mideleg_q; // we only support supervisor and m-mode interrupts
|
||||
|
@ -260,7 +262,7 @@ module csr_regfile #(
|
|||
mstatus_n.fs = 2'b0;
|
||||
mstatus_n.upie = 1'b0;
|
||||
mstatus_n.uie = 1'b0;
|
||||
// if the SIE was set also set the MIE as interrupts for
|
||||
// if the SIE was set also set the MIE, as interrupts for
|
||||
// higher privilege levels are always set, 1.10 p.20
|
||||
if (csr_wdata[1])
|
||||
mstatus_n.mie = 1'b1;
|
||||
|
@ -270,13 +272,13 @@ module csr_regfile #(
|
|||
mstatus_n.sie = 1'b0;
|
||||
end
|
||||
// machine exception delegation register
|
||||
// 0 - 12 exceptions supported
|
||||
// 0 - 15 exceptions supported
|
||||
CSR_MEDELEG: medeleg_n = csr_wdata & 64'hF7FF;
|
||||
// machine interrupt delegation register
|
||||
// we do not support user interrupt delegation
|
||||
CSR_MIDELEG: mideleg_n = csr_wdata & 64'hBBB;
|
||||
|
||||
// mask the register so that user interrupts can never be set
|
||||
// mask the register so that unsupported interrupts can never be set
|
||||
CSR_MIE: mie_n = csr_wdata & 64'hBBB; // we only support supervisor and m-mode interrupts
|
||||
CSR_MIP: mip_n = csr_wdata & 64'h33; // only USIP, SSIP, UTIP, STIP are write-able
|
||||
|
||||
|
@ -287,7 +289,7 @@ module csr_regfile #(
|
|||
CSR_MTVAL: mtval_n = csr_wdata;
|
||||
default: update_access_exception = 1'b1;
|
||||
endcase
|
||||
// so we wrote something, TODO: this can be finer grained (e.g.: did it have side effects?)
|
||||
// so we wrote something, TODO: this can be more fine grained (e.g.: did it have side effects?)
|
||||
flush_o = 1'b1;
|
||||
end
|
||||
// ---------------------
|
||||
|
@ -296,15 +298,15 @@ module csr_regfile #(
|
|||
// Machine Mode External Interrupt Pending
|
||||
mip_n[11] = mip_q[11] & irq_i[0];
|
||||
// Supervisor Mode External Interrupt Pending
|
||||
mip_n[9] = mip_q[9] & irq_i[0];
|
||||
mip_n[9] = mip_q[9] & irq_i[1];
|
||||
|
||||
// -----------------------
|
||||
// Manage Exception Stack
|
||||
// -----------------------
|
||||
// update exception CSRs
|
||||
// we got an exception update cause, pc and stval register
|
||||
// Exception is taken
|
||||
trap_to_priv_lvl = PRIV_LVL_M;
|
||||
// Exception is taken
|
||||
if (ex_i.valid) begin
|
||||
// do not flush, flush is reserved for CSR writes with side effects
|
||||
flush_o = 1'b0;
|
||||
|
@ -351,6 +353,15 @@ module csr_regfile #(
|
|||
|
||||
priv_lvl_n = trap_to_priv_lvl;
|
||||
end
|
||||
// ------------------------------
|
||||
// MPRV - Modify Privilege Level
|
||||
// ------------------------------
|
||||
// Set the address translation at which the load and stores should occur
|
||||
// we can use the previous values since changing the address translation will always involve a pipeline flush
|
||||
if (mstatus_q.mprv && satp_q.mode == 4'h8 && (mstatus_q.mpp != PRIV_LVL_M))
|
||||
en_ld_st_translation_n = 1'b1;
|
||||
else // otherwise we go with the regular settings
|
||||
en_ld_st_translation_n = en_translation_o;
|
||||
// -----------------------
|
||||
// Return from Exception
|
||||
// -----------------------
|
||||
|
@ -511,18 +522,18 @@ module csr_regfile #(
|
|||
// -------------------
|
||||
// Output Assignments
|
||||
// -------------------
|
||||
assign csr_rdata_o = csr_rdata;
|
||||
assign priv_lvl_o = priv_lvl_q;
|
||||
assign csr_rdata_o = csr_rdata;
|
||||
assign priv_lvl_o = priv_lvl_q;
|
||||
// MMU outputs
|
||||
assign satp_ppn_o = satp_q.ppn;
|
||||
assign asid_o = satp_q.asid[ASID_WIDTH-1:0];
|
||||
assign sum_o = mstatus_q.sum;
|
||||
assign satp_ppn_o = satp_q.ppn;
|
||||
assign asid_o = satp_q.asid[ASID_WIDTH-1:0];
|
||||
assign sum_o = mstatus_q.sum;
|
||||
// we support bare memory addressing and SV39
|
||||
assign enable_translation_o = (satp_q.mode == 4'h8 && priv_lvl_q != PRIV_LVL_M) ? 1'b1 : 1'b0;
|
||||
assign mxr_o = mstatus_q.mxr;
|
||||
assign tvm_o = mstatus_q.tvm;
|
||||
assign tw_o = mstatus_q.tw;
|
||||
assign tsr_o = mstatus_q.tsr;
|
||||
assign en_translation_o = (satp_q.mode == 4'h8 && priv_lvl_q != PRIV_LVL_M) ? 1'b1 : 1'b0;
|
||||
assign mxr_o = mstatus_q.mxr;
|
||||
assign tvm_o = mstatus_q.tvm;
|
||||
assign tw_o = mstatus_q.tw;
|
||||
assign tsr_o = mstatus_q.tsr;
|
||||
|
||||
// output assignments dependent on privilege mode
|
||||
always_comb begin : priv_output
|
||||
|
@ -570,6 +581,8 @@ module csr_regfile #(
|
|||
// timer and counters
|
||||
cycle_q <= 64'b0;
|
||||
instret_q <= 64'b0;
|
||||
// aux registers
|
||||
en_ld_st_translation_q <= 1'b0;
|
||||
end else begin
|
||||
priv_lvl_q <= priv_lvl_n;
|
||||
// machine mode registers
|
||||
|
@ -593,6 +606,8 @@ module csr_regfile #(
|
|||
// timer and counters
|
||||
cycle_q <= cycle_n;
|
||||
instret_q <= instret_n;
|
||||
// aux registers
|
||||
en_ld_st_translation_q <= en_ld_st_translation_n;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ module ex_stage #(
|
|||
input logic csr_commit_i,
|
||||
// memory management
|
||||
input logic enable_translation_i,
|
||||
input logic en_ld_st_translation_i,
|
||||
input logic flush_tlb_i,
|
||||
input logic fetch_req_i,
|
||||
output logic fetch_gnt_o,
|
||||
|
|
|
@ -40,7 +40,7 @@ module lsu #(
|
|||
input logic commit_i, // commit the pending store
|
||||
|
||||
input logic enable_translation_i, // enable virtual memory translation
|
||||
|
||||
input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores
|
||||
input logic fetch_req_i, // Instruction fetch interface
|
||||
output logic fetch_gnt_o, // Instruction fetch interface
|
||||
output logic fetch_valid_o, // Instruction fetch interface
|
||||
|
|
18
src/mmu.sv
18
src/mmu.sv
|
@ -27,10 +27,12 @@ module mmu #(
|
|||
parameter int ASID_WIDTH = 1
|
||||
)
|
||||
(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic flush_i,
|
||||
input logic enable_translation_i,
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic flush_i,
|
||||
input logic enable_translation_i,
|
||||
input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores
|
||||
|
||||
// IF interface
|
||||
input logic fetch_req_i,
|
||||
output logic fetch_gnt_o,
|
||||
|
@ -273,7 +275,7 @@ module mmu #(
|
|||
daccess_err = (ld_st_priv_lvl_i == PRIV_LVL_S && !sum_i && dtlb_content.u) || // SUM is not set and we are trying to access a user page in supervisor mode
|
||||
(ld_st_priv_lvl_i == PRIV_LVL_U && !dtlb_content.u); // this is not a user page but we are in user mode and trying to access it
|
||||
// translation is enabled and no misaligned exception occurred
|
||||
if (enable_translation_i && !misaligned_ex_i.valid) begin
|
||||
if (en_ld_st_translation_i && !misaligned_ex_i.valid) begin
|
||||
lsu_valid_o = 1'b0;
|
||||
// 4K page
|
||||
lsu_paddr_o = {dtlb_content.ppn, lsu_vaddr_i[11:0]};
|
||||
|
@ -296,6 +298,10 @@ module mmu #(
|
|||
if (!dtlb_content.w || daccess_err) begin
|
||||
lsu_exception_o = {ST_ACCESS_FAULT, lsu_vaddr_i, 1'b1};
|
||||
end
|
||||
// check if the dirty flag is set
|
||||
if (!dtlb_content.d) begin
|
||||
lsu_exception_o = {STORE_PAGE_FAULT, lsu_vaddr_i, 1'b1};
|
||||
end
|
||||
// this is a load, check for sufficient access privileges
|
||||
end else if (daccess_err) begin
|
||||
lsu_exception_o = {LD_ACCESS_FAULT, lsu_vaddr_i, 1'b1};
|
||||
|
@ -304,7 +310,7 @@ module mmu #(
|
|||
// ---------
|
||||
// DTLB Miss
|
||||
// ---------
|
||||
// watch out for exception
|
||||
// watch out for exceptions
|
||||
if (ptw_active && !walking_instr) begin
|
||||
// page table walker threw an exception
|
||||
if (ptw_error) begin
|
||||
|
|
34
src/ptw.sv
34
src/ptw.sv
|
@ -24,16 +24,18 @@ module ptw #(
|
|||
parameter int ASID_WIDTH = 1
|
||||
)
|
||||
(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush everything, we need to do this because
|
||||
// actually everything we do is speculative at this stage
|
||||
// e.g.: there could be a CSR instruction that changes everything
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush everything, we need to do this because
|
||||
// actually everything we do is speculative at this stage
|
||||
// e.g.: there could be a CSR instruction that changes everything
|
||||
output logic ptw_active_o,
|
||||
output logic walking_instr_o, // set when walking for TLB
|
||||
output logic ptw_error_o, // set when an error occurred
|
||||
input logic enable_translation_i, // CSRs indicate to enable SV39
|
||||
input logic lsu_is_store_i, // this translation was triggered by a store
|
||||
output logic walking_instr_o, // set when walking for TLB
|
||||
output logic ptw_error_o, // set when an error occurred
|
||||
input logic enable_translation_i, // CSRs indicate to enable SV39
|
||||
input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores
|
||||
|
||||
input logic lsu_is_store_i, // this translation was triggered by a store
|
||||
// PTW Memory Port
|
||||
output logic [11:0] address_index_o,
|
||||
output logic [43:0] address_tag_o,
|
||||
|
@ -177,7 +179,7 @@ module ptw #(
|
|||
vaddr_n = itlb_vaddr_i;
|
||||
NS = WAIT_GRANT;
|
||||
// we got an DTLB miss
|
||||
end else if (enable_translation_i & dtlb_access_i & dtlb_miss_i) begin
|
||||
end else if (en_ld_st_translation_i & dtlb_access_i & dtlb_miss_i) begin
|
||||
ptw_pptr_n = {satp_ppn_i, dtlb_vaddr_i[38:30], 3'b0};
|
||||
tlb_update_asid_n = asid_i;
|
||||
vaddr_n = dtlb_vaddr_i;
|
||||
|
@ -253,6 +255,18 @@ module ptw #(
|
|||
NS = PROPAGATE_ERROR;
|
||||
end
|
||||
end
|
||||
// check if the ppn is correctly aligned:
|
||||
// 6. If i > 0 and pa.ppn[i − 1 : 0] != 0, this is a misaligned superpage; stop and raise a page-fault
|
||||
// exception.
|
||||
if (ptw_lvl_q == LVL1 && pte.ppn[17:0] != '0) begin
|
||||
NS = PROPAGATE_ERROR;
|
||||
dtlb_update_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
end else if (ptw_lvl_q == LVL2 && pte.ppn[8:0] != '0) begin
|
||||
NS = PROPAGATE_ERROR;
|
||||
dtlb_update_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
end
|
||||
// this is a pointer to the next TLB level
|
||||
end else begin
|
||||
// pointer to next level of page table
|
||||
|
|
|
@ -180,4 +180,8 @@ class instruction_tracer;
|
|||
$fwrite(this.f, {print_ex, "\n"});
|
||||
endfunction
|
||||
|
||||
function void close();
|
||||
$fclose(this.f);
|
||||
endfunction
|
||||
|
||||
endclass : instruction_tracer
|
Loading…
Add table
Add a link
Reference in a new issue