/******************************************************************************/
/* */
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved. */
/* */
/* The contents of this file are subject to the current version of the Sun */
/* Community Source License, microSPARCII ("the License"). You may not use */
/* this file except in compliance with the License. You may obtain a copy */
/* of the License by searching for "Sun Community Source License" on the */
/* World Wide Web at http://www.sun.com. See the License for the rights, */
/* obligations, and limitations governing use of the contents of this file. */
/* */
/* Sun Microsystems, Inc. has intellectual property rights relating to the */
/* technology embodied in these files. In particular, and without limitation, */
/* these intellectual property rights may include one or more U.S. patents, */
/* foreign patents, or pending applications. */
/* */
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos, */
/* Solaris, Java and all Java-based trademarks and logos are trademarks or */
/* registered trademarks of Sun Microsystems, Inc. in the United States and */
/* other countries. microSPARC is a trademark or registered trademark of */
/* SPARC International, Inc. All SPARC trademarks are used under license and */
/* are trademarks or registered trademarks of SPARC International, Inc. in */
/* the United States and other countries. Products bearing SPARC trademarks */
/* are based upon an architecture developed by Sun Microsystems, Inc. */
/* */
/******************************************************************************/
/***************************************************************************
****************************************************************************
***
*** Program File: @(#)rl_mmu_lgc.v
***
****************************************************************************
****************************************************************************/
//****************************************************************************
// @(#)rl_mmu_lgc.v 1.168 1/31/94
//
// Description:
// Preprocessed MMU Logic
//
//****************************************************************************
// m4 doesn't work on the rest of this file with the usual quotes
// because these are used by verilog defines.
// change the quotes to very unlikely characters.
// also have to .
/* functional model of MMU internal mem bus arbiter */
module rl_mmu_lgc
(
mm_mreq,
mm_fb_req,
r_dc_miss,
dc_miss,
r_ic_miss,
ic_miss,
dvma_req_s,
dvma_req_x,
set_m_on_tw,
r_sxlate,
r_sxlate_ioreq,
strt_tw_for_m,
dmiss_for_m,
sb_write,
r_srd_ioreq,
r_tlb_miss,
size_w,
mm_fb_size,
bypass_mmu_asi,
asidcd_mask,
asi_done,
sb_data_avail,
mm_sbsize,
data_acc_s,
r_tlb_miss_tw,
tlb_miss_tw,
mm_dabort,
dabort_in,
mm_iabort,
ldd_w,
std_x,
r_tlb_used,
asi_w,
r_sb_ioreq,
r_trap_w,
read_w,
read_w_reg,
write_x,
st_op_w,
ldsto_w,
ldsto_x,
r_ldsto_w,
cbit_in,
mmulgc_bp_hit,
ok_2_probe,
mm_page,
r_io_space,
r_mem_space,
r_cntl_space,
r_pci_space,
wb_valid_t,
wb_valid_x,
wb_valid_x_reg,
wb_empty,
st_miss_c,
st_miss_x,
st_miss_x_reg,
last_st_w,
derr_wbstb, /* Data error write buffer strobe */
r_dc_in_par,
r_ic_in_par,
r_ic_tlb,
r_dc_tlb,
r_wr_tlb,
pipe_moved,
dfetch,
fp_ld_mask,
precharge_early_0,
precharge_early_1,
mm_hold_rst,
afx_qbusy,
wb_3_asi_buf,
/* start of inputs */
tw_tlb_nxt,
cntrl_spc_err,
dcc_idle,
hold_par,
mc_mstb_l,
normal_asi_w,
invalid_wb_entry,
mm_dnocache_done,
sb_data_clr,
sbc_pa_valid,
sb_ioreq,
sb_ioreq_vld,
tw_par,
ld_op_e,
st_op_e,
fpu_mem_e,
fp_trap_fix, // FPU trap may occur at anytime
wb_3_size,
wb_valid,
iu_size_e,
iu_asi_e,
tlb_miss,
ld_par,
ld_mreq_tw,
pcr_dcen,
pcr_icen,
tw_read_req,
tw_write_req,
mem_issue_req,
iu_pipe_hold,
iu_pipe_hold_fast,
m_miss,
tlb_c_bit,
bypass_mmu_asi_w,
mmu_bypass,
pcr_mmuen,
pcr_ac,
ldst_st,
iu_in_trap,
io_space,
cntl_space,
mem_space,
fb_space,
pci_space,
flush_iopte,
tw_err,
priv_err_x,
prtct_err_x,
sb_cyc_pnd,
io_tlb_err,
tw_init_par,
probe,
probe_done,
tw_sm_lvl,
r_acc_err_tw,
tw_prb_drdy,
iacc_miss,
dacc_miss,
enbl_soft_tw,
ic_tlb,
ic_tlb_state,
dc_tlb,
dc_tlb_state,
wr_tlb,
io_tlb,
ic_tlb_tw,
dc_tlb_tw,
wr_tlb_tw,
io_tlb_tw,
ic_in_par,
dc_in_par,
par_cbit,
ipar_cbit,
dpar_cbit,
ic_par_state,
dc_par_state,
mop_c_bit,
ic_miss_or_part,
ic_miss_and_part,
it_hit_f, // itag hit in f stage ** ASSERTED LOW **
dc_miss_or_part,
dc_miss_and_part,
dt_hit_w,
dc_miss_sustain,
dc_stream,
ic_miss_sustain,
mm_wbstb,
wb_3_asi,
mm_sb_err,
mmu_asi_op,
dc_issue_req,
asi_dcd3,
r_pipe_moved,
page_hit,
page_miss0,
page_miss1,
req_pending,
mc_mbsy,
r_mbsy,
sup_nalloc,
r_sup_mode,
dp_bp_hit,
mmu_brkpt_en,
r_p_reply_dec, // AFX queue status
afx_qlvl, // AFX queue read level control bit
marb_busy, // Memory state machine busy
aarb_bsy, // ASI state machine busy
r_mem_issue_req,
sbus_id_hit,
cs_st_op,
ss_clock,
ss_reset
);
output [3:0] mm_mreq
; // output to MCB showing type of request
output mm_fb_req
; // indicates a frame buffer request has been detected
output r_dc_miss
; // Reg'd dc_miss
output dc_miss
;
output r_ic_miss
; // Reg'd ic_miss
output ic_miss
;
output dvma_req_s
; // indicates a valid dvma request has been detected
output dvma_req_x
; // indicates a valid dvma request has been detected
output set_m_on_tw
; // bit says to set the modified bit on a tablewalk
output r_sxlate
; // dvma xlate op OR dvma control space read
output r_sxlate_ioreq
; // dvma xlate op
output strt_tw_for_m
; // bit says to start a tablewalk for setting PTE M-bit
output dmiss_for_m
; // bit says to set mm_dacc_miss for modeifed case
output sb_write
; // SBC write pending
output r_srd_ioreq
; // SBC read pending
output r_tlb_miss
; // registered tlb miss
output [1:0] size_w
; // size of xaction from iu (byte, hw, wrd, dw) in e
output [1:0] mm_fb_size
; // size of FB xaction (byte, hw, wrd, dw)
output bypass_mmu_asi
; // bypass the mmu due to asi 0x20
output asidcd_mask
; // Mask non-device ASI decodes
output asi_done
; // asi op complete
output sb_data_avail
; // read data is available from sbc
output [1:0] mm_sbsize
; //size of op from iu to sbus
output [2:0] data_acc_s
; // access type field for SFSR
output r_tlb_miss_tw
; // Qualified tlb miss signal for tw (w/out mbit gating)
output tlb_miss_tw
; // Qualified tlb miss signal for tw (w/out mbit gating)
output mm_dabort
; // dcache memory op abort indication (R-stage)
output dabort_in
; // dcache memory op abort indication (R-stage)
output mm_iabort
; // icache memory op abort indication
output ldd_w
; // ldd in W-stage
output std_x
; // std in W-stage & X-stage
output r_tlb_used
;
output [5:0] asi_w
;
output [3:0] r_sb_ioreq
;
output r_trap_w
; // registered iu_trap_w
output read_w
; // registered (held on iu_pipe_hold) ld_op_e
output read_w_reg
; // copy of read_w (created for timing fix --Sand)
output write_x
; // registered write_w
output st_op_w
; // registered (held on iu_pipe_hold) st_op_e
output ldsto_w
; // Qualified ldsto_w
output ldsto_x
; // registered ldsto_w (used in X-stage)
output r_ldsto_w
; // registered (held on iu_pipe_hold) iu_ldsto_e
output cbit_in
; // cacheable bit for AFSR.
output mmulgc_bp_hit
;
output ok_2_probe
;
output mm_page
;
output r_io_space
;
output r_mem_space
;
output r_cntl_space
;
output r_pci_space
;
output wb_valid_t
; // Write buffer valid (translate stage)
output wb_valid_x
; // Write buffer valid (execute stage)
output wb_valid_x_reg
; // Copy of wb_valid_x (for timing fix --Sand)
output wb_empty
; // Write buffer empty
output st_miss_c
; // Store miss - cacheable
output st_miss_x
; // Store miss
output st_miss_x_reg
; // Copy of st_miss_x (for timing fix -- Sand)
output last_st_w
; // Last store in write buffer and in W-stage
output derr_wbstb
; // Data error write buffer strobe
output r_dc_in_par
; // D$ address in PAR
output r_ic_in_par
; // I$ address in PAR
output r_ic_tlb
; // I$ address translation attempted last cycle
output r_dc_tlb
; // D$ address translation attempted last cycle
output r_wr_tlb
; // WB address translation attempted last cycle
output pipe_moved
; // pipe_moved decode
output dfetch
; // D$ lookup this stage (W) - perf cntr trigger
output fp_ld_mask
; // FP mask for loads (until trap window done).
output precharge_early_0
; // Precharge page 0 (page miss)
output precharge_early_1
; // Precharge page 1 (page miss)
output mm_hold_rst
;
output afx_qbusy
; // AFX Queue busy
output [1:0] wb_3_asi_buf
; // wb_3_asi with buf to slow it down, Yup SLOW!!!
input tw_tlb_nxt
;
input cntrl_spc_err
;
input dcc_idle
;
input hold_par
;
input mc_mstb_l
; // input mdata strobe from mcb
input normal_asi_w
; // normal asi in w
input invalid_wb_entry
; // st has trapped. mask wr_buf_valid if only 1 entry
input mm_dnocache_done
; // used to indicate that asi op so mreq = 0
input sb_data_clr
; // signal that sb_data_avail is being serviced
input sbc_pa_valid
; // pa valid to sbc
input [3:0] sb_ioreq
; // input from sbc showing type of request
input sb_ioreq_vld
; // strobe from sbc showing valid sb_ioreq code
input tw_par
; // tlb used for tablewalk this cycle
input ld_op_e
; // read from iu
input st_op_e
; // write from iu
input fpu_mem_e
; // fpu mem op in E-stage
input fp_trap_fix
; // FPU trap may occur at anytime
input [1:0] wb_3_size
; // size of xaction from wb_3 (byte, hw, wrd, dw)
input [1:0] wb_valid
; // size of xaction from wb_3 (byte, hw, wrd, dw)
input [1:0] iu_size_e
; // size of xaction from iu (byte, hw, wrd, dw) in e
input [5:0] iu_asi_e
; // e stage asi from iu
/* need to make sure next signal is valid for iva or else need _d version */
input tlb_miss
; // tlb miss
input ld_par
; // load par with normal translation result
input ld_mreq_tw
; // load mreq during table walk
input pcr_dcen
; // data cache enable (from PCR)
input pcr_icen
; // instruction cache enable (from PCR)
input tw_read_req
; // need to read pte or ptp for table walk
input tw_write_req
; // need to write pte table walk
input mem_issue_req
; // issue a request to memory (from mreq_reg)
input iu_pipe_hold
; // indication that the pipeline is being held
input iu_pipe_hold_fast
; // indication that the pipeline is being held
input m_miss
; // modified bit output from tlb
input tlb_c_bit
; // cacheable bit output from tlb
input bypass_mmu_asi_w
; // mmu bypass caused by asi 0x20 in w stage
input mmu_bypass
; // mmu bypass this cycle from any reason
input pcr_mmuen
; // PCR[00] - MMU enable
input pcr_ac
; // PCR[15] - alternate cacheability enable
input ldst_st
; // indication that mreq needs to move from ld to st
input iu_in_trap
; // iu in trap condition, cancel write pending
input io_space
; // address decode indicating sb address space
input cntl_space
; // address decode indicating cntl address space
input mem_space
; // address decode indicating mem address space
input fb_space
; // address decode indicating FB address space
input pci_space
;
input flush_iopte
; // flush IO PTE
input tw_err
;
input priv_err_x
;
input prtct_err_x
;
input sb_cyc_pnd
; // cpu cycle pending in sbc
input io_tlb_err
;
input tw_init_par
;
input probe
;
input probe_done
;
input [1:0] tw_sm_lvl
;
input r_acc_err_tw
;
input tw_prb_drdy
;
input iacc_miss
;
input dacc_miss
;
input enbl_soft_tw
;
input ic_tlb
; // Par control in IC_TLB state
input ic_tlb_state
; // Par control in IC_TLB state
input dc_tlb
; // Par control in DC_TLB state
input dc_tlb_state
; // Par control in DC_TLB state
input wr_tlb
; // Par control in WR_TLB state
input io_tlb
; // Par control in IO_TLB state
input ic_tlb_tw
; // Par control in IC_TLB_TW state
input dc_tlb_tw
; // Par control in DC_TLB_TW state
input wr_tlb_tw
; // Par control in WR_TLB_TW state
input io_tlb_tw
; // Par control in IO_TLB_TW state
input ic_in_par
; // I-cache address in PAR
input dc_in_par
; // D-cache address in PAR
input par_cbit
;
input ipar_cbit
;
input dpar_cbit
;
input ic_par_state
;
input dc_par_state
;
input mop_c_bit
;
input ic_miss_or_part
;
input ic_miss_and_part
;
input it_hit_f
; // itag hit in f stage ** ASSERTED LOW **
input dc_miss_or_part
;
input dc_miss_and_part
;
input dt_hit_w
;
input dc_miss_sustain
;
input dc_stream
;
input ic_miss_sustain
;
input mm_wbstb
;
input [1:0] wb_3_asi
;
input mm_sb_err
;
input mmu_asi_op
;
input dc_issue_req
;
input asi_dcd3
;
input r_pipe_moved
;
input page_hit
;
input page_miss0
;
input page_miss1
;
input req_pending
;
input mc_mbsy
;
input r_mbsy
;
input sup_nalloc
;
input r_sup_mode
;
input dp_bp_hit
;
input [11:00] mmu_brkpt_en
;
input [2:0] r_p_reply_dec
; // AFX queue status (# of entries)
input afx_qlvl
; // AFX queue read level control bit
input marb_busy
; // Memory state machine busy
input aarb_bsy
; // ASI state machine busy
input r_mem_issue_req
;
input sbus_id_hit
;
input cs_st_op
;
input ss_clock
; // input clock
input ss_reset
; // input reset
wire pio_write_op
;
wire write_w
;
wire r_srd_cs
;
wire icen_int
;
wire dcen_int
;
wire pcr_icen;
wire pcr_dcen;
wire pcr_mmuen;
wire pcr_ac;
wire [3:0] mreq_in
;
wire wr_xlate_in
;
wire rd_xlate_in
;
wire ldsto_xlate_in
;
wire iu_wr_xlate_in
;
wire r_iu_rd_xlate
;
wire r_iu_ldsto_xlate
;
wire iusb_wr_xlate_in
;
wire iucs_wr_xlate_in
;
wire r_iusb_rd_xlate
;
wire r_iucs_rd_xlate
;
wire r_iusb_ldsto_xlate
;
wire r_iucs_ldsto_xlate
;
wire io_xlate_in
;
wire [3:0] mreq_rdy
;
wire [2:0] read_rdy
;
wire [2:0] wrt_rdy
;
wire pg_md_in
;
wire hld_mreq_reg
;
wire asi_s_bit
;
wire no_ireq_in
;
wire r_srd
;
wire swr
;
wire srd_ioreq
;
wire cntl_st
;
wire cntl_ld
;
wire cntl_st_sb
;
wire cntl_ld_sb
;
wire [1:0] sbsize_in
;
wire redo_iusb_op
;
wire redo_iurd_op
;
wire can_wr_due_sb_pnd
;
wire can_wr_due_sbatom
;
wire dpa_dcd_w
;
wire ipa_dcd_f
;
wire mm_dmhold_r
;
wire r_dxlate_err
;
wire ic_adr_miss
;
wire ioxlate_done
;
wire iu_ldsto_e
;
/***************************************************************************/
/***************************************************************************/
// define sb_ioreq operations
parameter [3:0] SNOP = 4'b0000,
SRD64 = 4'b0111,
SRD128 = 4'b0101,
SRD256 = 4'b0001,
SCRDDATA = 4'b0100,
SWR8 = 4'b1001,
SWR16 = 4'b1010,
SWR32 = 4'b1000,
SWR64 = 4'b1100,
SXLATE = 4'b1101,
SWR128 = 4'b1110;
/*** Discreet register used to hold MMU state either 1 cycle, ***************/
/*** or to keep in synch with the IU pipeline. ***************/
wire iabort_in
; //forward
wire r_io_space;
MflipflopR_1 io_space_ff_1(r_io_space,io_space,ss_clock,hold_par,ss_reset) ;
wire r_cntl_space;
MflipflopR_1 cntl_space_ff_1(r_cntl_space,cntl_space,ss_clock,hold_par,ss_reset) ;
wire r_mem_space;
MflipflopR_1 mem_space_ff_1(r_mem_space,mem_space,ss_clock,hold_par,ss_reset) ;
wire r_fb_space
;
MflipflopR_1 fb_space_ff_1(r_fb_space,fb_space,ss_clock,hold_par,ss_reset) ;
wire r_pci_space;
MflipflopR_1 pci_space_ff_1(r_pci_space,pci_space,ss_clock,hold_par,ss_reset) ;
assign mm_fb_req = r_fb_space ;
wire r_dc_tlb;
wire r_dc_tlb_in
= dc_tlb & ~dabort_in;
Mflipflop_r_1 dc_tlb_ff_1(r_dc_tlb,r_dc_tlb_in,~ss_reset,ss_clock) ;
wire r_ic_tlb;
wire r_ic_tlb_in
= ic_tlb & ~iabort_in;
Mflipflop_r_1 ic_tlb_ff_1(r_ic_tlb,r_ic_tlb_in,~ss_reset,ss_clock) ;
wire r_wr_tlb;
Mflipflop_r_1 wr_tlb_ff_1(r_wr_tlb,wr_tlb,~ss_reset,ss_clock) ;
wire r_io_tlb
;
Mflipflop_r_1 io_tlb_ff_1(r_io_tlb,io_tlb,~ss_reset,ss_clock) ;
/*** The it_hit_f signal has been changed to be ASSERTED LOW ***/
/*** This change was made as a timing optimization (hand edit) ***/
assign ic_miss = ic_miss_or_part | (it_hit_f & ic_miss_and_part);
wire r_ic_miss;
Mflipflop_r_1 ic_miss_ff_1(r_ic_miss,ic_miss,~ss_reset,ss_clock) ;
assign dc_miss = dc_miss_or_part | (~dt_hit_w & dc_miss_and_part);
wire r_dc_miss;
Mflipflop_r_1 dc_miss_ff_1(r_dc_miss,dc_miss,~ss_reset,ss_clock) ;
wire r_dc_in_par;
Mflipflop_r_1 dc_in_par_ff_1(r_dc_in_par,dc_in_par,~ss_reset,ss_clock) ;
wire r_ic_in_par;
Mflipflop_r_1 ic_in_par_ff_1(r_ic_in_par,ic_in_par,~ss_reset,ss_clock) ;
assign iu_ldsto_e = st_op_e & ld_op_e ;
// same function, simpler form
wire asi_done_in
= asi_done & iu_pipe_hold_fast | mm_dnocache_done;
wire asi_done;
Mflipflop_r_1 asi_done_ff_1(asi_done,asi_done_in,~ ss_reset,ss_clock) ;
wire r_tlb_miss;
Mflipflop_r_1 tlb_miss_ff_1(r_tlb_miss,tlb_miss,~ss_reset,ss_clock) ;
/*** Created a qualified r_tlb_miss with the PTE Mbit forced miss. ***/
wire r_dcmbit_miss
;
wire r_wrmbit_miss
;
wire r_tlb_miss_m
= r_tlb_miss | r_dcmbit_miss | r_wrmbit_miss;
wire r_tlb_miss_tw;
Mflipflop_r_1 tlb_miss_tw_ff_1(r_tlb_miss_tw,tlb_miss_tw,~ss_reset,ss_clock) ;
wire pipe_moved;
Mflipflop_r_1 pipe_moved_ff_1(pipe_moved,~iu_pipe_hold,~ss_reset,ss_clock) ;
wire r_ld_par
;
Mflipflop_r_1 ld_par_ff_1(r_ld_par,ld_par,~ss_reset,ss_clock) ;
/************************************************************************/
/*** Memory Precharge decodes *****/
assign precharge_early_0 = page_miss0 & req_pending & ~mc_mbsy & r_mbsy ;
assign precharge_early_1 = page_miss1 & req_pending & ~mc_mbsy & r_mbsy ;
assign mm_page = page_hit & ~(page_miss0 | page_miss1) ;
/************************************************************************/
/*** Decode translation mask for FP loads *****/
/*** fp_ld_mask is used to inhibit traps during translation of a *****/
/*** a FP load. This is needed since the FPC can assert a trap at *****/
/*** anytime during the ldf (different than the rest of the swift *****/
/*** trap model). If the translated ldf address is to memory, *****/
/*** perform the ldf. Otherwise wait until the trap window is *****/
/*** over (fp_trap_fix goes away). [added for performance.] *****/
/*** *****/
/*** decode FPU loads, as these need to mask out traps for a while *****/
wire fp_ld_e
= fpu_mem_e & ld_op_e ;
wire fp_ld_w
;
MflipflopR_1 fp_ld_w_ff_1(fp_ld_w,fp_ld_e,ss_clock,iu_pipe_hold,ss_reset) ;
wire r_fp_trap_fix
;
Mflipflop_r_1 fp_trap_fix_ff_1(r_fp_trap_fix,fp_trap_fix,~ss_reset,ss_clock) ;
wire fp_ld_mask_in
;
wire fp_ld_mask;
Mflipflop_r_1 fp_ld_mask_ff_1(fp_ld_mask,fp_ld_mask_in,~ss_reset,ss_clock) ;
/*** Set mask on every FP load (1-cycle after pipe held to allow *****/
/*** normal traps to occur) *****/
/*** *****/
/*** Clear mask when: *****/
/*** - translation is aborted (exception or error) *****/
/*** - Memory request has been made (mmu is done with op) *****/
/*** - No FP load in W-stage (safety net in case pipe moved) *****/
/*** - Translated address and it was to memory space *****/
/*** (if address was to memory space, clear on request) *****/
/*** - Translated address and FPU no longer in trap mode *****/
/*** *****/
assign fp_ld_mask_in = (fp_ld_w & pipe_moved) |
(fp_ld_mask & ~(mm_dabort | dc_issue_req | ~fp_ld_w |
(r_dc_miss & r_dc_tlb & ~r_tlb_miss &
(~r_mem_space | ~r_fp_trap_fix))));
wire r_trap_w;
Mflipflop_r_1 trap_w_ff_1(r_trap_w,iu_in_trap,~ss_reset,ss_clock) ;
/************************************************************************/
/*** Check if wb empty OR if writing last entry *************************/
/*** wb_valid[1] - write buffer 3 valid *************************/
/*** wb_valid[0] - write buffer 2 valid *************************/
wire last_wb_entry
= (~wb_valid[0] & wb_valid[1]) ;
wire r_last_wb_entry
;
Mflipflop_r_1 last_wb_entry_ff_1(r_last_wb_entry,last_wb_entry,~ss_reset,ss_clock) ;
wire st_miss_w
= last_wb_entry & write_w & dc_miss & ~ldsto_w;
wire st_miss_x ;
Mflipflop_r_1 st_miss_ff_1(st_miss_x,st_miss_w,~ss_reset,ss_clock) ;
// Duplicated to reduce load to rl_mmu_regs.v (Timing fix -- Sand)
wire st_miss_x_reg ;
Mflipflop_r_1 st_miss_reg_1(st_miss_x_reg,st_miss_w,~ss_reset,ss_clock) ;
assign last_st_w = last_wb_entry & write_w & ~r_trap_w;
/*** st_miss_c is only valid the cycle of issue_req ************/
assign st_miss_c = st_miss_x & par_cbit ;
/************************************************************************/
/*** wb_empty gets SET 1-cycle late, but is cleared correct cycle ******/
/*** this is corrected in the wr_buf_valid decode ******/
/*** ******/
/*** Mark write buffer empty when: ******/
/*** D-cache invalidates write buffer entry and it's the only one ****/
/*** Only last write buffer valid and it is strobed out. ******/
/*** Last write buffer entry is not valid (initialize). ******/
wire wb_empty_in
= (last_wb_entry & invalid_wb_entry) |
(r_last_wb_entry & invalid_wb_entry & mm_wbstb) |
(mm_wbstb & last_wb_entry) |
~wb_valid[1] ;
wire wb_empty;
Mflipflop_r_1 wb_empty_ff_1(wb_empty,wb_empty_in,~ss_reset,ss_clock) ;
wire st_op_w;
MflipflopR_1 st_op_w_ff_1(st_op_w,st_op_e,ss_clock,iu_pipe_hold,ss_reset) ;
/************************************************************************/
/*** write_w decode - indicates write in W-stage ***********************/
/*** decode is necessary since ldst indicate st_op_w before the ***/
/*** write buffer is marked valid for the current operation. This ***/
/*** can lead to confusion when 1 other write buf entry is valid, ***/
/*** and the current op is a ldst miss. ***/
/*** The decode qualifies st_op_w during ldsto_w to be valid only ***/
/*** during the store portion of the ldst operation. ***/
/*** - An exception to the above case was found when a trap occurs ***/
/*** with the ldsto in the W-stage. Since the D$ will set the ***/
/*** write buffer valid (in W+1), the MMU needs to indicate a ***/
/*** 'write_w' to allow proper decode of 'wb_valid'. Since ***/
/*** 'r_trap_w' will not be asserted until W+1, this will always ***/
/*** track with the wb_valid bit being asserted. [This is due to ***/
/*** how the IU masks D-stage read/write signals, but not E/W-stage***/
/*** signals. Since ldsto is a 2-cycle op, trap will not be ***/
/*** asserted in only the 2nd cycle]. ***/
assign write_w = st_op_w & (ldst_st | ~read_w) ;
wire write_x;
Mflipflop_r_1 write_x_ff_1(write_x,write_w,~ss_reset,ss_clock) ;
/************************************************************************/
/*** Mark write buffer Valid when: ******/
/*** 1. Write buffer is NOT empty ******/
/*** 2. write in W-stage, and has not been invalidated. ******/
/*** [2nd term covers 1-cycle delay in clearing 'wb_empty'.] ******/
/*** *. Note that this is for translation cycle only, and is NOT ******/
/*** cleared on traps (iu_in_trap). The 'execute' stage decode *****/
/*** will NOT be set if a trap occurs, which should prevent ******/
/*** any action based on the translation. ******/
/*** - Clear wb_valid_x if trap occurs on ld portion of a ldsto ******/
/*** ******/
/*** - Added '~mm_wbstb' to clear wb_valid_t 1-cylce earlier. ******/
/*** This help fix a timing problem on asserting 'mm_wbstb' ******/
/*** for errors (daborts), since it masks the clearing of ******/
/*** the wb_valid signal for the 1 additonal cycle. ******/
assign wb_valid_t = (~wb_empty | (write_w & last_wb_entry & ~derr_wbstb) &
~(r_last_wb_entry & invalid_wb_entry & derr_wbstb) ) ;
wire wb_valid_x_in
= (~wb_empty |
(write_w & ~invalid_wb_entry & last_wb_entry)) &
~(r_last_wb_entry & invalid_wb_entry & mm_wbstb) ;
// ~(ldst_st & r_trap_w & last_wb_entry) ;
/*** Write buffer valid for the Execute stage of MMU ******/
wire wb_valid_x ;
Mflipflop_r_1 wb_vaild_x_ff_1(wb_valid_x,wb_valid_x_in,~ss_reset,ss_clock) ;
// Duplicated to reduce load to rl_mmu_regs.v (Timing fix -- Sand)
wire wb_valid_x_reg;
Mflipflop_r_1 wb_vaild_x_reg_1(wb_valid_x_reg,wb_valid_x_in,~ss_reset,ss_clock) ;
/************************************************************************/
/*** Mask ASI decodes (non-device ASIs) ******/
/*** Non-device ASIs are non-cacheable, and therefore are always******/
/*** executed from the W-stage. To take advantage of this fact, ******/
/*** the MMU must ensure that no write buffer operations are ******/
/*** pending (store hits), since these must be executed first. ******/
/*** 'asidcd_mask' is used to mask out the non-device ASI decodes ****/
/*** until all store hits have completed. ******/
/*** ******/
/*** Since the 1st cycle of a st creates a timing problem in ******/
/*** decoding the correct ASI, the reg'd wb valid status is ******/
/*** qualified with the 1st cycle of the ASI to determine if ******/
/*** previous store hits are still in the write buffer. ******/
wire [1:0] r_wb_valid
;
Mflipflop_r_2 wb_vaild_ff_2(r_wb_valid,wb_valid,~ss_reset,ss_clock) ;
assign asidcd_mask = (read_w & ~wb_empty) |
(st_op_w & ((pipe_moved & r_wb_valid[1]) | r_wb_valid[0])) ;
/************************************************************************/
/*** Decode sb_ioreq size for DMA access to AFX frame buffer ***/
/*** dma_size is encoded as follows: ***/
/*** ***/
/*** 00 - byte access ***/
/*** 01 - halfword access ***/
/*** 10 - word access ***/
/*** 11 - double word access or greater (bursts) ***/
wire [1:0] dma_size
;
assign dma_size[1] = ~r_sb_ioreq[3] | // ALL reads
(r_sb_ioreq[3] & (r_sb_ioreq[2] | // SWR64, SWR128
(~r_sb_ioreq[1] & ~r_sb_ioreq[0]))) ; // SWR32
assign dma_size[0] = ~r_sb_ioreq[3] | // ALL reads
(r_sb_ioreq[3] & (r_sb_ioreq[2] | // SWR64, SWR128
r_sb_ioreq[1])) ; // SWR16
/************************************************************************/
/*** AFX Queue Busy decode ***/
/*** ***/
/*** Decode afx_qbusy based on the status of the AFX queue, and ***/
/*** the type of operation pending (read/write). ***/
/*** - Writes set the afx_qbusy signal if the queue is full ***/
/*** (p_reply_dec == 3'b100) ***/
/*** - Reads set afx_qbusy based on the afx_qlvl bit. ***/
/*** When afx_qlvl = 0, ***/
/*** afx_qbusy is set when (p_reply_dec > 3'b000) ***/
/*** When afx_qlvl = 1, ***/
/*** afx_qbusy is set when (p_reply_dec > 3'b001) ***/
assign afx_qbusy = ((read_w | (write_x & ~wb_valid_x)) &
((afx_qlvl & (r_p_reply_dec > 3'b001)) |
(~afx_qlvl & (r_p_reply_dec > 3'b000)))) |
(wb_valid_x & (r_p_reply_dec > 3'b011)) ;
//wire afx_qbusy_in = ((read_w | (write_x & ~wb_valid_x)) &
// ((afx_qlvl & (p_reply_dec > 3'b001)) |
// (~afx_qlvl & (p_reply_dec > 3'b000)))) |
// (wb_valid_x & (p_reply_dec > 3'b011)) ;
//
//ASFFRHA __spare_gate_ff_0_g1_v12_0_s918 (.H(1'b0),.D(afx_qbusy_in),
// .Q(afx_qbusy),.CK(ss_clock), .SM(1'b0),.SI(1'b0),.R(~ss_reset));
/************************************************************************/
wire [1:0] size_w;
MflipflopR_2 size_w_ff_2(size_w,iu_size_e,ss_clock,iu_pipe_hold,ss_reset) ;
assign ldd_w = read_w & (size_w == 2'b11) ;
wire std_x_in
= wb_valid_x_in & (wb_3_size == 2'b11) ;
wire std_x ;
Mflipflop_r_1 std_x_ff_1(std_x,std_x_in,~ss_reset,ss_clock) ;
/*** Ensure read in E-stage is not part of an ldd ***/
// What happens when you get ldd ldd back to back ?
// wire read_e = ld_op_e & ~ldd_w ;
wire read_e
= ld_op_e ;
wire read_w;
MflipflopR_1 read_w_ff_1(read_w,read_e,ss_clock,iu_pipe_hold,ss_reset) ;
//Duplicated to reduce load to rl_mmu_regs.v (timing fix --Sand)
wire read_w_reg;
MflipflopR_1 read_w_reg_1(read_w_reg,read_e,ss_clock,iu_pipe_hold,ss_reset) ;
assign dfetch = st_op_w | read_w ; /* D$ lookup for this stage */
/************************************************************************/
/*** ldsto decode ***/
/*** Messy decode to ensure we're looking at a ldsto and not ***/
/*** a previous store overlapping with a current load. ***/
/*** ***/
/*** r_ldsto_w - decode for ldsto in W-stage ***/
/*** r_ldsto_w_val - reg'd decode of valid ldsto in W-stage ***/
/*** (valid means D$ checked the tag, needed for streaming) ***/
/*** ldsto_w_val - optimize case when pipe is moving and not in ***/
/*** D$ streaming. This was needed because dcc_idle was a ***/
/*** bad timing path (so it had to be reg'd), but dcc_idle ***/
/*** is assumed when pipe is moving and D$ is not streaming. ***/
/*** ldsto_w - final decode of VALID ldsto in W-stage ***/
/*** ***/
/************************************************************************/
wire r_ldsto_w;
MflipflopR_1 ldsto_w_ff_1(r_ldsto_w,iu_ldsto_e,ss_clock,iu_pipe_hold,ss_reset) ;
wire r_ldsto_w_val
;
wire ldsto_w_val_in
= (dcc_idle & r_ldsto_w) | (r_ldsto_w_val & ~pipe_moved);
Mflipflop_r_1 ldsto_w_val_ff_1(r_ldsto_w_val,ldsto_w_val_in,~ss_reset,ss_clock) ;
wire ldsto_w_val
= pipe_moved ? ~dc_stream :
(r_ldsto_w_val | (dcc_idle & r_ldsto_w)) ;
assign ldsto_w = r_ldsto_w & ldsto_w_val ;
wire ldsto_x;
Mflipflop_r_1 ldsto_x_ff_1(ldsto_x,ldsto_w,~ss_reset,ss_clock) ;
// This signal is used to hold off watchdog reset while there is still
// IU-initiated MMU/cache activity going on.
// Also see the comments in rl_rst_cntl.v .
wire mm_hold_rst = wb_valid_x | dvma_req_x |
req_pending | marb_busy | aarb_bsy ;
/*** Data memory op ABORT signal based on an error detected during xlate. ***/
wire mm_dabort;
MflipflopR_1 dabort_ff_1(mm_dabort, dabort_in, ss_clock,1'b0,ss_reset) ;
/*** Instr memory op ABORT signal based on error detected during xlate. ***/
// See bug 532/547 and timing bug 2.
// For timing bug 2, we register the (tw_err & ic_tlb_tw) and
// to iabort, effectively adding a cycle to imhold in those cases.
assign iabort_in = (~r_tlb_miss & ic_miss_sustain &
r_ic_tlb & (priv_err_x | prtct_err_x)) |
(ic_tlb_tw & (tw_err | r_acc_err_tw)) | iacc_miss ;
wire mm_iabort ;
Mflipflop_r_1 iabort_ff_1(mm_iabort,iabort_in,~ss_reset,ss_clock) ;
wire [1:0] mm_sbsize_unbuf
;
MflipflopR_2 size_sb_reg_2(mm_sbsize_unbuf,sbsize_in,ss_clock,~ld_par,ss_reset) ;
wire [5:0] asi_w;
MflipflopR_6 asi_w_reg_6(asi_w,iu_asi_e,ss_clock,iu_pipe_hold,ss_reset) ;
wire [3:0] mm_mreq;
Mflipflop_r_4 mreq_reg_4(mm_mreq,mreq_rdy,~ss_reset,ss_clock) ;
// REGR(mreq_reg,4,mm_mreq,mreq_rdy,ss_clock,hld_mreq_reg,ss_reset)
// since one cycle delay for dvma write operation
// , a make up registered signal r_sb_ioreq_hld is used
// to avoid sb_ioreq_hld assert for more than one cycle
// this will happen if a 8 byte back to back dvma write occur
wire r_sb_ioreq_hld
;
wire sb_ioreq_hld
= ~(sb_ioreq_vld | sbc_pa_valid | sb_data_clr | mm_sb_err);
Mflipflop_r_1 sb_ioreq_hld_reg_1(r_sb_ioreq_hld,sb_ioreq_hld,~ss_reset,ss_clock) ;
wire [3:0] r_sb_ioreq;
MflipflopR_4 sb_ioreq_reg_4(r_sb_ioreq,sb_ioreq,ss_clock,sb_ioreq_hld,ss_reset) ;
/*** next signals are input to reg indicating size of iu op to sb */
assign sbsize_in[1] = ic_in_par | (~ic_in_par & size_w[0]);
assign sbsize_in[0] = ic_in_par | (~ic_in_par &
(size_w==2'b11 | size_w==2'b00));
assign srd_ioreq = ((sb_ioreq == SRD64) | (sb_ioreq == SRD128) |
(sb_ioreq == SRD256));
wire swr_ioreq
= ((sb_ioreq == SWR8) | (sb_ioreq == SWR16) |
(sb_ioreq == SWR32) | (sb_ioreq == SWR64) |
(sb_ioreq == SWR128));
wire sxlate_ioreq
= (sb_ioreq == SXLATE) ;
wire data_avail
= (sb_ioreq == SCRDDATA) ;
wire r_swr_ioreq
;
MflipflopR_1 swr_ff_1(r_swr_ioreq,swr_ioreq,ss_clock,sb_ioreq_hld,ss_reset) ;
assign sb_write = r_swr_ioreq ;
wire r_sxlate_ioreq ;
MflipflopR_1 sxlate_ff_1(r_sxlate_ioreq,sxlate_ioreq,ss_clock,sb_ioreq_hld,ss_reset) ;
assign r_sxlate = (r_sxlate_ioreq |
(r_srd_ioreq & r_io_space & ~r_cntl_space & ~r_tlb_miss));
wire r_srd_ioreq ;
MflipflopR_1 srd_ff_1(r_srd_ioreq,srd_ioreq,ss_clock,sb_ioreq_hld,ss_reset) ;
wire sb_data_avail ;
MflipflopR_1 sb_data_avail_ff_1(sb_data_avail,data_avail,ss_clock,sb_ioreq_hld,ss_reset) ;
assign r_srd = r_srd_ioreq & ~r_io_space;
assign r_srd_cs = ((r_sb_ioreq == SRD64) & r_cntl_space);
wire dvma_req_in
= swr_ioreq | srd_ioreq | sxlate_ioreq ;
wire dvma_req_x ;
MflipflopR_1 dvma_req_ff_1(dvma_req_x,dvma_req_in,ss_clock,sb_ioreq_hld,ss_reset) ;
/*** The S-stage dvma_req decode is chopped 1-cycle to prevent an *****/
/*** unnecessary IO_TLB. *****/
assign dvma_req_s = dvma_req_x & ~(sbc_pa_valid | mm_sb_err | cs_st_op) ;
/***** Forces a tlb_miss when the M-bit needs to be set in the PTE. ***/
/*** tlb_miss is timing critical, may want to break it out ********/
wire mbit_dctlb_miss
= (dc_tlb & (last_st_w | (ldsto_w & wb_empty))) &
~r_trap_w & ~asi_dcd3 & ~mmu_bypass &
m_miss & ~tlb_miss & normal_asi_w;
wire mbit_wrtlb_miss
= wr_tlb & m_miss & ~tlb_miss;
Mflipflop_r_1 dc_mbit_miss_ff_1(r_dcmbit_miss,mbit_dctlb_miss,~ss_reset,ss_clock) ;
Mflipflop_r_1 wr_mbit_miss_ff_1(r_wrmbit_miss,mbit_wrtlb_miss,~ss_reset,ss_clock) ;
assign strt_tw_for_m = (r_wrmbit_miss | (r_dcmbit_miss & dc_miss_sustain)) &
tw_par & ~(prtct_err_x | priv_err_x | enbl_soft_tw);
assign dmiss_for_m = (r_wrmbit_miss | (r_dcmbit_miss & dc_miss_sustain)) &
enbl_soft_tw & ~(r_trap_w | prtct_err_x | priv_err_x);
/*** Indicate that Modified bit should be set for PTE *******************/
/*** case 1 - D$ tablewalk for last write buf entry (store miss) ***/
/*** case 2 - ldst in W-stage and write buf empty (ldst 2 cyc op) ***/
/*** case 3 - Write buf tablewalk (store hit) ***/
wire set_m_on_tw_in
= (dc_tlb_tw & (last_st_w | (ldsto_w & wb_empty))) |
wr_tlb_tw;
wire set_m_on_tw ;
Mflipflop_r_1 set_m_ff_1(set_m_on_tw,set_m_on_tw_in,~ss_reset,ss_clock) ;
/*************************************************************************/
/*** Could make this decode faster by using the tlb_miss from the CAM */
/*** combined with the compare valid signal. */
assign tlb_miss_tw = tlb_miss & ~enbl_soft_tw ;
/*************************************************************************/
/*** Data Access type decode (set-up stage) *****/
assign data_acc_s[2] = wb_valid_t |
(dc_miss_sustain ? st_op_w : st_op_e) ;
assign data_acc_s[1] = (wb_valid_t ? ~wb_3_asi_buf[1] :
(dc_miss_sustain ?
(~asi_w[1]) : (~iu_asi_e[1]))) ;
assign data_acc_s[0] = (wb_valid_t ? wb_3_asi_buf[0] :
(dc_miss_sustain ? asi_w[0] : iu_asi_e[0])) ;
wire acc_err_tw_hld
;
wire acc_err_tw
= (r_acc_err_tw | acc_err_tw_hld) & tw_par ;
This page: |
Created: | Thu Aug 19 11:56:47 1999 |
| From: |
../../../sparc_v8/ssparc/mmu/m_mmu_cntl/rtl/rl_mmu_lgc.v
|