OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [ao486/] [exception.v] - Rev 6

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 * Copyright (c) 2014, Aleksander Osman
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * 
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
`include "defines.v"
 
//PARSED_COMMENTS: this file contains parsed script comments
 
module exception(
    input               clk,
    input               rst_n,
 
    //exception indicators
    input               dec_gp_fault,
    input               dec_ud_fault,
    input               dec_pf_fault,
 
    input               rd_seg_gp_fault,
    input               rd_descriptor_gp_fault,
    input               rd_seg_ss_fault,
    input               rd_io_allow_fault,
    input               rd_ss_esp_from_tss_fault, 
 
    input               exe_div_exception,
    input               exe_trigger_gp_fault,
    input               exe_trigger_ts_fault,
    input               exe_trigger_ss_fault,
    input               exe_trigger_np_fault,
    input               exe_trigger_nm_fault,
    input               exe_trigger_db_fault,
    input               exe_trigger_pf_fault,
    input               exe_bound_fault,
    input               exe_load_seg_gp_fault,
    input               exe_load_seg_ss_fault,
    input               exe_load_seg_np_fault,
 
    input               wr_debug_init,
 
    input               wr_new_push_ss_fault,
    input               wr_string_es_fault,
    input               wr_push_ss_fault,
 
    //from memory
    input               read_ac_fault,
    input               read_page_fault,
 
    input               write_ac_fault,
    input               write_page_fault,
 
    input       [15:0]  tlb_code_pf_error_code,
    input       [15:0]  tlb_check_pf_error_code,
    input       [15:0]  tlb_write_pf_error_code,
    input       [15:0]  tlb_read_pf_error_code,
 
    //wr_int
    input               wr_int,
    input               wr_int_soft_int,
    input               wr_int_soft_int_ib,
    input       [7:0]   wr_int_vector,
 
    input               wr_exception_external_set,
    input               wr_exception_finished,
 
    //eip
    input       [31:0]  eip,
    input       [31:0]  dec_eip,
    input       [31:0]  rd_eip,
    input       [31:0]  exe_eip,
    input       [31:0]  wr_eip,
 
    input       [3:0]   rd_consumed,
    input       [3:0]   exe_consumed,
    input       [3:0]   wr_consumed,
 
    //pipeline
    input               rd_dec_is_front,
    input               rd_is_front,
    input               exe_is_front,
    input               wr_is_front,
 
    //interrupt
    input       [7:0]   interrupt_vector,
    output reg          interrupt_done,
 
    //input
    input               wr_interrupt_possible,
    input               wr_string_in_progress_final,
    input               wr_is_esp_speculative,
 
    input               real_mode,
 
    input       [15:0]  rd_error_code,
    input       [15:0]  exe_error_code,
    input       [15:0]  wr_error_code,
 
    //output
    output              exc_dec_reset,
    output              exc_micro_reset,
    output              exc_rd_reset,
    output              exc_exe_reset,
    output              exc_wr_reset,
 
    output              exc_restore_esp,
    output              exc_set_rflag,
    output              exc_debug_start,
 
    output              exc_init,
    output reg          exc_load,
    output reg  [31:0]  exc_eip,
 
    output      [7:0]   exc_vector,
    output reg  [15:0]  exc_error_code,
    output reg          exc_push_error,
    output reg          exc_soft_int,
    output reg          exc_soft_int_ib,
 
    output              exc_pf_read,
    output              exc_pf_write,
    output              exc_pf_code,
    output              exc_pf_check
);
 
//------------------------------------------------------------------------------
 
//------------------------------------------------------------------------------
 
wire        exception_init;
wire        exception_start;
 
wire        active_dec;
wire        active_rd;
wire        active_exe;
wire        active_wr;
 
wire [31:0] exception_eip_from_wr;
 
//------------------------------------------------------------------------------
 
reg         external;
reg [1:0]   count;
reg [1:0]   last_type;
 
reg [31:0]  trap_eip;
 
reg         shutdown;
 
reg         interrupt_load;
reg         interrupt_string_in_progress;
 
reg [8:0]   exc_vector_full;
 
//------------------------------------------------------------------------------
 
wire [7:0]  vector;
wire [15:0] error_code;
wire        push_error;
 
wire        class_trap;
wire        class_abort;
 
wire [1:0]  exception_type;
 
wire        shutdown_start;
 
//------------------------------------------------------------------------------
 
assign exc_vector = exc_vector_full[7:0];
 
//------------------------------------------------------------------------------
 
assign exception_init = exc_vector_full[8];
 
assign exc_init   = exception_init || wr_interrupt_possible || interrupt_done || wr_debug_init;
 
assign active_dec = (dec_gp_fault || dec_ud_fault || dec_pf_fault) &&
                    rd_dec_is_front && ~(exc_init);
assign active_rd  = (rd_seg_gp_fault || rd_descriptor_gp_fault || rd_seg_ss_fault || rd_io_allow_fault ||
                     rd_ss_esp_from_tss_fault || read_ac_fault || read_page_fault) &&
                    rd_is_front  && ~(exc_init);
assign active_exe = (exe_div_exception || exe_trigger_gp_fault || exe_trigger_ts_fault || exe_trigger_ss_fault ||
                     exe_trigger_np_fault || exe_trigger_nm_fault || exe_trigger_db_fault || exe_trigger_pf_fault ||
                     exe_bound_fault || exe_load_seg_gp_fault || exe_load_seg_ss_fault || exe_load_seg_np_fault) &&
                    exe_is_front && ~(exc_init);
assign active_wr  = (wr_new_push_ss_fault || wr_string_es_fault || wr_push_ss_fault || write_ac_fault ||
                     write_page_fault || wr_int) &&
                    wr_is_front  && ~(exc_init);
 
assign exc_pf_read = active_rd  && read_page_fault;
assign exc_pf_write= active_wr  && write_page_fault;
assign exc_pf_code = active_dec && dec_pf_fault;
assign exc_pf_check= active_exe && exe_trigger_pf_fault;
 
//------------------------------------------------------------------------------
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                               exc_vector_full <= 9'd0;
 
    else if(active_wr && wr_new_push_ss_fault)      exc_vector_full <= { 1'b1, `EXCEPTION_SS };
    else if(active_wr && wr_string_es_fault)        exc_vector_full <= { 1'b1, `EXCEPTION_GP };
    else if(active_wr && wr_push_ss_fault)          exc_vector_full <= { 1'b1, `EXCEPTION_SS };
    else if(active_wr && write_ac_fault)            exc_vector_full <= { 1'b1, `EXCEPTION_AC };
    else if(active_wr && write_page_fault)          exc_vector_full <= { 1'b1, `EXCEPTION_PF };
 
    else if(active_wr && wr_int)                    exc_vector_full <= { 1'b0, wr_int_vector };
 
    else if(active_exe && exe_div_exception)        exc_vector_full <= { 1'b1, `EXCEPTION_DE };
    else if(active_exe && exe_trigger_gp_fault)     exc_vector_full <= { 1'b1, `EXCEPTION_GP };
    else if(active_exe && exe_trigger_ts_fault)     exc_vector_full <= { 1'b1, `EXCEPTION_TS };
    else if(active_exe && exe_trigger_ss_fault)     exc_vector_full <= { 1'b1, `EXCEPTION_SS };
    else if(active_exe && exe_trigger_np_fault)     exc_vector_full <= { 1'b1, `EXCEPTION_NP };
    else if(active_exe && exe_trigger_nm_fault)     exc_vector_full <= { 1'b1, `EXCEPTION_NM };
    else if(active_exe && exe_trigger_db_fault)     exc_vector_full <= { 1'b1, `EXCEPTION_DB };
    else if(active_exe && exe_trigger_pf_fault)     exc_vector_full <= { 1'b1, `EXCEPTION_PF };
    else if(active_exe && exe_bound_fault)          exc_vector_full <= { 1'b1, `EXCEPTION_BR };
    else if(active_exe && exe_load_seg_gp_fault)    exc_vector_full <= { 1'b1, `EXCEPTION_GP };
    else if(active_exe && exe_load_seg_ss_fault)    exc_vector_full <= { 1'b1, `EXCEPTION_SS };
    else if(active_exe && exe_load_seg_np_fault)    exc_vector_full <= { 1'b1, `EXCEPTION_NP };
 
    else if(active_rd && rd_seg_gp_fault)           exc_vector_full <= { 1'b1, `EXCEPTION_GP };
    else if(active_rd && rd_descriptor_gp_fault)    exc_vector_full <= { 1'b1, `EXCEPTION_GP };
    else if(active_rd && rd_seg_ss_fault)           exc_vector_full <= { 1'b1, `EXCEPTION_SS };
    else if(active_rd && rd_io_allow_fault)         exc_vector_full <= { 1'b1, `EXCEPTION_GP };
    else if(active_rd && rd_ss_esp_from_tss_fault)  exc_vector_full <= { 1'b1, `EXCEPTION_TS };
    else if(active_rd && read_ac_fault)             exc_vector_full <= { 1'b1, `EXCEPTION_AC };
    else if(active_rd && read_page_fault)           exc_vector_full <= { 1'b1, `EXCEPTION_PF };
 
    else if(active_dec && dec_gp_fault)             exc_vector_full <= { 1'b1, `EXCEPTION_GP };
    else if(active_dec && dec_ud_fault)             exc_vector_full <= { 1'b1, `EXCEPTION_UD };
    else if(active_dec && dec_pf_fault)             exc_vector_full <= { 1'b1, `EXCEPTION_PF };
 
    else                                            exc_vector_full <= exc_vector_full_to_reg; //set if(exception_init || wr_debug_init || interrupt_done)
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                           exc_error_code <= 16'd0;
 
    else if(active_wr && write_ac_fault)        exc_error_code <= 16'd0;
    else if(active_wr && write_page_fault)      exc_error_code <= tlb_write_pf_error_code;
    else if(active_wr)                          exc_error_code <= wr_error_code;
 
    else if(active_exe && exe_trigger_pf_fault) exc_error_code <= tlb_check_pf_error_code;
    else if(active_exe)                         exc_error_code <= exe_error_code;
 
    else if(active_rd && read_ac_fault)         exc_error_code <= 16'd0;
    else if(active_rd && read_page_fault)       exc_error_code <= tlb_read_pf_error_code;
    else if(active_rd)                          exc_error_code <= rd_error_code;
 
    else if(active_dec && dec_pf_fault)         exc_error_code <= tlb_code_pf_error_code;
    else if(active_dec)                         exc_error_code <= 16'd0;
 
    else                                        exc_error_code <= exc_error_code_to_reg; //set if(exception_init || wr_debug_init || interrupt_done)
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)               exc_push_error <= `FALSE;
    else if(active_wr && wr_int)    exc_push_error <= `FALSE;
    else                            exc_push_error <= exc_push_error_to_reg;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)               exc_soft_int <= `FALSE;
    else if(active_wr && wr_int)    exc_soft_int <= wr_int_soft_int;
    else                            exc_soft_int <= exc_soft_int_to_reg;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)               exc_soft_int_ib <= `FALSE;
    else if(active_wr && wr_int)    exc_soft_int_ib <= wr_int_soft_int_ib;
    else                            exc_soft_int_ib <= exc_soft_int_ib_to_reg;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   exc_load <= `FALSE;
    else                exc_load <= exception_start || interrupt_done;
end
 
//------------------------------------------------------------------------------
 
//------------------------------------------------------------------------------
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                   external <= 1'b0;
    else if(wr_exception_external_set)  external <= `TRUE;
    else if(wr_exception_finished)      external <= `FALSE;
    else                                external <= external_to_reg;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                   count <= 2'b0;
    else if(wr_exception_finished)      count <= 2'd0;
    else                                count <= count_to_reg;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   last_type <= 2'b0;
    else                last_type <= last_type_to_reg;
end
 
assign exception_eip_from_wr = wr_eip  - { 28'd0, wr_consumed };
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)      exc_eip <= 32'd0;
    else if(active_wr)     exc_eip <= exception_eip_from_wr;
    else if(active_exe)    exc_eip <= exe_eip - { 28'd0, exe_consumed };
    else if(active_rd)     exc_eip <= rd_eip  - { 28'd0, rd_consumed };
    else if(active_dec)    exc_eip <= eip;
    else                   exc_eip <= exc_eip_to_reg;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)      trap_eip <= 32'd0;
    else if(active_wr)     trap_eip <= wr_eip;
    else if(active_exe)    trap_eip <= exe_eip;
    else if(active_rd)     trap_eip <= rd_eip;
    else if(active_dec)    trap_eip <= dec_eip;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   shutdown <= `FALSE;
    else                shutdown <= shutdown_to_reg;
end
 
//------------------------------------------------------------------------------
 
assign vector = (wr_debug_init)? `EXCEPTION_DB : exc_vector_full[7:0];
 
assign error_code =
    (real_mode)?                                            16'd0 :
    (vector != `EXCEPTION_PF && vector != `EXCEPTION_DF)?   { exc_error_code[15:1], external } :
                                                            exc_error_code;
 
assign push_error =
    ~(real_mode) && (
        (vector == `EXCEPTION_DF) || (vector == `EXCEPTION_TS) || (vector == `EXCEPTION_NP) ||
        (vector == `EXCEPTION_SS) || (vector == `EXCEPTION_GP) || (vector == `EXCEPTION_PF) ||
        (vector == `EXCEPTION_AC));
 
assign class_trap  = (vector == `EXCEPTION_BP) || (vector == `EXCEPTION_OF);
 
assign class_abort = (vector == `EXCEPTION_MC);
 
`define EXCEPTION_TYPE_BENIGN           2'd0
`define EXCEPTION_TYPE_CONTRIBUTORY     2'd1
`define EXCEPTION_TYPE_PAGE_FAULT       2'd2
`define EXCEPTION_TYPE_DOUBLE_FAULT     2'd3
 
assign exception_type =
    (vector == `EXCEPTION_DE) || (vector >= `EXCEPTION_TS && vector <= `EXCEPTION_GP)?  `EXCEPTION_TYPE_CONTRIBUTORY :
    (vector == `EXCEPTION_DF)?                                                          `EXCEPTION_TYPE_DOUBLE_FAULT :
    (vector == `EXCEPTION_PF)?                                                          `EXCEPTION_TYPE_PAGE_FAULT :
                                                                                        `EXCEPTION_TYPE_BENIGN;
 
assign shutdown_start = count > 2'd2 || (count > 2'd0 && last_type == `EXCEPTION_TYPE_DOUBLE_FAULT);
 
//------------------------------------------------------------------------------
 
// interrupt_vector[7:0], interrupt_done; 
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)               interrupt_done <= `FALSE;
    else if(wr_interrupt_possible)  interrupt_done <= `TRUE;
    else                            interrupt_done <= `FALSE;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)           interrupt_load <= `FALSE;
    else                        interrupt_load <= interrupt_done;
end
 
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                                               interrupt_string_in_progress <= `FALSE;
    else if(wr_interrupt_possible && wr_string_in_progress_final)   interrupt_string_in_progress <= `TRUE;
    else if(wr_interrupt_possible)                                  interrupt_string_in_progress <= `FALSE;
end
 
assign exc_debug_start = exc_load && vector == `EXCEPTION_DB && interrupt_load == `FALSE;
 
/*******************************************************************************SCRIPT
 
NO_ALWAYS_BLOCK(exc_eip);
NO_ALWAYS_BLOCK(exc_error_code);
NO_ALWAYS_BLOCK(exc_push_error);
NO_ALWAYS_BLOCK(exc_soft_int);
NO_ALWAYS_BLOCK(exc_soft_int_ib);
NO_ALWAYS_BLOCK(exc_vector_full);
NO_ALWAYS_BLOCK(shutdown);
NO_ALWAYS_BLOCK(last_type);
NO_ALWAYS_BLOCK(count);
NO_ALWAYS_BLOCK(external);
 
*/
 
/*******************************************************************************SCRIPT
 
IF(exception_init || wr_debug_init);
    //NOTE: exe_reset must in same cycle as exception_init (wr waits one cycle for wr_one_cycle_wait) 
    SET(exc_dec_reset);
    SET(exc_micro_reset);
    SET(exc_rd_reset);
    SET(exc_exe_reset);
    SET(exc_wr_reset);
 
    IF(~(class_trap) && ~(class_abort));
 
        IF(wr_is_esp_speculative); SET(exc_restore_esp); ENDIF();
        // eip in exc_eip
 
        IF(vector != `EXCEPTION_DB); SET(exc_set_rflag); ENDIF();
    ELSE();
        // trap
            //esp no change needed
            SAVE(exc_eip, trap_eip);
    ENDIF();
 
    IF(vector == `EXCEPTION_DB);
        IF(wr_debug_init && ~(wr_string_in_progress_final));  SAVE(exc_eip, wr_eip); ENDIF();
        IF(wr_debug_init && wr_string_in_progress_final);     SAVE(exc_eip, exception_eip_from_wr); ENDIF();
        // if not wr_debug_init -- eip already in exc_eip
    ENDIF();
 
    SAVE(external, `TRUE);
 
    IF(shutdown_start == `FALSE && count > 2'd0 && exception_type != `EXCEPTION_TYPE_DOUBLE_FAULT && (
        (last_type == `EXCEPTION_TYPE_CONTRIBUTORY && exception_type == `EXCEPTION_TYPE_CONTRIBUTORY) ||
        (last_type == `EXCEPTION_TYPE_PAGE_FAULT   && exception_type == `EXCEPTION_TYPE_CONTRIBUTORY) ||
        (last_type == `EXCEPTION_TYPE_PAGE_FAULT   && exception_type == `EXCEPTION_TYPE_PAGE_FAULT)));
 
        SAVE(exc_vector_full, { 1'b1, `EXCEPTION_DF });
        SAVE(exc_error_code, 16'd0);
    ELSE();
 
        IF(shutdown_start == `FALSE);
            SAVE(last_type, exception_type);
            SAVE(count,     count + 2'd1);
 
            SAVE(exc_push_error, push_error);
            SAVE(exc_error_code, error_code);
 
            SAVE(exc_soft_int,    `FALSE);
            SAVE(exc_soft_int_ib, `FALSE);
 
            // finish this state
            SAVE(exc_vector_full, { 1'b0, vector });
 
            SET(exception_start);
        ENDIF();
    ENDIF(); 
 
    IF(shutdown_start);
        // finish this state
        SAVE(exc_vector_full, { 1'b0, vector });
 
        SAVE(shutdown, `TRUE);
    ENDIF();
 
ENDIF();
 
*/
 
/*******************************************************************************SCRIPT
 
IF(shutdown);
 
    // keep pipeline reset
    SET(exc_dec_reset);
    SET(exc_micro_reset);
    SET(exc_rd_reset);
    SET(exc_exe_reset);
    SET(exc_wr_reset);
ENDIF();
 
*/
 
/*******************************************************************************SCRIPT
 
IF(interrupt_done);
 
    SAVE(external, `TRUE);
 
    SAVE(exc_vector_full, { 1'b0, interrupt_vector });
 
    SAVE(exc_push_error, `FALSE);
    SAVE(exc_error_code, 16'd0);
 
    SAVE(exc_eip, (interrupt_string_in_progress)? exception_eip_from_wr : wr_eip);
 
    SAVE(exc_soft_int,    `FALSE);
    SAVE(exc_soft_int_ib, `FALSE);
 
    SET(exc_dec_reset);
    SET(exc_micro_reset);
    SET(exc_rd_reset);
    SET(exc_exe_reset);
    SET(exc_wr_reset);
ENDIF();
 
*/
 
//------------------------------------------------------------------------------
 
`include "autogen/exception.v"
 
 
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.