/******************************************************************************/
/* */
/* 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: @(#)task.v
***
****************************************************************************
****************************************************************************/
/* Changes:
6/22/98: changed pcr[31:0] assignment when in MMU_GATE_LEVEL,
according to Seagle synthesis netlist.
*/
`ifdef VCS
`define NOFORCE 1
`endif
`ifdef GATELEVEL
`define NOFORCE 1
`endif
module Mtask
;
// This should mirror the reset state machine - we're interested in
// knowing when rsm has been cleared by rcc_rst_l .
Mflipflop_rh rst_rst(rst_initialized_l
, 1'b1,
~`misc.last_phi, ~(~`misc.rcc_rst_l & `misc.last_phi),
`misc.rcc_clk) ;
// When set, we'll use the CLK_RST TAP op to intialize clk_cntl; otherwise
// we'll just force clk_rst_l. pll_byp_l must be 0 if this is set!
reg use_jtag_clk_rst
, lofreq_clk_rst
;
// add pci_slave_mode for 2.0 slave mode to enable a pci reset since
// Eagle won't be doing it.
reg ext_clk2
, pll_byp_l
;
initial begin
$GetEnv("use_jtag_clk_rst", use_jtag_clk_rst) ;
$GetEnv("lofreq_clk_rst", lofreq_clk_rst) ;
$GetEnv("ext_clk2", ext_clk2) ;
$GetEnv("pll_byp_l", pll_byp_l) ;
end
// Used by the mode scripts. On exit, we are stopped just before the
// first non-reset ss_clock positive edge.
task do_reset ;
// 1-> initialize some IU signals for sas compatibility
input init_iu ;
begin
// Initialize some regs in the IU, for the sake of sas compare
if (init_iu) begin
`ifdef NOFORCE
Mclocks.print_error("Must use a no-force mode with this model") ;
`else
// force the tbr to agree with mpsas
force `IU.iuchip.exec.tbr_mod.hld_tt = 0 ;
force `IU.iuchip.exec.tbr_mod.tbr_unwr_wire = 'haa ;
// force the WIM to agree with mpsas
force `IU.iuchip.exec.wim_mod.wimm = 'hx ;
// force the Y-reg to agree with mpsas
force `IU.iuchip.exec.y_mod.ym = 'hx ;
// These are the undefined bits in the psr. In order to
// make I-I compare with mpsas work, we initialize them
// to '0' here.
force `IU.iuchip.exec.psr_mod.cc_mod.cc_next = 0 ;
force complete.cc_w_out = 0 ;
force `IU.iuchip.exec.psr_mod.cwp_mod.ncwp = 0 ;
force complete.ncwp = 0 ;
force `IU.iuchip.exec.psr_mod.pil_master_mux_out = 0 ;
force `IU.iuchip.exec.psr_mod.result[12] = 0 ;
force `IU.iuchip.exec.psr_mod.result[13] = 0 ;
force `IU.iuchip.exec.psr_mod.hld_pilefec = 0 ;
force `IU.iuchip.exec.psr_mod.ps_mod.nps = 1 ;
force `SSPARC_CORE.pipe_hold4ic = 0 ;
`endif
end
// Do the reset
Msystem.input_reset_l = 0 ;
Msystem.jtag_trst_l = 0 ;
// for 2.0 slave mode turn on pci reset since eagle won't
if (ext_clk2 && pll_byp_l)
force Msystem.RSTnn = 0;
fork
// Run clocks forever - we'll turn them off below.
Mclocks.cycles('h7fffffff,20,1,2,0) ;
// Reset the clock controller
#1 if (use_jtag_clk_rst) begin
// Can't do this if we're using the PLL
if (Msystem.pll_byp_l) Mclocks.print_error(
"can't do JTAG CLK_RST when using the PLL") ;
// We're bypassing the PLL - use the CLK_RST JTAG op;
misc_tasks.do_jtag_clk_rst(lofreq_clk_rst) ;
// The clock controller has been reset, and we're ready
// for the first ext_clk pulse.
end
else begin
// Just force clk_rst_l for one or two input_clock
// posedges, to sync free_clk with Mclocks.clock.
force `rl_clk_cntl.clk_rst_l = 0 ;
// also force the path to pci clocks to initialize since
// the clk_rst_l has been removed from these flops -
force `rl_clk_cntl.free_phase_pci = 3'h0;
// the following three forces will be required for gate level, so just
// leave them commented out for now. (replaces above 3)
// force `rl_clk_cntl.lsitkn_fppci_rega47Mflipflop_rh_2_0a47dffa47w0 = 0;
// force `rl_clk_cntl.lsitkn_fppci_rega47Mflipflop_rh_2_1a47dffa47w0 = 0;
// force `rl_clk_cntl.lsitkn_fppci_rega47Mflipflop_rh_2_2a47dffa47w0 = 0;
force `rl_clk_cntl.last_free_phase_pci = 0;
force `rl_clk_cntl.free_clock = 0;
force `rl_clk_cntl.pci_refclk_unbuf_ndly = 0;
force `rl_clk_cntl.pci_refclk_unbuf = 0;
force `rl_clk_cntl.pci_refclk_unbuf_ = 0;
// free_clk is being forced to 0 on each input_clock
// posedge. Wait for the input_clock at which
// Mclocks.clock will toggle to 0.
@(negedge `rl_clk_cntl.input_clock)
if (~Mclocks.clock) @(posedge `rl_clk_cntl.input_clock) ;
// Release the reset
#1 release `rl_clk_cntl.clk_rst_l ;
// now release all the path to the pci clocks -
release `rl_clk_cntl.free_phase_pci ;
// the following three releases will be required for gate level, so just
// leave them commented out for now. (replaces above )
// release `rl_clk_cntl.lsitkn_fppci_rega47Mflipflop_rh_2_0a47dffa47w0 ;
// release `rl_clk_cntl.lsitkn_fppci_rega47Mflipflop_rh_2_1a47dffa47w0 ;
// release `rl_clk_cntl.lsitkn_fppci_rega47Mflipflop_rh_2_2a47dffa47w0 ;
release `rl_clk_cntl.last_free_phase_pci ;
release `rl_clk_cntl.free_clock ;
release `rl_clk_cntl.pci_refclk_unbuf_ndly ;
release `rl_clk_cntl.pci_refclk_unbuf ;
release `rl_clk_cntl.pci_refclk_unbuf_ ;
end
begin
// Wait for the reset state machine to reset, then de-assert
@(posedge (rst_initialized_l===1'b0))
// Wait 15 clock cycles
repeat (15) @(posedge Mclocks.clock) ;
#1 Msystem.input_reset_l = 1 ;
// release pci reset for 2.0
if (ext_clk2 && pll_byp_l)
release Msystem.RSTnn;
`ifdef STOP_ON_RESET
// Special power-up sequence for scan testing:
// Stop issuing clocks when rst_cntl has reached the
// clocks stopped state
@(posedge `rl_clk_cntl.stopped)
Mclocks.cycles.n = 0 ;
`else
// Re-assert trst so clocks don't stop at the end of reset
Msystem.jtag_trst_l = 0 ;
// Stop issuing clocks when rst_cntl has deasserted its
// outputs and ss_clock is brought low for the first
// non-reset clock edge.
@(negedge `SS_SCOPE.reset)
@(negedge Msystem.clock)
Mclocks.cycles.n = 0 ;
`endif
end
join
// It's now right before the first posedge clock in which the
// internal reset is de-asserted.
`ifdef NOFORCE
`else
// Release the held nets
if (init_iu) begin
release `IU.iuchip.exec.tbr_mod.hld_tt ;
release `IU.iuchip.exec.tbr_mod.tbr_unwr_wire ;
release `IU.iuchip.exec.wim_mod.wimm ;
release `IU.iuchip.exec.y_mod.ym ;
release `IU.iuchip.exec.psr_mod.cc_mod.cc_next ;
release complete.cc_w_out ;
release `IU.iuchip.exec.psr_mod.cwp_mod.ncwp ;
release complete.ncwp ;
release `IU.iuchip.exec.psr_mod.pil_master_mux_out ;
release `IU.iuchip.exec.psr_mod.result[12] ;
release `IU.iuchip.exec.psr_mod.result[13] ;
release `IU.iuchip.exec.psr_mod.hld_pilefec ;
release `IU.iuchip.exec.psr_mod.ps_mod.nps ;
release `SSPARC_CORE.pipe_hold4ic ;
end
`endif
end
endtask
// Initialize the PCR to the given value.
`ifdef NOFORCE
`else
task init_pcr ;
// Initial PCR value
input [31:0] pcr ;
begin
// Assign to the reg which drives the PCR output nets. This
// reg is clock enabled whenever the IU pipe is not held.
`MMU.MMU_cntl.mmu_regs.mmu_cr_out = {
pcr[23], // ST
pcr[22], // WP
pcr[21], // BF
pcr[20:19], // PMC
pcr[18], // PE
pcr[17], // PC
pcr[16], // AP
pcr[15], // AC
~pcr[14], // ~BM
pcr[13:10], // RFR CNTL
pcr[9], // IE
pcr[8], // DE
pcr[7], // Superviosr cache allocate disable
pcr[1], // NF
pcr[0] // EN
} ;
// Assign to the regs which drive the inputs of the
// above reg. These regs are strobed on PCR writes.
`MMU.MMU_cntl.mmu_regs.mmu_cr_rega = {
`MMU.MMU_cntl.mmu_regs.mmu_cr_out[18:10],
`MMU.MMU_cntl.mmu_regs.mmu_cr_out[8:5],
`MMU.MMU_cntl.mmu_regs.mmu_cr_out[2:1]
} ;
`MMU.MMU_cntl.mmu_regs.mmu_cr_regw = {
`MMU.MMU_cntl.mmu_regs.mmu_cr_out[9],
`MMU.MMU_cntl.mmu_regs.mmu_cr_out[4:3],
`MMU.MMU_cntl.mmu_regs.mmu_cr_out[0]
} ;
end
endtask
`endif
// Tasks to dump memory.
// Virtual-to-physical translation
function [31:0] phys ;
input [31:0] cid ;
input [31:0] virt_adr ;
begin
// For now, phys=virt
phys = virt_adr ;
end
endfunction
// Task to display a word. It displays either as four hex bytes,
// or as a dis-assembled opcode
task dispwd ;
input disassemble ;
input [1:0] mem_type ;
input [31:0] adr ;
input begin_line ;
input begin_block ;
reg [31:0] word ;
reg dummy ;
begin
word = read_mem(mem_type, adr) ;
// Display opcode if specified (unless parity is bad)
if (disassemble) begin
$write("%x: %x ", padr(mem_type, adr), word) ;
if (^word===1'bx) $display ;
else dummy = $disassemble(word, 0) ;
end
else begin
if (begin_line) begin
if (begin_block) $write("%x: ", padr(mem_type, adr)) ;
else $write(" ") ;
end
$write(" %h %h %h %h ",
word[31:24], word[23:16], word[15:8], word[7:0]) ;
end
end
endtask
function [31:0] read_mem ;
input [1:0] mem_type ;
input [31:0] mem_adr ;
reg [31:0] adr, a ;
reg [32:0] sparse_mem_adr; // need 33 bits sparse memory model
reg [63:0] mem_data; // temp reg for sparse memory model
begin
case (mem_type)
// I-Cache
0: begin
// Word-align the virtual address
adr = mem_adr & `ic_maxbyte & ~32'b11 ;
read_mem =
{`ICACHE[adr], `ICACHE[adr+1],
`ICACHE[adr+2], `ICACHE[adr+3]} ;
end
// D-Cache
1: begin
// Word-align the virtual address
adr = mem_adr & `dc_maxbyte & ~32'b11 ;
read_mem =
{`DCACHE[adr], `DCACHE[adr+1],
`DCACHE[adr+2], `DCACHE[adr+3]} ;
end
// Memory
2: begin
// This is a *physical* address, not virtual
// Doubleword-align the address
adr = mem_adr & ~32'b111 ;
sparse_mem_adr = {1'b0, adr >> 3} ;
mem_data = 64'h0;
$mem_read(Msystem.TheRam.memHandle, sparse_mem_adr, 8'b11111111, mem_data) ;
// $display("sp_a:%h", sparse_mem_adr, "m_data:%h ", mem_data);
if (mem_adr[2]) begin
// Odd-word RAM
read_mem = mem_data[31:0] ;
end
else begin
// Even-word RAM
read_mem = mem_data[63:32] ;
end
end
endcase
end
endfunction
// Return the address held in a cache tag at a virtual address.
// For mem_type==2 (memory), just return tha address we were called with.
function [31:0] padr ;
input [1:0] mem_type ;
input [31:0] adr ;
reg [31:0] tag ;
begin
padr = 0 ; // clear unused bits
case (mem_type)
0: begin
padr[(`it_lspa-1):0] = adr[(`it_lspa-1):0] ;
tag = `ITAG[(adr>>`log2_iblksize)&`it_maxblks] ;
padr[(`it_msb+`it_lspa):`it_lspa]
// LSB of ITag is hard-wired to 0
= tag[`dt_msb:1] ;
end
1: begin
padr[(`dt_lspa-1):0] = adr[(`dt_lspa-1):0] ;
tag = `DTAG[(adr>>`log2_dblksize)&`dt_maxblks] ;
padr[(`dt_msb+`dt_lspa):`dt_lspa]
= tag[`dt_msb:0] ;
end
2: begin
padr = adr ;
end
endcase
end
endfunction
// Task to display tlb entries
// dtlb(<start_adr>, <#_of_entries>) ;
// take out conditional don't compile when gate level MMU -bih
task dtlb ;
input [31:0] start_adr, n_entries ;
reg [5:0] adr ;
reg [41:0] tlb_tag ;
reg [27:0] tlb_data;
reg [8:0] index1;
reg [7:0] context ;
reg [5:0] index2, index3;
reg [2:0] lvl ;
reg valid_bit, lvl_1, lvl_2, lvl_3 , supervisor, io_pte, ptp_bit ;
reg ue, ur, uw, se, sr, sw ;
reg [18:0] ppn;
reg [22:0] ptp;
reg m_bit_tag, c_bit, m_bit, r_bit, w_bit;
reg [2:0] acc;
begin
adr = start_adr ; // Truncate to 6 bits
repeat (n_entries) begin
// added this to allow to work on gate level simulations -bih
`ifdef MMU_GATE_LEVEL
// gate level tlb paths
case(adr)
0: tlb_tag = `mc_tlb.TLB_cam.tag00_out;
1: tlb_tag = `mc_tlb.TLB_cam.tag01_out;
2: tlb_tag = `mc_tlb.TLB_cam.tag02_out;
3: tlb_tag = `mc_tlb.TLB_cam.tag03_out;
4: tlb_tag = `mc_tlb.TLB_cam.tag04_out;
5: tlb_tag = `mc_tlb.TLB_cam.tag05_out;
6: tlb_tag = `mc_tlb.TLB_cam.tag06_out;
7: tlb_tag = `mc_tlb.TLB_cam.tag07_out;
8: tlb_tag = `mc_tlb.TLB_cam.tag08_out;
9: tlb_tag = `mc_tlb.TLB_cam.tag09_out;
10: tlb_tag = `mc_tlb.TLB_cam.tag10_out;
11: tlb_tag = `mc_tlb.TLB_cam.tag11_out;
12: tlb_tag = `mc_tlb.TLB_cam.tag12_out;
13: tlb_tag = `mc_tlb.TLB_cam.tag13_out;
14: tlb_tag = `mc_tlb.TLB_cam.tag14_out;
15: tlb_tag = `mc_tlb.TLB_cam.tag15_out;
16: tlb_tag = `mc_tlb.TLB_cam.tag16_out;
17: tlb_tag = `mc_tlb.TLB_cam.tag17_out;
18: tlb_tag = `mc_tlb.TLB_cam.tag18_out;
19: tlb_tag = `mc_tlb.TLB_cam.tag19_out;
20: tlb_tag = `mc_tlb.TLB_cam.tag20_out;
21: tlb_tag = `mc_tlb.TLB_cam.tag21_out;
22: tlb_tag = `mc_tlb.TLB_cam.tag22_out;
23: tlb_tag = `mc_tlb.TLB_cam.tag23_out;
24: tlb_tag = `mc_tlb.TLB_cam.tag24_out;
25: tlb_tag = `mc_tlb.TLB_cam.tag25_out;
26: tlb_tag = `mc_tlb.TLB_cam.tag26_out;
27: tlb_tag = `mc_tlb.TLB_cam.tag27_out;
28: tlb_tag = `mc_tlb.TLB_cam.tag28_out;
29: tlb_tag = `mc_tlb.TLB_cam.tag29_out;
30: tlb_tag = `mc_tlb.TLB_cam.tag30_out;
31: tlb_tag = `mc_tlb.TLB_cam.tag31_out;
// 32: tlb_tag = `mc_tlb.TLB_cam.tag32_out;
// 33: tlb_tag = `mc_tlb.TLB_cam.tag33_out;
// 34: tlb_tag = `mc_tlb.TLB_cam.tag34_out;
// 35: tlb_tag = `mc_tlb.TLB_cam.tag35_out;
// 36: tlb_tag = `mc_tlb.TLB_cam.tag36_out;
// 37: tlb_tag = `mc_tlb.TLB_cam.tag37_out;
// 38: tlb_tag = `mc_tlb.TLB_cam.tag38_out;
// 39: tlb_tag = `mc_tlb.TLB_cam.tag39_out;
// 40: tlb_tag = `mc_tlb.TLB_cam.tag40_out;
// 41: tlb_tag = `mc_tlb.TLB_cam.tag41_out;
// 42: tlb_tag = `mc_tlb.TLB_cam.tag42_out;
// 43: tlb_tag = `mc_tlb.TLB_cam.tag43_out;
// 44: tlb_tag = `mc_tlb.TLB_cam.tag44_out;
// 45: tlb_tag = `mc_tlb.TLB_cam.tag45_out;
// 46: tlb_tag = `mc_tlb.TLB_cam.tag46_out;
// 47: tlb_tag = `mc_tlb.TLB_cam.tag47_out;
// 48: tlb_tag = `mc_tlb.TLB_cam.tag48_out;
// 49: tlb_tag = `mc_tlb.TLB_cam.tag49_out;
// 50: tlb_tag = `mc_tlb.TLB_cam.tag50_out;
// 51: tlb_tag = `mc_tlb.TLB_cam.tag51_out;
// 52: tlb_tag = `mc_tlb.TLB_cam.tag52_out;
// 53: tlb_tag = `mc_tlb.TLB_cam.tag53_out;
// 54: tlb_tag = `mc_tlb.TLB_cam.tag54_out;
// 55: tlb_tag = `mc_tlb.TLB_cam.tag55_out;
// 56: tlb_tag = `mc_tlb.TLB_cam.tag56_out;
// 57: tlb_tag = `mc_tlb.TLB_cam.tag57_out;
// 58: tlb_tag = `mc_tlb.TLB_cam.tag58_out;
// 59: tlb_tag = `mc_tlb.TLB_cam.tag59_out;
// 60: tlb_tag = `mc_tlb.TLB_cam.tag60_out;
// 61: tlb_tag = `mc_tlb.TLB_cam.tag61_out;
// 62: tlb_tag = `mc_tlb.TLB_cam.tag62_out;
// 63: tlb_tag = `mc_tlb.TLB_cam.tag63_out;
endcase
tlb_data = `mc_tlb.TLB_ram.tlb_data[adr];
`else
`ifdef RTL_TLB
case(adr)
0: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag00_out;
1: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag01_out;
2: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag02_out;
3: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag03_out;
4: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag04_out;
5: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag05_out;
6: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag06_out;
7: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag07_out;
8: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag08_out;
9: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag09_out;
10: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag10_out;
11: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag11_out;
12: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag12_out;
13: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag13_out;
14: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag14_out;
15: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag15_out;
16: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag16_out;
17: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag17_out;
18: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag18_out;
19: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag19_out;
20: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag20_out;
21: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag21_out;
22: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag22_out;
23: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag23_out;
24: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag24_out;
25: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag25_out;
26: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag26_out;
27: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag27_out;
28: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag28_out;
29: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag29_out;
30: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag30_out;
31: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag31_out;
// 32: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag32_out;
// 33: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag33_out;
// 34: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag34_out;
// 35: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag35_out;
// 36: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag36_out;
// 37: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag37_out;
// 38: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag38_out;
// 39: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag39_out;
// 40: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag40_out;
// 41: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag41_out;
// 42: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag42_out;
// 43: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag43_out;
// 44: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag44_out;
// 45: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag45_out;
// 46: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag46_out;
// 47: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag47_out;
// 48: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag48_out;
// 49: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag49_out;
// 50: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag50_out;
// 51: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag51_out;
// 52: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag52_out;
// 53: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag53_out;
// 54: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag54_out;
// 55: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag55_out;
// 56: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag56_out;
// 57: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag57_out;
// 58: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag58_out;
// 59: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag59_out;
// 60: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag60_out;
// 61: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag61_out;
// 62: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag62_out;
// 63: tlb_tag = `MMU.MMU_tlb.TLB_cam.tag63_out;
endcase
tlb_data = `MMU.MMU_tlb.TLB_ram.tlb_data[adr];
`else
tlb_tag = `MMU.MMU_tlb.tlb_tag[adr];
tlb_data = `MMU.MMU_tlb.tlb_data[adr];
`endif
`endif
valid_bit = tlb_tag[ 41];
lvl_1 = tlb_tag[ 40];
index1 = tlb_tag[ 39:32];
lvl_2 = tlb_tag[ 31];
index2 = tlb_tag[ 30:25];
lvl_3 = tlb_tag[ 24];
index3 = tlb_tag[ 23:18];
context = tlb_tag[ 17:10];
ue = tlb_tag[ 9];
ur = tlb_tag[ 8];
uw = tlb_tag[ 7];
se = tlb_tag[ 6];
sr = tlb_tag[ 5];
sw = tlb_tag[ 4];
supervisor = tlb_tag[ 3];
io_pte = tlb_tag[ 2];
ptp_bit = tlb_tag[ 1];
m_bit_tag = tlb_tag[ 0];
lvl = tlb_data[ 27:25];
ppn = tlb_data[ 24:6];
c_bit = tlb_data[ 5];
m_bit = tlb_data[ 4];
r_bit = tlb_data[ 3];
acc = tlb_data[ 2:0];
w_bit = tlb_data[ 0];
ptp = tlb_data[24:2];
$write("ent:%h v:%b vpn:%h lvl:%h s:%b io:%b p:%b cxt:%h ",
adr, valid_bit, {index1, index2, index3},
{lvl_1, lvl_2, lvl_3}, supervisor, io_pte,
ptp_bit,context);
case ({valid_bit, io_pte, ptp_bit})
3'b100: begin // valid, pte
$display("ppn:%h c:%b m:%b r:%b acc:%h (pte)",
ppn, c_bit, m_bit, r_bit, acc);
end
3'b101: begin // valid, ptp
$display("ptp:%h (ptp)", ptp);
end
3'b110: begin // valid, io_pte
$display("ppn:%h w:%b (io_pte)",
ppn, w_bit);
end
3'b111: begin // illegal, (io_ptp?)
$display("vptp:%h (ptp)", ptp);
end
3'b000, 3'b001, 3'b010, 3'b011, 3'b0xx: begin
$display("(..inv..)");
end
default: begin
$display("(..xxx..)");
end
endcase
adr = adr + 1;
end
end
endtask
// Task to display 32-byte blocks of memory
// dmemn(<dcache/icache>, <start_adr>, <#_of_blocks>, <disassemble>) ;
task dmemn ;
input [1:0] mem_type ;
input [31:0] start_adr, n_blocks ;
input disassemble ;
reg [31:0] adr, stopadr ;
reg [31:0] cid ;
integer line ;
reg [31:0] blocksize, maxbyte ;
reg [31:0] tag, pa ;
reg [31:0] mem_lbl ;
reg [71:0] vhdr ;
reg [4:0] supv_lvl ;
begin
case (mem_type)
0: begin
mem_lbl = "I VA" ;
vhdr = "V S Ctx L" ;
blocksize = `ic_blksize ;
maxbyte = `ic_maxbyte ;
end
1: begin
mem_lbl = "D VA" ;
vhdr = "V A Ctx " ;
blocksize = `dc_blksize ;
maxbyte = `dc_maxbyte ;
end
2: begin
mem_lbl = "M PA" ;
vhdr = "" ;
blocksize = 32 ;
maxbyte = `main_mem_size-1 ;
end
endcase
adr = start_adr & ~(blocksize-1) ;
$write("--%s--", mem_lbl) ;
if (disassemble) $display ;
else $display(
" 0 1 2 3 4 5 6 7 8 9 a b c d e f %0s",
vhdr) ;
repeat (n_blocks) begin
adr = adr & maxbyte ;
stopadr = adr + blocksize ;
line = 1 ;
while (adr < stopadr) begin
dispwd(disassemble, mem_type, adr, 1, (line==1)) ;
dispwd(disassemble, mem_type, adr+4, 0, 0) ;
dispwd(disassemble, mem_type, adr+8, 0, 0) ;
dispwd(disassemble, mem_type, adr+12, 0, 0) ;
if (!disassemble) begin
if (line==1) case (mem_type)
// ITag
0: begin
supv_lvl = `ITAGA[adr/blocksize] ;
$write(" %b %b %h %h",
`ITAGV[adr/blocksize],
supv_lvl[3],
`ITAGC[adr/blocksize],
supv_lvl[1:0]
) ;
end
// DTag
1: $write(" %b %0h %h",
`DTAGV[adr/blocksize],
acc_decode(`DTAGA[adr/blocksize]),
`DTAGC[adr/blocksize]
) ;
endcase
$display("") ;
end
adr = adr + 16 ;
line = line + 1 ;
end
end
end
endtask
// Decode the encoded ACC field from a cache tag
function [2:0] acc_decode ;
input [4:0] encoded_acc ;
acc_decode =
(encoded_acc==5'h06) ? 0 : (
(encoded_acc==5'h02) ? 1 : (
(encoded_acc==5'h04) ? 2 : (
(encoded_acc==5'h00) ? 3 : (
(encoded_acc==5'h01) ? 4 : (
(encoded_acc==5'h10) ? 5 : (
(encoded_acc==5'h0c) ? 6 : (
(encoded_acc==5'h08) ? 7 : (
3'bx )))))))) ;
endfunction
// Task to alter Tag values
task altertag ;
input [1:0] mem_type ;
input [31:0] a,v,n ;
integer foo, adr, stopadr, blocksize, tag_adr ;
reg [7:0] cid ; // Should be an input?
reg [4:0] encoded_acc ; // Should be an input?
reg [31:0] phys_adr ;
reg [`dt_msb:0] dtva ;
reg [`it_msb:0] itva ;
begin
// These should be supplied as inputs
cid = 0 ;
encoded_acc = 0 ;
blocksize = mem_type[0] ? `dc_blksize : `ic_blksize ;
stopadr=a+(n*blocksize) ;
if (n>1) $write("Initializing %c-tags %h through %h . . . ",
mem_type[0] ? "D" : "I",
a,stopadr-blocksize);
for (adr=a;(adr===a)||(adr<stopadr);adr=adr+blocksize) begin
phys_adr = phys(cid,adr) ;
if (mem_type) begin
tag_adr = (adr >> `log2_dblksize) & `dt_maxblks ;
dtva = phys_adr>>`dt_lspa ;
`DTAG[tag_adr] = dtva ;
`DTAGC[tag_adr] = cid ;
`DTAGA[tag_adr] = encoded_acc ;
// Don't change V-bit unless 0 or 1 is specified
if ((v & ~1)===0) `DTAGV[tag_adr] = v ;
end
else begin
tag_adr = (adr >> `log2_iblksize) & `it_maxblks ;
itva = phys_adr>>`it_lspa ;
// LSB of ITag is 0.
`ITAG[tag_adr] = {itva,1'b0} ;
`ITAGC[tag_adr] = cid ;
`ITAGA[tag_adr] = encoded_acc ;
// Don't change V-bit unless 0 or 1 is specified
if ((v & ~1)===0) `ITAGV[tag_adr] = v ;
end
end
if (n>1) $display("done");
end
endtask
function tag_match ;
input [1:0] mem_type ;
input [31:0] cid ;
input [31:0] virt_adr ;
reg [31:0] pcr ;
reg cache_enabled, tag_valid ;
begin
// Check PCR to see if this cache is enabled.
`ifdef MMU_GATE_LEVEL
/* changed to match Seagle synthesis netlist. 6/22/98.
pcr[15] = `m_mmu_cntl.mmu_regs_mmu_cr_19_MflipflopR_18_10_dff.Q;
pcr[9] = `m_mmu_cntl.mmu_regs_mmu_cr_19_MflipflopR_18_4_dff.Q;
pcr[8] = `m_mmu_cntl.mmu_regs_mmu_cr_19_MflipflopR_18_3_dff.Q;
pcr[0] = `m_mmu_cntl.mmu_regs_mmu_cr_19_MflipflopR_18_0_dff.Q;
*/
pcr[15] = `m_mmu_cntl.mmu_regs.mmu_cr[15];
pcr[9] = `m_mmu_cntl.mmu_regs.mmu_cr[9];
pcr[8] = `m_mmu_cntl.mmu_regs.mmu_cr[8];
pcr[0] = `m_mmu_cntl.mmu_regs.mmu_cr[0];
`else
pcr = `MMU.pcr ;
`endif
cache_enabled =
(pcr[0] | pcr[15]) // mmu_en or alt_cacheablity
& (mem_type[0] ? pcr[8] : pcr[9])
;
tag_valid = mem_type[0]
? `DTAGV[(virt_adr >> `log2_dblksize) & `dt_maxblks]
: `ITAGV[(virt_adr >> `log2_iblksize) & `it_maxblks]
;
tag_match =
cache_enabled & tag_valid
& ( phys(cid, virt_adr) == padr(mem_type, virt_adr) )
;
if (~cache_enabled && tag_valid) begin
$display(
"\n### tag_match: %s-cache disabled but tag valid at virtual address %h",
mem_type[0] ? "D" : "I",
virt_adr) ;
Mclocks.warning_count = Mclocks.warning_count + 1 ;
end
end
endfunction
// Get the addressed word from memory.
function [31:0] getword ;
input nomem ;
input [31:0] cid ;
input [31:0] virt_adr ;
reg imatch, dmatch ;
reg [31:0] iword, dword, mword ;
begin
if (nomem) mword = 32'bx ;
else mword = read_mem(2, phys(cid, virt_adr)) ;
// ******
// force imatch to 0 for now to disable icache - dcache - mem
// checking.
// we'll eventually want to do this via a switch and
// variable in vfront!!!!
//
// imatch = tag_match(0, cid, virt_adr) ;
imatch = 0;
dmatch = tag_match(1, cid, virt_adr) ;
if (dmatch) begin
dword = read_mem(1, virt_adr) ;
if (~nomem && (dword !== mword)) begin
$display(
"\n### getword: mismatch: D-cache=%h, Memory=%h at %h in Context %0h",
dword, mword,
virt_adr, cid) ;
Mclocks.warning_count = Mclocks.warning_count + 1 ;
end
end
if (imatch) begin
iword = read_mem(0, virt_adr) ;
if (~nomem && (iword !== mword)) begin
$display(
"\n### getword: mismatch: I-cache=%h, Memory=%h at %h in Context %0h",
iword, mword,
virt_adr, cid) ;
Mclocks.warning_count = Mclocks.warning_count + 1 ;
end
end
case ({imatch, dmatch})
2'b01: begin
getword = dword ;
end
2'b10: begin
getword = iword ;
end
2'b11: begin
getword = dword ;
if (dword !== iword) begin
$display(
"\n### getword: mismatch: I-cache=%h, D-cache=%h at %h in Context %0h",
iword, getword,
virt_adr, cid) ;
Mclocks.warning_count = Mclocks.warning_count + 1 ;
end
end
2'b00: begin
getword = mword ;
end
default: begin
$display(
"\n*** getword: I-tagmatch=%b, D-tagmatch=%b at %h in Context %0h",
imatch, dmatch,
virt_adr, cid) ;
Mclocks.error_count = Mclocks.error_count + 1 ;
getword = 32'bx ;
end
endcase
end
endfunction
// Task to dump memory in SAS format.
// Takes a virtual address and context ID.
task mdump ;
input nomem ;
input [31:0] cid ;
input [31:0] start_wd, stop_wd, boot_wd ;
reg [31:0] start_adr, stop_adr, virt_adr, word ;
reg [31:0] dumpfile ;
begin
start_adr = start_wd*4 ;
stop_adr = stop_wd*4 ;
$write("Dumping Virtual locations %h:%h in Context %0h . . . ",
start_adr, stop_adr+3, cid) ;
dumpfile = $fopen({Mclocks.working_dir,"/mdump.v"}) ;
// Now dump from cache/memory
for (virt_adr=start_adr ;
virt_adr <= stop_adr ;
virt_adr = virt_adr+4 ) begin
word = getword(nomem, cid, virt_adr) ;
$fdisplay(dumpfile, " 0x%h", word) ;
end
$fclose(dumpfile) ;
$display("done");
end
endtask
// Task to compare a range of virtual memory in a given context
// to the pattern written by adrinit.
task wbcomp ;
input nomem ;
input [31:0] start_wd, stop_wd ;
input [6:0] cid ;
reg [31:0] start_adr, stop_adr, virt_adr ;
reg [31:0] compfile ;
reg [31:0] word ;
reg [15:0] va, va2 ;
reg [31:0] err_count ;
begin
start_adr = start_wd*4 ;
stop_adr = stop_wd*4 ;
err_count = 0 ;
$display("Checking Virtual locations %h:%h in Context %h . . . ",
start_adr, stop_adr+3, cid) ;
compfile = $fopen({Mclocks.working_dir,"/wb.comp"}) ;
for (virt_adr=start_adr ;
virt_adr <= stop_adr ;
virt_adr = virt_adr+4 ) begin
va = virt_adr ;
va2 = virt_adr+2 ;
word = getword(nomem, cid, virt_adr) ;
// **** changed {va, va2} to ffffffff
// Changes needed to work with new sparse memory
// model. The sparse memory model initializes
// unused locations to 'ffffffff'...
// note 2: switched it to 'h0 until IU fixed
if (word !== 'h0 ) begin
$fdisplay(compfile|1, "*** wbcomp: %h had 0x%h, should be 0x%h in Context %h",
virt_adr, word,'h00000000 , cid) ;
err_count = err_count + 1 ;
end
end
$fclose(compfile) ;
This page: |
Created: | Thu Aug 19 12:00:49 1999 |
| From: |
../../../sparc_v8/env/rtl/task.v
|