Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / dmu / rtl / dmu_mmu_vtb.v
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: dmu_mmu_vtb.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
//
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
//
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
// ========== Copyright Header End ============================================
module dmu_mmu_vtb
(
l2clk, // clock for rams
clk, // clock
rst_l, // reset
scan_in,
tcu_array_bypass,
tcu_se_scancollar_in,
tcu_scan_en,
tcu_array_wr_inhibit,
tcu_pce_ov,
tcu_aclk,
tcu_bclk,
scan_out,
csr2vtb_ra, // csr read address
csr2vtb_wa, // csr write address
csr2vtb_wd, // csr write data
csr2vtb_we, // csr write enable
ptb2vtb_inv, // ptb invalidate
tcb2vtb_hld, // tcb hold
tcb2vtb_sel, // tcb select
tcb2vtb_tmv, // tcb translation mode valid
tcb2vtb_vld, // tcb valid
tcb2vtb_wa, // tcb write address
tcb2vtb_we, // tcb write enable
tlb2vtb_addr, // tlb virtual tag
tlb2vtb_iotsbno, // tlb virtual iotsb for sun4v mode
vab2vtb_addr, // vab address
vab2vtb_dbra, // vab read address
vab2vtb_iotsbno, // vab iotsb number for sun4v mode
sun4v_mode, // 1 if in suv4v mode
vtb2crb_hit, // crb hit
vtb2crb_inv, // crb tag invalidate
vtb2crb_tag, // crb invalidate tag
vtb2crb_vld, // crb valid
vtb2csr_prf, // vtb performance event
vtb2csr_rd, // csr read data
vtb2tcb_hit, // tcb virtual tag hit
vtb2tdb_dbra, // tdb data buffer read address
vtb2tlb_dbra, // tlb data buffer read address
dmu_cb0_run,
dmu_cb0_addr,
dmu_cb0_wdata_key,
dmu_cb0_mmu_vtb_wr_en,
dmu_cb0_mmu_vtb_rd_en,
dmu_cb0_mmu_vtb_lkup_en,
dmu_cb0_hld,
mmu_vtb_hit,
vtb_dout_4msb
);
// ----------------------------------------------------------------------------
// Ports
// ----------------------------------------------------------------------------
input l2clk;
input clk;
input rst_l;
input scan_in;
input tcu_array_bypass;
input tcu_se_scancollar_in;
input tcu_scan_en;
input tcu_array_wr_inhibit;
input tcu_pce_ov;
input tcu_aclk;
input tcu_bclk;
output scan_out;
input [`FIRE_DLC_MMU_TAG_PTR_BITS] csr2vtb_ra;
input [`FIRE_DLC_MMU_TAG_PTR_BITS] csr2vtb_wa;
input [`FIRE_DLC_MMU_VTR_BITS] csr2vtb_wd;
input csr2vtb_we;
input [`FIRE_DLC_MMU_TAG_BITS] ptb2vtb_inv;
input tcb2vtb_hld;
input tcb2vtb_sel;
input tcb2vtb_tmv;
input tcb2vtb_vld;
input [`FIRE_DLC_MMU_TAG_PTR_BITS] tcb2vtb_wa;
input tcb2vtb_we;
input [`FIRE_DLC_MMU_VTD_VPN_BITS] tlb2vtb_addr;
input [`FIRE_DLC_MMU_VAR_IOTSB_BITS] tlb2vtb_iotsbno;
input [`FIRE_DLC_MMU_VTD_VPN_BITS] vab2vtb_addr;
input [`FILE_DLC_MMU_TTE_CNT_BITS] vab2vtb_dbra;
input [`FIRE_DLC_MMU_VAR_IOTSB_BITS] vab2vtb_iotsbno;
input sun4v_mode;
output [`FIRE_DLC_MMU_TAG_BITS] vtb2crb_hit;
output vtb2crb_inv;
output [`FIRE_DLC_MMU_TAG_PTR_BITS] vtb2crb_tag;
output [`FIRE_DLC_MMU_TAG_BITS] vtb2crb_vld;
output vtb2csr_prf;
output [`FIRE_DLC_MMU_VTR_BITS] vtb2csr_rd;
output vtb2tcb_hit;
output [`FIRE_DLC_MMU_TDB_PTR_BITS] vtb2tdb_dbra;
output [`FIRE_DLC_MMU_TDB_PTR_BITS] vtb2tlb_dbra;
input dmu_cb0_run;
input [5:0] dmu_cb0_addr;
input [32:0] dmu_cb0_wdata_key;
input dmu_cb0_mmu_vtb_wr_en;
input dmu_cb0_mmu_vtb_rd_en;
input dmu_cb0_mmu_vtb_lkup_en;
input dmu_cb0_hld;
output [63:0] mmu_vtb_hit;
output [3:0] vtb_dout_4msb;
// ----------------------------------------------------------------------------
// Variables
// ----------------------------------------------------------------------------
wire [`FIRE_DLC_MMU_VTR_BITS] vtb2csr_rd;
wire [`FIRE_DLC_MMU_TAG_PTR_BITS] vtb2crb_tag, hit_tag;
wire [`FIRE_DLC_MMU_TAG_BITS] vtb2crb_hit, vtb2crb_vld, hit_vld;
wire [`FIRE_DLC_MMU_TDB_PTR_BITS] vtb2tdb_dbra, vtb2tlb_dbra, dbra_ps1;
wire [`FIRE_DLC_MMU_VTD_VPN_BITS] new_tag;
wire [`FIRE_DLC_MMU_TAG_PTR_BITS] new_wa;
wire [`FIRE_DLC_MMU_TAG_BITS] nxt_vld, clr_vld;
wire [`FIRE_DLC_MMU_VAR_IOTSB_BITS] new_tag_iotsbno;
wire sun4v_mode;
// reg [`FIRE_DLC_MMU_VTD_VPN_BITS] tag [`FIRE_DLC_MMU_TAG_MEM_BITS];
wire [`FIRE_DLC_MMU_TAG_BITS] hit_ps1,hit_out;
reg [`FIRE_DLC_MMU_TAG_BITS] tag_ld, tld;
reg [`FIRE_DLC_MMU_TAG_BITS] vld, set_vld, clr_vct;
// integer i;
// ----------------------------------------------------------------------------
// Zero In Checkers
// ----------------------------------------------------------------------------
// 0in bits_on -var {csr2vtb_we, tcb2vtb_we} -max 1
// 0in bits_on -var hit_vld -max 1
// 0in decoder -in new_wa -out set_vld -active set_bit
// 0in decoder -in new_wa -out clr_vct -active clr_bit
// 0in decoder -in new_wa -out tag_ld -active new_we
// 0in encoder -in hit_vld -out hit_tag -zero off
// 0in encoder -in ptb2vtb_inv -out vtb2crb_tag -zero off -active ~sun4v_mode
// ----------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------
function [`FIRE_DLC_MMU_TAG_PTR_BITS] tag_enc;
input [`FIRE_DLC_MMU_TAG_BITS] di;
reg [`FIRE_DLC_MMU_TAG_PTR_BITS] do;
reg [1+`FIRE_DLC_MMU_TAG_PTR_BITS] i;
parameter MAX = { 1'b0, { `FIRE_DLC_MMU_TAG_PTR_SIZE {1'b1} } };
begin
do = 0;
for (i = 0; i <= MAX; i = i + 1) begin
if (di[i[`FIRE_DLC_MMU_TAG_PTR_BITS]])
do = i[`FIRE_DLC_MMU_TAG_PTR_BITS];
end
tag_enc = do;
end
endfunction // tag_enc
// ----------------------------------------------------------------------------
// Combinational
// ----------------------------------------------------------------------------
// new tag address, write address, and write enable
assign new_tag = tcb2vtb_sel ? tlb2vtb_addr : csr2vtb_wd
[`FIRE_DLC_MMU_VTR_VPN_BITS];
assign new_tag_iotsbno = sun4v_mode ? (tcb2vtb_sel ? tlb2vtb_iotsbno : csr2vtb_wd[`FIRE_DLC_MMU_VTR_IOTSBNO_BITS]) : 5'b0;
assign new_wa = tcb2vtb_sel ? tcb2vtb_wa : csr2vtb_wa;
wire new_we = tcb2vtb_we | csr2vtb_we;
// csr valid set and clear
wire csr_set = csr2vtb_we & csr2vtb_wd[`FIRE_DLC_MMU_VTR_VLD_BITS];
wire csr_clr = csr2vtb_we & ~csr2vtb_wd[`FIRE_DLC_MMU_VTR_VLD_BITS];
// tcb valid set and clear
wire tcb_set = tcb2vtb_we & tcb2vtb_vld;
wire tcb_clr = tcb2vtb_we & ~tcb2vtb_vld;
// valid bit set and clear
wire set_bit = tcb_set | csr_set;
wire clr_bit = tcb_clr | csr_clr;
// valid bit set for the valid bit vector
always @ (new_wa or set_bit) begin
set_vld = 0;
set_vld[new_wa] = set_bit;
end
// valid bit clear for the valid bit vector
always @ (new_wa or clr_bit) begin
clr_vct = 0;
clr_vct[new_wa] = clr_bit;
end
assign clr_vld = clr_vct | ptb2vtb_inv;
// next valid bit vector
assign nxt_vld = (vld & ~clr_vld) | set_vld;
// tag write enables
always @ (new_we or new_wa or rst_l) begin
tag_ld = { `FIRE_DLC_MMU_TAG_SIZE { ~rst_l } };
tag_ld[new_wa] = new_we | ~rst_l;
end
// hit valid and hit invalidate
assign hit_vld = hit_ps1 & vld;
wire hit_inv = |ptb2vtb_inv;
// data buffer read address encoding
assign hit_tag = tag_enc (hit_vld);
assign dbra_ps1 = {hit_tag, vab2vtb_dbra};
// crb hit, invalidate, tag, and valid
assign vtb2crb_hit = hit_vld;
wire vtb2crb_inv = hit_inv;
assign vtb2crb_tag = tag_enc (ptb2vtb_inv);
assign vtb2crb_vld = vld;
// csr performance events
wire vtb2csr_prf = hit_inv;
// csr read data
// assign vtb2csr_rd[`FIRE_DLC_MMU_VTR_TAG_BITS] = tag[csr2vtb_ra];
assign vtb2csr_rd[`FIRE_DLC_MMU_VTR_VLD_BITS] = vld[csr2vtb_ra];
// tcb hit is the virtual address tag hit
wire vtb2tcb_hit = |(hit_vld & ~tld);
// data buffer read addresses
assign vtb2tdb_dbra = dbra_ps1;
assign vtb2tlb_dbra = dbra_ps1;
// ----------------------------------------------------------------------------
// Sequential
// ----------------------------------------------------------------------------
always @ (posedge clk) begin
if (!rst_l) begin
vld <= 0;
end
else begin
vld <= nxt_vld;
end
end
always @ (posedge clk)
if(~rst_l) begin
tld <= {`FIRE_DLC_MMU_TAG_SIZE{1'b0}};
end
else begin
if (!tcb2vtb_hld) begin
tld <= tag_ld;
end
else begin
tld <= tld | tag_ld;
end
end
// always @ (posedge clk) begin
// for (i = 0; i < `FIRE_DLC_MMU_TAG_SIZE; i = i + 1) begin
// if (tag_ld[i]) begin
// tag[i] <= new_tag;
// end
// if (!tcb2vtb_hld) begin
// hit_ps1[i] <= tcb2vtb_tmv & vld[i] & (vab2vtb_addr == tag[i]);
// end
// end
// end
//BP n2 6-30-04 new cam model
wire [3:0] spare;
wire [4:0] sun4v_bits;
assign sun4v_bits = sun4v_mode ? vab2vtb_iotsbno : {5{1'b0}};
//BP 9-23-04 add dout bypass mux for scan
// note tlb2vtb_addr comes from flops in dmu_mmu_tlb.v
wire [23:0] vtb_out1;
wire [4:0] vtb_out2;
assign vtb2csr_rd[`FIRE_DLC_MMU_VTR_IOTSBNO_BITS] = tcu_array_bypass ? tlb2vtb_addr[20:16] : vtb_out2 ;
assign vtb2csr_rd[`FIRE_DLC_MMU_VTR_VPN_BITS] = tcu_array_bypass ? tlb2vtb_addr : vtb_out1 ;
//SV 02/24/05 added BIST logic
wire [32:0] din_cam, key_cam ;
wire [5:0] rd_addr_cam, wr_addr_cam ;
wire wr_en_cam, rd_en_cam, lkup_en_cam, hld_cam ;
assign mmu_vtb_hit = hit_out ;
assign vtb_dout_4msb = spare[3:0] ;
assign din_cam = dmu_cb0_run ? dmu_cb0_wdata_key : ({{4{1'b0}},new_tag_iotsbno,new_tag}) ;
assign rd_addr_cam = dmu_cb0_run ? dmu_cb0_addr : csr2vtb_ra ;
assign wr_addr_cam = dmu_cb0_run ? dmu_cb0_addr : new_wa ;
assign wr_en_cam = dmu_cb0_run ? dmu_cb0_mmu_vtb_wr_en : new_we ;
assign rd_en_cam = dmu_cb0_run ? dmu_cb0_mmu_vtb_rd_en : 1'b1 ;
assign hld_cam = dmu_cb0_run ? dmu_cb0_hld : tcb2vtb_hld ;
assign key_cam = dmu_cb0_run ? dmu_cb0_wdata_key : ({{4{1'b0}},sun4v_bits,vab2vtb_addr}) ;
assign lkup_en_cam = dmu_cb0_run ? dmu_cb0_mmu_vtb_lkup_en : tcb2vtb_tmv ;
/* 0in memory_access -read_addr rd_addr_cam -read (rd_en_cam & ~wr_en_cam)
-write_addr wr_addr_cam -write wr_en_cam
-latency 1
-write_data din_cam
-read_data {spare[3:0],vtb_out2,vtb_out1}
*/
n2_mmu_cm_64x34s_cust vtb_cam
(
// address ports
.rd_addr (rd_addr_cam),
.wr_addr (wr_addr_cam),
// clock ports
.clk (l2clk),
// data input ports
.din (din_cam),
// data output ports
// .dout ({spare,vtb2csr_rd[`FIRE_DLC_MMU_VTR_IOTSBNO_BITS],vtb2csr_rd[`FIRE_DLC_MMU_VTR_VPN_BITS]}),
.dout ({spare[3:0],vtb_out2,vtb_out1}),
// port enables
.wr_en (wr_en_cam),
.rd_en (rd_en_cam),
// key--address to CAM against
.key (key_cam),
// key--address to CAM against
.lkup_en (lkup_en_cam),
// hold key
.hld (hld_cam),
// 64 hit values after CAM'ing
.hit (hit_out),
// scan ports
.scan_in (scan_in),
.tcu_se_scancollar_in (tcu_se_scancollar_in),
.tcu_scan_en (tcu_scan_en),
.tcu_array_wr_inhibit (tcu_array_wr_inhibit),
.tcu_pce_ov (tcu_pce_ov),
.pce (1'b1),
.tcu_aclk (tcu_aclk),
.tcu_bclk (tcu_bclk),
.scan_out (scan_out)
);
reg [63:0] vld_d;
always @ (posedge clk)
if(~rst_l) begin
vld_d <= {64{1'b0}};
end
else begin
if (!tcb2vtb_hld) begin
vld_d <= vld;
end
end
//assign hit_ps1 = {64{tcb2vtb_tmv}} & vld & hit_out;
assign hit_ps1 = vld_d & hit_out;
endmodule // dmu_mmu_vtb