/******************************************************************************/
/* */
/* 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_tw_sm.v
***
****************************************************************************
****************************************************************************/
//***************************************************************************
// @(#)rl_tw_sm.v 1.109 5/15/94
// rl_tw_sm.v
//
// Description:
// Preprocessed MMU Table Walk State Machine
//
// Dependencies: Always..
//
//***************************************************************************
/* functional model of MMU table walk state machine */
module rl_tw_sm
(
root_tw,
pt1_tw,
pt2_tw,
tw_done,
io_s_bit,
tw_abort,
tw_tlb_vbit,
tw_io_bit,
lvl_probe_hld,
tlb_cam_reload,
co_in,
tw_rewrite_cam,
ldtlb_data_tw,
ldtlb_tag_tw,
va_sel_par_in,
tw_read_req,
read_word_mreq,
tw_write_req,
m_in,
ptp_in,
va_s_in,
tlb_ram_lvl,
tlb_cam_lvl,
tw_tlb_nxt,
tw_sm_lvl,
tw_err_lvl,
ld_par_tw,
tw_init_par,
ld_mreq_tw,
tlb_flush,
r_flush_entry,
tlb_update,
tw_trcr_hld,
tw_addr_err,
tw_xlat_err,
tw_prb_drdy,
tw_prb_err,
probe_invalid,
probe_done,
flush_done,
tw_sin,
tw_pte_chk,
io_tw_wrt,
sr_tw_wrt,
cam_reg_hld,
ram_reg_hld,
asi_cam_read,
asi_ram_read,
/*** Inputs ***/
io_tlb_tw,
io_tlb,
dvma_req_x,
set_m_on_tw,
strt_tw_for_m,
mdata_in_et,
mdata_in_acc,
mdata_in_r,
mdata_in_m,
tlb_miss,
asi_done,
mmstben,
virt_ptp2,
mmdaten,
mc_mstb_l,
st_miss_x,
r_dc_tlb,
dc_tlb_tw,
flush_tlb_pte,
flush_tlb_seg,
flush_tlb_reg,
flush_tlb_ctx,
flush_tlb_all,
flush_iopte,
flush_ioall,
probe_err,
probe,
flush,
probe_entire,
probe_lvl0,
probe_lvl1,
probe_lvl2,
probe_lvl3,
r_acc_err_tw,
mm_misc2cf,
tw_perr,
r_tw_err,
tw_par,
mmu_asi_op,
r_trap_w,
sb_data_avail,
enbl_soft_tw,
ss_clock,
ss_reset);
output root_tw
; // rootmem or rootwrt
output pt1_tw
; // pt1mem or pt1wrt
output pt2_tw
; // pt2mem or pt2wrt
output tw_done
; // indicates that table walk is done
output tw_abort
; // indicates table walk was aborted because of dvma_req
output lvl_probe_hld
; // hold PTP/PTE coming from memory
output tw_tlb_vbit
; // tlb v bit for tw write to tlb
output tw_io_bit
; // tlb io_bit
output tlb_cam_reload
; // wrap cam_reg back onto cam_data_in
output co_in
; // indicates compare override
output tw_rewrite_cam
; // indicates that table walk will rewrite CAM for L1,L2 PTE
output ldtlb_data_tw
; // indicates that tlb data is written with ptp or pte
output ldtlb_tag_tw
; // indicates that tlb tag is written with ptp or pte
output va_sel_par_in
; // indicates that PAR is TLB tag input next cycle
output tw_read_req
; // memory read of word at address in par required
output read_word_mreq
; // early mem read of word at address in par required
output tw_write_req
; // memory write of word at address in par required
output m_in
; // modified bit location input to ram (bit 6)
output ptp_in
; // ptp bit input to ram
output va_s_in
; // superviosr bit input to cam
output io_s_bit
; // superviosr bit input to cam
output [2:0] tlb_ram_lvl
; // level field input to ram
output [2:0] tlb_cam_lvl
; // level field input to cam
output tw_tlb_nxt
; // tlb being used for table walk next cycle
output [1:0] tw_sm_lvl
; // level of tablewalk
output [1:0] tw_err_lvl
; // level of tablewalk during error
output ld_par_tw
; // ld par signal during table walk
output tw_init_par
; // CTPR/IBAR select
output ld_mreq_tw
; // ld mreq signal during table walk
output tlb_flush
; // TLB flush control signal for PTE flushes
output r_flush_entry
; // TLB flush last cycle
output tlb_update
; // TLB update from read word in progress
output tw_trcr_hld
; // Hold TRCR register value during TAG update
output tw_addr_err
; // interanl address error detected.
output tw_xlat_err
; // translation error detected.
output tw_prb_drdy
; // Probe data ready next cycle.
output tw_prb_err
; // Probe error during tablewalk
output probe_invalid
; // Invalid Probe entry
output probe_done
; // Probe done
output flush_done
; // flush done
output tw_sin
; // Tablewalk CAM Supervisor input bit
output tw_pte_chk
; // Tablewalk PTE privelege/protection check state
output io_tw_wrt
; // IO Tablewalk sm write state
output sr_tw_wrt
; // IU Tablewalk sm write state
output cam_reg_hld
; // TLB CAM output register hold
output ram_reg_hld
; // TLB RAM output register hold
input asi_cam_read
; // hold cam shadow for asi read
input virt_ptp2
; //
input dc_tlb_tw
; //
input dvma_req_x
; //
input asi_ram_read
; // hold ram shadow register for asi read
input io_tlb_tw
; // IO TLB reference next (and current in tw) cycle
input io_tlb
; // IO TLB reference next (and current in tw) cycle
input set_m_on_tw
; // set modified bit on a table walk due to write op
input strt_tw_for_m
; // set modified bit on a table walk due to write op
input [1:0] mdata_in_et
; // et field of incoming data (bits [1:0])
input [1:0] mdata_in_acc
; // acc[2:1] field of incoming data (bits [4:3])
input mdata_in_r
; // r field of incoming data (bit 5)
input mdata_in_m
; // m field of incoming data (bit 6)
input tlb_miss
; // tlb miss this cycle
input mmstben
; // next mc_mstb_l means mmu data is ready
input mmdaten
; // means that write has started.
input mc_mstb_l
; // input mdata strobe from mcb
input r_dc_tlb
;
input st_miss_x
;
input asi_done
;
input flush_tlb_pte
; // ASI decode for PTE flush
input flush_tlb_seg
; // ASI decode for SEG flush
input flush_tlb_reg
; // ASI decode for REG flush
input flush_tlb_ctx
; // ASI decode for CTX flush
input flush_tlb_all
; // ASI decode for ALL flush
input flush_iopte
; // Control space decode for PTE flush
input flush_ioall
; // Control space decode for PTE flush
input probe_err
;
input flush
;
input probe
;
input probe_entire
;
input probe_lvl0
;
input probe_lvl1
;
input probe_lvl2
;
input probe_lvl3
;
input r_acc_err_tw
;
input mm_misc2cf
;
input tw_perr
;
input r_tw_err
;
input tw_par
; // par cntl in TLB_TW state
input mmu_asi_op
; // par cntl in ASI_OP state
input r_trap_w
;
input sb_data_avail
;
input enbl_soft_tw
;
input ss_clock
; // input clock
input ss_reset
; // input reset
wire [29:0] state
;
// state names
// The Msb is intended to be the table walk indicator.
parameter IDLE = 0,
INIT_PAR = 1,
INIT_PAR_MEM = 2,
INIT_PAR_WRT = 3,
ROOT = 4,
RTMEM = 5,
RTWRT = 6,
PTBL1 = 7,
PT1MEM = 8,
PT1WRT = 9,
PTBL2 = 10,
PT2MEM = 11,
PT2WRT = 12,
PTBL3 = 13,
PT3MEM = 14,
PT3WRT = 15,
PTE_TAG = 16,
PTE_TAG_U = 17,
UPDATE = 18,
UPDATE_C = 19,
UPDATE2 = 20,
UPDATE_F = 21,
PTE_FLUSH = 22,
PRB_DONE = 23,
PRB_CLR = 24,
ERR_ADR = 25,
ERR_XLT = 26,
VPTP_HIT = 27,
PTE_FLUSH1 = 28,
PTE_FLUSH2 = 29;
wire tdata_rdy_in
= ~mc_mstb_l & mmstben;
wire probe_hit
;
wire lvl_probe_hld;
wire tdata_rdy
;
Mflipflop_r_1 mc_mstb_reg_1(tdata_rdy,tdata_rdy_in,~ss_reset,ss_clock) ;
wire r_mdata_in_r
;
Mflipflop_r_1 mdata_r_reg_1(r_mdata_in_r,mdata_in_r,~ss_reset,ss_clock) ;
wire r_mmdaten
;
Mflipflop_r_1 mmdaten_reg_1(r_mmdaten,mmdaten,~ss_reset,ss_clock) ;
wire r_mdata_in_m
;
Mflipflop_r_1 mdata_m_reg_1(r_mdata_in_m,mdata_in_m,~ss_reset,ss_clock) ;
wire [1:0] r_mdata_et
;
Mflipflop_r_2 mdata_et_reg_2(r_mdata_et,mdata_in_et,~ss_reset,ss_clock) ;
wire [1:0] r_mdata_acc
;
Mflipflop_r_2 mdata_acc_reg_2(r_mdata_acc,mdata_in_acc,~ss_reset,ss_clock) ;
wire flush_entry
= (dc_tlb_tw & ~flush_done & (flush_tlb_pte |
flush_tlb_seg | flush_tlb_reg | flush_tlb_ctx |
flush_tlb_all)) |
(~io_tlb & (flush_iopte | flush_ioall)) ;
wire dvma_ioflush
= io_tlb & (flush_iopte | flush_ioall);
wire flush_crs
= dc_tlb_tw & (flush_tlb_ctx | flush_tlb_reg |
flush_tlb_seg) ;
wire r_flush_entry_in
= flush_entry | dvma_ioflush |
(state[PTE_FLUSH] & flush_crs) |
(state[PTE_FLUSH1] & virt_ptp2);
wire r_flush_entry;
Mflipflop_r_1 flush_entry_ff_1(r_flush_entry,r_flush_entry_in,~ss_reset,ss_clock) ;
wire ptp_flush_in
;
wire r_ptp_flush
;
wire ptp_flush
= ptp_flush_in | (r_ptp_flush & tw_par);
Mflipflop_r_1 ptp_flush_ff_1(r_ptp_flush,ptp_flush,~ss_reset,ss_clock) ;
// 2 1
// 987654321098765432109876543210
parameter [29:0] D_IDLE = 30'b000000000000000000000000000001,
D_INIT_PAR = 30'b000000000000000000000000000010,
D_INIT_PAR_MEM = 30'b000000000000000000000000000100,
D_INIT_PAR_WRT = 30'b000000000000000000000000001000,
D_ROOT = 30'b000000000000000000000000010000,
D_RTMEM = 30'b000000000000000000000000100000,
D_RTWRT = 30'b000000000000000000000001000000,
D_PTBL1 = 30'b000000000000000000000010000000,
D_PT1MEM = 30'b000000000000000000000100000000,
D_PT1WRT = 30'b000000000000000000001000000000,
D_PTBL2 = 30'b000000000000000000010000000000,
D_PT2MEM = 30'b000000000000000000100000000000,
D_PT2WRT = 30'b000000000000000001000000000000,
D_PTBL3 = 30'b000000000000000010000000000000,
D_PT3MEM = 30'b000000000000000100000000000000,
D_PT3WRT = 30'b000000000000001000000000000000,
D_PTE_TAG = 30'b000000000000010000000000000000,
D_PTE_TAG_U = 30'b000000000000100000000000000000,
D_UPDATE = 30'b000000000001000000000000000000,
D_UPDATE_C = 30'b000000000010000000000000000000,
D_UPDATE2 = 30'b000000000100000000000000000000,
D_UPDATE_F = 30'b000000001000000000000000000000,
D_PTE_FLUSH = 30'b000000010000000000000000000000,
D_PRB_DONE = 30'b000000100000000000000000000000,
D_PRB_CLR = 30'b000001000000000000000000000000,
D_ERR_ADR = 30'b000010000000000000000000000000,
D_ERR_XLT = 30'b000100000000000000000000000000,
D_VPTP_HIT = 30'b001000000000000000000000000000,
D_PTE_FLUSH1 = 30'b010000000000000000000000000000,
D_PTE_FLUSH2 = 30'b100000000000000000000000000000;
/*** Display routine for tw sm state information. *****************/
// synopsys translate_off
reg[30*8:1] tw_state_name
;
always @ state
if(~ss_reset & (state == 30'b0)) begin
Mclocks.print_error("TW state = 0 *** BAD TW_STATE ***") ;
tw_state_name = "*** ALL ZERO *** BAD TW_STATE!";
end
else case (state)
D_IDLE: tw_state_name = "[idle] - idle";
D_INIT_PAR: tw_state_name = "[init_par] - Ld PAR";
D_ROOT: tw_state_name = "[root] - Root lookup";
D_INIT_PAR_MEM: tw_state_name = "[ioroot] - IO root";
D_INIT_PAR_WRT: tw_state_name = "[iorwrt] - IO tlb wrt";
D_PTBL1: tw_state_name = "[ptbl1] - LVL1 lookup";
D_PTBL2: tw_state_name = "[ptbl2] - LVL2 lookup";
D_PTBL3: tw_state_name = "[ptbl3] - LVL3 lookup";
D_ERR_ADR: tw_state_name = "[err_adr] - address error";
D_ERR_XLT: tw_state_name = "[err_xlt] - translate error";
D_RTMEM: tw_state_name = "[rtmem] - root mem wait";
D_RTWRT: tw_state_name = "[rtwrt] - root tlb update";
D_PT1MEM: tw_state_name = "[pt1mem] - LVL1 mem wait";
D_PT1WRT: tw_state_name = "[pt1wrt] - LVL1 tlb update";
D_PT2MEM: tw_state_name = "[pt2mem] - LVL2 mem wait";
D_PT2WRT: tw_state_name = "[pt2wrt] - LVL2 tlb update";
D_PT3MEM: tw_state_name = "[pt3mem] - LVL3 mem wait";
D_PT3WRT: tw_state_name = "[pt3wrt] - LVL3 tlb update";
D_PTE_TAG: tw_state_name = "[pte_tag] - Fix PTE tag";
D_UPDATE: tw_state_name = "[update] - Read TLB PTE";
D_UPDATE_C: tw_state_name = "[update_c] - Check TLB PTE";
D_UPDATE2: tw_state_name = "[update2] - Update mem PTE";
D_UPDATE_F: tw_state_name = "[update_f] - Flush TLB PTE";
D_PTE_TAG_U: tw_state_name = "[pte_tag_u] - Fix tag/mem";
D_PTE_FLUSH: tw_state_name = "[pte_flush] - Flush Entry";
D_PTE_FLUSH1: tw_state_name = "[pte_flush1] - Flush ptps";
D_PTE_FLUSH2: tw_state_name = "[pte_flush2] - Flush V-ptps";
D_PRB_DONE: tw_state_name = "[prb_done] - Probe Done ";
D_PRB_CLR: tw_state_name = "[prb_clr] - Probe Clear ";
D_VPTP_HIT: tw_state_name = "[vptp_hit] - vptp2 hit ";
endcase
// synopsys translate_on
/*******************************************************************/
/* function drives ldtlb_tw, ld_par_tw, ld_mreq_tw,
tw_read_req, read_word_mreq, tw_write_req, ptp_in,
m_in, tw_sm_lvl, ld_par_iotw */
function [29:0] next_tw_state;
input [29:0] state;
input io_tlb_tw;
input tlb_miss;
input dvma_req_x;
input r_dc_tlb;
input st_miss_x;
input virt_ptp2;
input tdata_rdy;
input [1:0] r_mdata_et;
input flush_crs;
input r_mdata_in_r;
input r_mdata_in_m;
input flush_entry;
input dvma_ioflush;
input r_flush_entry;
input probe; //All probe siganls become active in the W-stage
input probe_entire;
input probe_lvl0;
input probe_lvl1;
input probe_lvl2;
input probe_lvl3;
input set_m_on_tw;
input strt_tw_for_m;
input r_mmdaten;
input r_acc_err_tw;
input tw_perr;
input probe_err;
input tw_par;
input flush_done;
input asi_done;
input r_trap_w;
input dc_tlb_tw;
input sb_data_avail;
input enbl_soft_tw;
begin
next_tw_state = {30'b0}; /* set next_state to default. */
case (1'b1) // synopsys parallel_case full_case
/********* Reset *********************************************************/
state == 30'b0:
next_tw_state[IDLE] = 1'b1;
/********* IDLE state ****************************************************/
state[IDLE]:
if (((strt_tw_for_m | flush_entry) & ~r_trap_w) |
(dvma_ioflush))
next_tw_state[PTE_FLUSH] = 1'b1;
else if (tw_par & ~strt_tw_for_m & ~flush_done &
~(dc_tlb_tw & r_trap_w))
next_tw_state[INIT_PAR] = 1'b1;
else
next_tw_state[IDLE] = 1'b1;
/********** INIT_PAR state - Load PAR with either CTPR,CXR or IBAR ******/
state[INIT_PAR]:
if (io_tlb_tw)
begin
next_tw_state[INIT_PAR_MEM] = 1'b1; /* IOROOT state */
end
else if((~tlb_miss & virt_ptp2 & probe_lvl2) |
(probe & enbl_soft_tw) |
(~tlb_miss & probe_entire))
next_tw_state[PTE_TAG] = 1'b1;
else if(~tlb_miss & virt_ptp2 & ~probe)
next_tw_state[VPTP_HIT] = 1'b1;
else
next_tw_state[ROOT] = 1'b1;
/********** ROOT state - CTPR look-up done during this state ************/
state[ROOT]:
if (tlb_miss)
begin
next_tw_state[RTMEM] = 1'b1;
end
else if (probe_lvl0)
next_tw_state[PTE_TAG] = 1'b1;
else
next_tw_state[PTBL1] = 1'b1; //lpar index1
/********** PTBL1 state - PTP/PTE level 1 lookup during this state ***/
state[PTBL1]:
if (dvma_req_x | sb_data_avail | (r_trap_w & dc_tlb_tw))
begin
next_tw_state[IDLE] = 1'b1;
end
else if (tlb_miss & ~(dvma_req_x | sb_data_avail |
(r_trap_w & dc_tlb_tw)))
begin
next_tw_state[PT1MEM] = 1'b1;
end
else if (probe_lvl1)
next_tw_state[PTE_TAG] = 1'b1;
else
next_tw_state[PTBL2] = 1'b1; //lpar index2
/********** PTBL2 state - PTP/PTE level 2 lookup during this state ***/
state[PTBL2]:
if (dvma_req_x | sb_data_avail | (r_trap_w & dc_tlb_tw))
begin
next_tw_state[IDLE] = 1'b1;
end
else if (tlb_miss & ~(dvma_req_x | sb_data_avail |
(r_trap_w & dc_tlb_tw)))
begin
next_tw_state[PT2MEM] = 1'b1;
end
else if (probe_lvl2)
next_tw_state[PTE_TAG] = 1'b1;
else
begin
next_tw_state[PTBL3] = 1'b1;
end
/********** PTBL3 state - PTP/PTE level 3 lookup during this state ***/
state[PTBL3]:
if (dvma_req_x | sb_data_avail | (r_trap_w & dc_tlb_tw))
begin
next_tw_state[IDLE] = 1'b1;
end
else if (~tlb_miss & probe_lvl3)
next_tw_state[PTE_TAG] = 1'b1;
else if (~(dvma_req_x | sb_data_avail |
(r_trap_w & dc_tlb_tw)))
begin
next_tw_state[PT3MEM] = 1'b1;
end
else
begin
next_tw_state[IDLE] = 1'b1;
end
/********** PTBL2 state - PTP/PTE level 3 lookup during this state ***/
state[VPTP_HIT]:
next_tw_state[PTBL3] = 1'b1;
/********** RTMEM state - start memory access for root PTP look-up ***/
state[RTMEM]:
begin
if (tdata_rdy)
begin
next_tw_state[RTWRT] = 1'b1;
end
else
begin
next_tw_state[RTMEM] = 1'b1;
end
end
/********** RTWRT state - finish memory access for root PTP look-up ***/
state[RTWRT]:
begin
if (probe_lvl0 | (probe & ~(r_mdata_et == 2'b01)))
next_tw_state[PTE_TAG] = 1'b1;
else if (tw_perr) next_tw_state[ERR_XLT] = 1'b1;
else
case (r_mdata_et) //synopsys parallel_case
2'b01: next_tw_state[PTBL1] = 1'b1;
2'b00: next_tw_state[ERR_ADR] = 1'b1;
default: next_tw_state[ERR_XLT] = 1'b1;
endcase
end
/********** PT1MEM state - start memory access for level 1 PTP look-up ***/
state[PT1MEM]:
begin
if (tdata_rdy)
next_tw_state[PT1WRT] = 1'b1;
else
next_tw_state[PT1MEM] = 1'b1;
end
/********** PT1WRT state - finish memory access for level 1 PTP look-up ***/
state[PT1WRT]:
begin
if (probe_entire & (r_mdata_et == 2'b10) & ~tw_perr)
next_tw_state[PTE_TAG_U] = 1'b1;
else if (probe_lvl1 | (probe & ~(r_mdata_et == 2'b01)))
next_tw_state[PTE_TAG] = 1'b1;
else if (tw_perr) next_tw_state[ERR_XLT] = 1'b1;
else
case (r_mdata_et) // synopsys parallel_case full_case
2'b01: next_tw_state[PTBL2] = 1'b1;
2'b10: begin
case ({r_mdata_in_m, set_m_on_tw,
r_mdata_in_r}) // synopsys parallel_case
3'b000: next_tw_state[PTE_TAG_U] = 1'b1;
3'b001: next_tw_state[PTE_TAG] = 1'b1;
3'b010: next_tw_state[PTE_TAG_U] = 1'b1;
3'b011: next_tw_state[PTE_TAG_U] = 1'b1;
3'b101: next_tw_state[PTE_TAG] = 1'b1;
3'b111: next_tw_state[PTE_TAG] = 1'b1;
default: next_tw_state[ERR_ADR] = 1'b1;
endcase
end
2'b00: next_tw_state[ERR_ADR] = 1'b1;
2'b11: next_tw_state[ERR_XLT] = 1'b1;
endcase
end
/********** PT2MEM state - start memory access for level 2 PTP look-up ***/
state[PT2MEM]:
begin
if (tdata_rdy)
next_tw_state[PT2WRT] = 1'b1;
else
next_tw_state[PT2MEM] = 1'b1;
end
/********** PT2WRT state - finish memory access for level 2 PTP look-up ***/
state[PT2WRT]:
begin
if (probe_entire & (r_mdata_et == 2'b10) & ~tw_perr)
next_tw_state[PTE_TAG_U] = 1'b1;
else if (probe_lvl2 | (probe & ~(r_mdata_et == 2'b01)))
next_tw_state[PTE_TAG] = 1'b1;
else if (tw_perr) next_tw_state[ERR_XLT] = 1'b1;
else
case (r_mdata_et) // synopsys parallel_case full_case
2'b01: next_tw_state[PT3MEM] = 1'b1;
2'b10: begin
case ({r_mdata_in_m, set_m_on_tw,
r_mdata_in_r}) // synopsys parallel_case
3'b000: next_tw_state[PTE_TAG_U] = 1'b1;
3'b001: next_tw_state[PTE_TAG] = 1'b1;
3'b010: next_tw_state[PTE_TAG_U] = 1'b1;
3'b011: next_tw_state[PTE_TAG_U] = 1'b1;
3'b101: next_tw_state[PTE_TAG] = 1'b1;
3'b111: next_tw_state[PTE_TAG] = 1'b1;
default: next_tw_state[ERR_ADR] = 1'b1;
endcase
end
2'b00: next_tw_state[ERR_ADR] = 1'b1;
2'b11: next_tw_state[ERR_XLT] = 1'b1;
endcase
end
/********** PT3MEM state - start memory access for level 3 PTP look-up ***/
state[PT3MEM]:
begin
if (tdata_rdy)
next_tw_state[PT3WRT] = 1'b1;
else
next_tw_state[PT3MEM] = 1'b1;
end
/********** PT3WRT state - finish memory access for level 3 PTP look-up ***/
state[PT3WRT]:
begin
if (probe_entire & (r_mdata_et == 2'b10) & ~tw_perr)
next_tw_state[PTE_TAG_U] = 1'b1;
else if (probe) next_tw_state[PRB_DONE] = 1'b1;
else if (tw_perr) next_tw_state[ERR_XLT] = 1'b1;
else
case (r_mdata_et) // synopsys parallel_case full_case
2'b10: begin
case ({r_mdata_in_m, set_m_on_tw,
r_mdata_in_r}) // synopsys parallel_case
3'b000: next_tw_state[UPDATE] = 1'b1;
3'b001: next_tw_state[IDLE] = 1'b1;
3'b010: next_tw_state[UPDATE] = 1'b1;
3'b011: next_tw_state[UPDATE] = 1'b1;
3'b101: next_tw_state[IDLE] = 1'b1;
3'b111: next_tw_state[IDLE] = 1'b1;
default: next_tw_state[ERR_ADR] = 1'b1;
endcase
end
2'b00: next_tw_state[ERR_ADR] = 1'b1;
2'b01: next_tw_state[ERR_XLT] = 1'b1;
2'b11: next_tw_state[ERR_XLT] = 1'b1;
endcase
end
/********** PTE_TAG state - Update TLB TAG with Virtual Addr. TAG ********/
state[PTE_TAG]:
if (probe)
next_tw_state[PRB_DONE] = 1'b1;
else
next_tw_state[IDLE] = 1'b1;
/********** PTE_TAG_U state - Update TLB TAG with Virtual Addr. TAG ********/
state[PTE_TAG_U]:
next_tw_state[UPDATE] = 1'b1;
/********** IOROOT state - look-up with IBAR for IOPTE in memory ***********/
state[INIT_PAR_MEM]:
begin
if (tdata_rdy) /* base for IOROOT and IOWRT */
next_tw_state[INIT_PAR_WRT] = 1'b1;
else
next_tw_state[INIT_PAR_MEM] = 1'b1;
end
/********** IORWRT state - finish IOPTE read from memory ****************/
state[INIT_PAR_WRT]:
begin
if (tw_perr) next_tw_state[ERR_XLT] = 1'b1;
else
begin
case (r_mdata_et) // synopsys parallel_case
2'b10: next_tw_state[IDLE] = 1'b1;
default: next_tw_state[ERR_XLT] = 1'b1;
endcase
end
end
/********** PTE_FLUSH state - FLUSH PTE entry ***************************/
state[PTE_FLUSH]:
if (r_flush_entry & ~flush_crs)
next_tw_state[IDLE] = 1'b1;
else if(r_flush_entry & flush_crs)
next_tw_state[PTE_FLUSH1] = 1'b1;
else
next_tw_state[INIT_PAR] = 1'b1;
/********** PTE_FLUSH1 state - flush all PTP after FLUSH CXT, REG, SEG **/
state[PTE_FLUSH1]:
if (virt_ptp2)
next_tw_state[PTE_FLUSH2] = 1'b1;
else
next_tw_state[IDLE] = 1'b1;
/********** PTE_FLUSH2 state - flush all PTP after FLUSH CXT, REG, SEG **/
state[PTE_FLUSH2]:
next_tw_state[IDLE] = 1'b1;
/********** UPDATE state - used to update R or M bit of PTE *************/
/********** Sets up a TLB read of PTE to be written to memory. **********/
state[UPDATE]: next_tw_state[UPDATE_C] = 1'b1;
/********** UPDATE_C state - used to check permission of current access */
/********** If protection/privilege error -> IDLE (flush entry) ******/
state[UPDATE_C]:
if (r_acc_err_tw)
begin
next_tw_state[UPDATE_F] = 1'b1;
end
else
next_tw_state[UPDATE2] = 1'b1;
/********** UPDATE2 state - used to update R or M bit of PTE *************/
state[UPDATE2]:
if (r_mmdaten & ~probe)
next_tw_state[IDLE] = 1'b1;
else if (r_mmdaten & probe)
next_tw_state[PRB_DONE] = 1'b1;
else
next_tw_state[UPDATE2] = 1'b1;
/********** UPDATE_FLUSH state - used to flush PTEs that failed UPDATE_C ***/
state[UPDATE_F]:
next_tw_state[IDLE] = 1'b1;
/********** ERR_XLT state - used to indicate a translation error **********/
/********** Go to PTE_TAG to invalidate entry (writes 0 in valid bit) ****/
state[ERR_XLT]: next_tw_state[PTE_TAG] = 1'b1;
/********** ERR_ADR state - used to indicate an invalid address error *****/
/********** Go to PTE_TAG to invalidate entry (writes 0 in valid bit) ****/
state[ERR_ADR]: next_tw_state[PTE_TAG] = 1'b1;
/********** PRB_DONE state - used to indicate the end of a Probe op *****/
state[PRB_DONE]:
if (~asi_done)
next_tw_state[PRB_DONE] = 1'b1;
else if (probe_entire & ~probe_err)
next_tw_state[IDLE] = 1'b1;
else
next_tw_state[PRB_CLR] = 1'b1;
/********** PRB_CLR state - used to indicate the end of a Probe op *****/
state[PRB_CLR]: next_tw_state[IDLE] = 1'b1;
endcase // endcase for case(state)
end
endfunction
wire [29:0] state_in
= next_tw_state(state, io_tlb_tw,
tlb_miss, dvma_req_x,
r_dc_tlb, st_miss_x, virt_ptp2,
tdata_rdy, r_mdata_et, flush_crs,
r_mdata_in_r, r_mdata_in_m,
flush_entry, dvma_ioflush, r_flush_entry,
probe, probe_entire, probe_lvl0,
probe_lvl1, probe_lvl2, probe_lvl3,
set_m_on_tw,
strt_tw_for_m, r_mmdaten, r_acc_err_tw,
tw_perr, probe_err,tw_par, flush_done,
asi_done,
r_trap_w, dc_tlb_tw, sb_data_avail,enbl_soft_tw);
/*** State regsiter bits ****************************************************/
Mflipflop_r_30 mtwsm_30(state,state_in,~ss_reset,ss_clock) ;
/*** Table Walk done ********************************************************/
/*** must ensure decode of state that return to IDLE ***/
/*** this is for normal tablewalks only (not probes or flushes) ***/
assign tw_done = (~probe & (state[UPDATE_F] | state[PTE_TAG] |
(state[UPDATE2] & r_mmdaten) |
(state[PT3WRT] & (r_mdata_et == 2'b10) & ~tw_perr &
((~r_mdata_in_m & ~set_m_on_tw & r_mdata_in_r) |
(r_mdata_in_m & ~set_m_on_tw & r_mdata_in_r) |
(r_mdata_in_m & set_m_on_tw & r_mdata_in_r))))) |
((state[PTBL1] | state[PTBL2] | state[PTBL3]) &
(dvma_req_x | sb_data_avail | (r_trap_w & dc_tlb_tw))) |
(state[INIT_PAR_WRT] & (r_mdata_et == 2'b10)) |
(dc_tlb_tw & r_trap_w & state[IDLE]) ; // for fast traps
wire tw_abort_in
= (state[PTBL1] | state[PTBL2] | state[PTBL3]) &
(dvma_req_x | sb_data_avail | (r_trap_w & dc_tlb_tw));
wire tw_abort;
Mflipflop_r_1 tw_abort_ff_1(tw_abort,tw_abort_in,~ss_reset,ss_clock) ;
/*** TLB RAM write enable ***************************************************/
assign ldtlb_data_tw = (((state[RTMEM])| /* RTMEM state */
(state[PT1MEM]) | /* PTBL1 state */
(state[PT2MEM]) | /* PTBL2 state */
(state[PT3MEM]) | /* PTBL3 state */
(state[INIT_PAR_MEM])) & /* IOROOT */
tdata_rdy) ;
/*** TLB CAM write enable ***************************************************/
assign ldtlb_tag_tw = (ldtlb_data_tw |
(state[PT3WRT] & tw_prb_err) |
(state[RTWRT] &
((probe & ~(r_mdata_et == 2'b01)))) |
((state[PT1WRT]) &
((probe & ~(r_mdata_et == 2'b01)))) |
((state[PT2WRT]) &
((probe & ~(r_mdata_et == 2'b01)))) |
(((state[RTWRT]) |
(state[PT1WRT]) |
(state[PT2WRT])) &
~(r_mdata_et == 2'b01)));
/****************************************************************************/
/***** va_sel_par_in is basically the same as the table_walk signal ****/
/***** except that it's disabled during PTE tag writes (must load ****/
/***** virtual address as PTE tag). ****/
/***** FIX for P0 TLB flush cxt/reg/seg multiple cam match bug ****/
/***** No va_sel_par_in during any of the PTE_FLUSH states ****/
assign va_sel_par_in = ~((flush_tlb_ctx | flush_tlb_seg | flush_tlb_reg |
flush_tlb_pte | flush_tlb_all) & dc_tlb_tw) &
(~state[IDLE] & ~state[VPTP_HIT] &
~state[ERR_ADR] & ~state[ERR_XLT] &
~(state[PT3WRT] | state[INIT_PAR_WRT] |
state[UPDATE_C] | state[UPDATE2] |
state[PTE_TAG] | state[PTE_TAG_U] |
(state[PTE_FLUSH] & ((virt_ptp2 & ~r_flush_entry) |
(r_flush_entry & ~flush_crs))) |
state[PRB_DONE] | state[PRB_CLR]) &
~(state[PT3MEM] | state[INIT_PAR_MEM] |
((state[RTWRT] &
(probe_lvl0 | ~(r_mdata_et == 2'b01))) |
(state[PT1WRT] &
(probe_lvl1 | ~(r_mdata_et == 2'b01))) |
(state[PT2WRT] &
(probe_lvl2 | ~(r_mdata_et == 2'b01)))
)) &
~(state[PTBL3] | state[PTBL2]) &
~((state[PTBL1] | state[PT1WRT] | state[PT2MEM]) &
virt_ptp2)) ;
/*** Load PAR decode - table walk decode for load PAR. ********************/
assign ld_par_tw = ((state[INIT_PAR]) | state[VPTP_HIT] |
(((state[ROOT] & ~(probe_lvl0 & ~tlb_miss)) |
(state[PTBL1] & ~(probe_lvl1 & ~tlb_miss)) |
(state[PTBL3] & ~(probe_lvl3 & ~tlb_miss)) |
(state[PTBL2] & ~(probe_lvl2 & ~tlb_miss))) &
~tlb_miss) |
((state[RTWRT] | state[PT1WRT] | state[PT2WRT]) &
(r_mdata_et == 2'b01)));
/****************************************************************************/
/*** Read word request (1 cycle early) for marb_sm. ***/
assign read_word_mreq = (state[INIT_PAR] |
state[ROOT] |
state[PTBL1] |
state[PTBL2] |
state[PTBL3]);
/****************************************************************************/
/*** Load memory request reg. decode ***/
assign ld_mreq_tw = read_word_mreq | tw_write_req ;
/****************************************************************************/
/*** Read word request (current cycle). ***/
assign tw_read_req = ((state[INIT_PAR_MEM]) |
(state[RTMEM]) |
(state[PT1MEM]) |
(state[PT2MEM]) |
(state[PT3MEM])) ;
/****************************************************************************/
/***** tw_write_req is used for writing a PTE to memory. This is done ***/
/***** only in the UPDATE state, and is used to slect the PTE onto the ***/
/***** mc_mdata bus. It must be de-asserted 1-cycle before IDLE, since ***/
/***** the TLB inputs are registerd and require 1-cycle latency. ***/
assign tw_write_req = (state[UPDATE2] & ~ss_reset);
/****************************************************************************/
/*** TLB input IO - IO flag for TLB CAM input. ***/
assign tw_io_bit = ((state[VPTP_HIT] | state[IDLE]) & tw_par &
~flush_entry & ~io_tlb_tw & virt_ptp2 &
~probe_entire & ~strt_tw_for_m) |
(state[PTBL1] & virt_ptp2) |
(state[IDLE] & (flush_iopte | flush_ioall)) |
(state[PTE_FLUSH] & tw_par & virt_ptp2 & ~r_flush_entry) |
(state[PTE_FLUSH1] & virt_ptp2) |
(state[PT1WRT] & virt_ptp2 & (r_mdata_et == 2'b01)) |
(state[PT2MEM] & virt_ptp2);
/****************************************************************************/
/*** TLB input PTP - PTP flag for TLB CAM input. ***/
/*** Also used for Context select for loading the TLB tag. ***/
assign ptp_in = (state[ROOT] |
state[PTBL1] |
// state[PTBL2] |
(state[PTE_FLUSH] & tw_par &
(flush_crs | (virt_ptp2 & ~r_flush_entry))) |
(state[PTE_FLUSH1] & virt_ptp2) |
state[INIT_PAR] | state[VPTP_HIT] |
(state[RTMEM] | state[PT1MEM] | state[PT2MEM]) |
((state[RTWRT] | state[PT1WRT] | state[PT2WRT]) &
(r_mdata_et == 2'b01)) |
(state[PRB_DONE] & r_ptp_flush) |
(state[IDLE] & tw_par & virt_ptp2 & ~probe_entire &
~(dvma_ioflush | flush_entry | strt_tw_for_m)) |
(state[PTBL3] & tw_par & virt_ptp2 & ~probe_entire));
/****************************************************************************/
/*** TLB superviosr bit input ***/
assign io_s_bit = flush_iopte | flush_ioall ;
assign va_s_in = (tw_sin & tw_tlb_nxt) | io_s_bit |
(state[PTE_FLUSH1] & virt_ptp2) ;
/****************************************************************************/
/*** Store state that a probe encountered a PTP at last level. ***/
/*** Needed for flush ***/
assign ptp_flush_in = ((state[RTWRT] & probe_lvl0) |
(state[PT1WRT] & probe_lvl1) |
(state[PT2WRT] & probe_lvl2)) &
(r_mdata_et == 2'b01) ;
/****************************************************************************/
/*** TLB data input level bits - Level bits that are input to TLB RAM ***/
/*** Decode for raw TLB level bits from tag (software tag[12:10]) ***/
/*** ***/
/*** cam_lvl[2:0] tlb_lvl_dcd[1:0] (PTE level) ***/
/*** ------------ ---------------- ----------- ***/
/*** 000 00 level-0 ***/
/*** 100 01 level-1 ***/
/*** 110 10 level-2 ***/
/*** 111 11 level-3 ***/
/*** 111 11 IO-PTE ***/
assign tlb_ram_lvl[2] = state[PT1MEM] | state[PT1WRT] |
state[PT2MEM] | state[PT2WRT] |
state[PT3MEM] | state[PT3WRT] | state[VPTP_HIT] |
state[INIT_PAR_MEM] | state[INIT_PAR_WRT] ;
assign tlb_ram_lvl[1] = state[PT2MEM] | state[PT2WRT] |
state[PT3MEM] | state[PT3WRT] | state[VPTP_HIT] |
state[INIT_PAR_MEM] | state[INIT_PAR_WRT] ;
assign tlb_ram_lvl[0] = state[PT3MEM] | state[PT3WRT] |
state[INIT_PAR_MEM] | state[INIT_PAR_WRT] ;
This page: |
Created: | Thu Aug 19 11:59:36 1999 |
| From: |
../../../sparc_v8/ssparc/mmu/m_mmu_cntl/rtl/rl_tw_sm.v
|