Line 25... |
Line 25... |
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for more details.
|
// for more details.
|
//
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program. (It's in the $(ROOT)/doc directory. Run make with no
|
|
// target there if the PDF file isn't present.) If not, see
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
|
//
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// http://www.gnu.org/licenses/gpl.html
|
// http://www.gnu.org/licenses/gpl.html
|
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
Line 40... |
Line 45... |
#include <verilated_vcd_c.h>
|
#include <verilated_vcd_c.h>
|
#include "testb.h"
|
#include "testb.h"
|
#include "Vzipmmu_tb.h"
|
#include "Vzipmmu_tb.h"
|
|
|
#define MMUFLAG_RONW 8 // Read only (not writeable)
|
#define MMUFLAG_RONW 8 // Read only (not writeable)
|
#define MMUFLAG_ACCS 4 // Accessed
|
#define MMUFLAG_EXE 4 // Page may be executed
|
#define MMUFLAG_CCHE 2 // Cachable
|
#define MMUFLAG_CCHE 2 // Cachable
|
#define MMUFLAG_THSP 1 // Page has this context
|
#define MMUFLAG_ACCS 1 // Accessed
|
|
#define ROFLAG 8 // This page is read-only
|
|
#define EXFLAG 4 // This page is executable
|
|
#define CHFLAG 2 // This page may be cached
|
|
#define AXFLAG 1 // This page has been accessed since loading
|
|
|
|
#define setup_stb i_ctrl_cyc_stb
|
|
#define setup_ack o_rtn_ack
|
|
#define setup_stall o_rtn_stall
|
|
#define setup_data o_rtn_data
|
|
#define mem_cyc v__DOT__mem_cyc
|
|
#define mem_stb v__DOT__mem_stb
|
|
#define mem_we v__DOT__mem_we
|
|
#define mem_r_we v__DOT__mut__DOT__r_we
|
|
#define mem_r_valid v__DOT__mut__DOT__r_valid
|
|
#define mem_addr v__DOT__mem_addr
|
|
#define mem_err v__DOT__mem_err
|
|
#define wr_vtable v__DOT__mut__DOT__wr_vtable
|
|
#define wr_ptable v__DOT__mut__DOT__wr_ptable
|
|
#define wr_control v__DOT__mut__DOT__wr_control
|
|
#define z_context __PVT__mut__DOT__z_context
|
|
#define context_word v__DOT__mut__DOT__r_context_word
|
|
#define r_pending v__DOT__mut__DOT__r_pending
|
|
#define r_we v__DOT__mut__DOT__r_we
|
|
#define r_valid v__DOT__mut__DOT__r_valid
|
|
#define r_addr v__DOT__mut__DOT__r_addr
|
|
#define r_data v__DOT__mut__DOT__r_data
|
|
|
|
#define R_CONTROL 0
|
|
#define R_STATUS 4
|
|
#define R_TABLESZ(LGSZ) (8<<LGSZ)
|
|
#define R_ENTRYSZ(LGSZ,K) (R_TABLESZ(LGSZ)+(K<<3))
|
|
#define R_TABLE (8<<LGTBL)
|
|
#define R_VENTRY(K) ((8<<LGTBL)+(K<<3))
|
|
#define R_PENTRY(K) (R_VENTRY(K)+4)
|
|
#define LOCONTEXT(C) ((C<<4)&((1<<LGPGSZ)-1))
|
|
#define HICONTEXT(C) (((C>>(LGPGSZ-4))<<4)&((1<<LGPGSZ)-1))
|
|
|
const int BOMBCOUNT = 32,
|
const int BOMBCOUNT = 32,
|
LGMEMSIZE = 15;
|
LGMEMSIZE = 15;
|
|
|
class ZIPMMU_TB : public TESTB<Vzipmmu_tb> {
|
class ZIPMMU_TB : public TESTB<Vzipmmu_tb> {
|
Line 58... |
Line 99... |
ZIPMMU_TB(void) {
|
ZIPMMU_TB(void) {
|
m_debug = true;
|
m_debug = true;
|
m_last_tlb_index = 0;
|
m_last_tlb_index = 0;
|
}
|
}
|
|
|
#define v__DOT__mem_stb v__DOT__mut__DOT__r_valid
|
|
void tick(void) {
|
void tick(void) {
|
|
|
TESTB<Vzipmmu_tb>::tick();
|
TESTB<Vzipmmu_tb>::tick();
|
|
|
bool writeout = true;
|
bool writeout = true;
|
|
|
if ((m_debug)&&(writeout)) {
|
if ((m_debug)&&(writeout)) {
|
printf("%08lx-MMU: ", m_tickcount);
|
printf("%08lx-MMU: ", m_tickcount);
|
printf("(%s%s%s%s) %08x (%s%s%s)%08x%s %s %08x/%08x %s%s%s%s%s",
|
printf("(%s%s%s%s%s%s) %08x (%s%s%s)%08x%s %s %08x/%08x %s%s%s%s",
|
(m_core->i_ctrl_cyc_stb)?"CT":" ",
|
(m_core->setup_stb)?"CT":" ",
|
(m_core->i_wbm_cyc)?"CYC":" ",
|
(m_core->i_wbm_cyc)?"CYC":" ",
|
(m_core->i_wbm_stb)?"STB":" ",
|
(m_core->i_wbm_stb)?"STB":" ",
|
(m_core->i_wb_we)?"WE":" ",
|
(m_core->i_wb_we)?"WE":" ",
|
|
(m_core->i_gie)?"IE":" ",
|
|
(m_core->i_exe)?"EX":" ",
|
(m_core->i_wb_addr),
|
(m_core->i_wb_addr),
|
(m_core->v__DOT__mem_cyc)?"CYC":" ",
|
(m_core->mem_cyc)?"CYC":" ",
|
(m_core->v__DOT__mem_stb)?"STB":" ",
|
(m_core->mem_stb)?"STB":" ",
|
#define v__DOT__mem_we v__DOT__mut__DOT__r_we
|
(m_core->mem_we)?"WE":" ",
|
(m_core->v__DOT__mem_we)?"WE":" ",
|
(m_core->mem_addr),
|
(m_core->v__DOT__mem_addr),
|
(m_core->mem_err)?"ER":" ",
|
(m_core->v__DOT__mem_err)?"ER":" ",
|
|
(m_core->i_wb_we)?"<-":"->",
|
(m_core->i_wb_we)?"<-":"->",
|
(m_core->i_wb_we)?m_core->i_wb_data:m_core->o_rtn_data,
|
(m_core->i_wb_we)?m_core->i_wb_data:m_core->o_rtn_data,
|
(m_core->v__DOT__mem_we)?m_core->v__DOT__mut__DOT__r_data:m_core->v__DOT__mem_odata,
|
(m_core->mem_we)?m_core->r_data:m_core->v__DOT__mem_odata,
|
(m_core->o_rtn_stall)?"STALL":" ",
|
(m_core->o_rtn_stall)?"STALL":" ",
|
(m_core->v__DOT__mut__DOT__setup_ack)?"S":" ",
|
|
(m_core->o_rtn_ack )?"ACK":" ",
|
(m_core->o_rtn_ack )?"ACK":" ",
|
(m_core->o_rtn_miss)?"MISS":" ",
|
(m_core->o_rtn_miss)?"MISS":" ",
|
(m_core->o_rtn_err )?"ERR":" ");
|
(m_core->o_rtn_err )?"ERR":" ");
|
|
|
printf("[%d,%d]",
|
printf("[%c]",
|
m_core->v__DOT__mut__DOT__wr_vtable,
|
(m_core->wr_control)?'C'
|
m_core->v__DOT__mut__DOT__wr_ptable);
|
:(m_core->wr_vtable)?'V'
|
printf("[%d,%d,%04x]",
|
:(m_core->wr_ptable)?'P'
|
m_core->v__DOT__mut__DOT__wr_control,
|
:'-');
|
m_core->v__DOT__mut__DOT__z_context,
|
printf("[%c,%04x]",
|
|
(m_core->v__DOT__mut__DOT__kernel_context)?'K'
|
|
:(m_core->v__DOT__mut__DOT__z_context)?'Z':'-',
|
m_core->v__DOT__mut__DOT__r_context_word);
|
m_core->v__DOT__mut__DOT__r_context_word);
|
/*
|
|
printf("[%08x,%08x-%08x]",
|
|
m_core->v__DOT__mut__DOT__w_vtable_reg,
|
|
m_core->v__DOT__mut__DOT__w_ptable_reg,
|
|
m_core->v__DOT__mut__DOT__setup_data);
|
|
*/
|
|
printf(" %s[%s%s@%08x,%08x]",
|
printf(" %s[%s%s@%08x,%08x]",
|
(m_core->v__DOT__mut__DOT__r_pending)?"R":" ",
|
(m_core->r_pending)?"R":" ",
|
(m_core->v__DOT__mut__DOT__r_we)?"W":" ",
|
(m_core->r_we)?"W":" ",
|
(m_core->v__DOT__mut__DOT__r_valid)?"V":" ",
|
(m_core->r_valid)?"V":" ",
|
(m_core->v__DOT__mut__DOT__r_addr),
|
(m_core->r_addr),
|
(m_core->v__DOT__mut__DOT__r_data));
|
(m_core->r_data));
|
printf("@%2x[%s%s%s][%s%s%s%s]",
|
printf("@%2x[%s%s%s][%s%s%s%s%s]",
|
(m_core->v__DOT__mut__DOT__s_tlb_addr),
|
(m_core->v__DOT__mut__DOT__s_tlb_addr),
|
(m_core->v__DOT__mut__DOT__s_pending)?"P":" ",
|
(m_core->v__DOT__mut__DOT__s_pending)?"P":" ",
|
(m_core->v__DOT__mut__DOT__s_tlb_hit)?"HT":" ",
|
(m_core->v__DOT__mut__DOT__s_tlb_hit)?"HT":" ",
|
(m_core->v__DOT__mut__DOT__s_tlb_miss)?"MS":" ",
|
(m_core->v__DOT__mut__DOT__s_tlb_miss)?"MS":" ",
|
(m_core->v__DOT__mut__DOT__ro_flag)?"RO":" ",
|
(m_core->v__DOT__mut__DOT__ro_flag)?"RO":" ",
|
(m_core->v__DOT__mut__DOT__simple_miss)?"SM":" ",
|
(m_core->v__DOT__mut__DOT__simple_miss)?"SM":" ",
|
(m_core->v__DOT__mut__DOT__ro_miss)?"RM":" ",
|
(m_core->v__DOT__mut__DOT__ro_miss)?"RM":" ",
|
|
(m_core->v__DOT__mut__DOT__exe_miss)?"EX":" ",
|
(m_core->v__DOT__mut__DOT__table_err)?"TE":" ");
|
(m_core->v__DOT__mut__DOT__table_err)?"TE":" ");
|
//(m_core->v__DOT__mut__DOT__cachable)?"CH":" ");
|
//(m_core->v__DOT__mut__DOT__cachable)?"CH":" ");
|
/*
|
/*
|
printf(" M[%016lx]",
|
printf(" M[%016lx]",
|
m_core->v__DOT__mut__DOT__r_tlb_match);
|
m_core->v__DOT__mut__DOT__r_tlb_match);
|
printf(" P[%3d] = 0x%08x, V=0x%08x, C=0x%08x, CTXT=%04x",
|
|
m_last_tlb_index,
|
|
m_core->v__DOT__mut__DOT__tlb_pdata[m_last_tlb_index],
|
|
m_core->v__DOT__mut__DOT__tlb_vdata[m_last_tlb_index],
|
|
m_core->v__DOT__mut__DOT__tlb_cdata[m_last_tlb_index],
|
|
m_core->v__DOT__mut__DOT__r_context_word);
|
|
*/
|
*/
|
|
printf(" P[%3d%c] = 0x%03x, V=0x%03x, C=0x%04x, CTXT=%04x",
|
|
m_last_tlb_index,
|
|
((m_core->v__DOT__mut__DOT__tlb_valid>>m_last_tlb_index)&1)?'V':'u',
|
|
m_core->v__DOT__mut__DOT__tlb_pdata[m_last_tlb_index],
|
|
m_core->v__DOT__mut__DOT__tlb_vdata[m_last_tlb_index],
|
|
m_core->v__DOT__mut__DOT__tlb_cdata[m_last_tlb_index],
|
|
m_core->v__DOT__mut__DOT__r_context_word);
|
printf("\n");
|
printf("\n");
|
}
|
}
|
}
|
}
|
|
|
void reset(void) {
|
void reset(void) {
|
m_core->i_rst = 1;
|
m_core->i_reset = 1;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_ctrl_cyc_stb = 0;
|
|
m_core->i_gie = 0;
|
|
m_core->i_exe = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_stb = 0;
|
m_core->i_wbm_stb = 0;
|
tick();
|
tick();
|
m_core->i_rst = 0;
|
m_core->i_reset = 0;
|
}
|
}
|
|
|
void wb_tick(void) {
|
void wb_tick(void) {
|
m_core->i_rst = 0;
|
m_core->i_reset = 0;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_stb = 0;
|
m_core->i_wbm_stb = 0;
|
tick();
|
tick();
|
assert(!m_core->o_rtn_ack);
|
assert(!m_core->o_rtn_ack);
|
assert(!m_core->o_rtn_err);
|
assert(!m_core->o_rtn_err);
|
}
|
}
|
|
|
unsigned operator[](unsigned a) {
|
unsigned operator[](unsigned a) {
|
a &= ((1<<LGMEMSIZE)-1);
|
unsigned msk = (1<<LGMEMSIZE)-1;
|
|
// printf("OP[] Reading from %08x\n", a);
|
|
assert((a&3)==0);
|
|
a = (a>>2)&(msk);
|
|
// printf("OP[] ----> %08x\n", a);
|
return m_core->v__DOT__ram__DOT__mem[a];
|
return m_core->v__DOT__ram__DOT__mem[a];
|
}
|
}
|
|
|
unsigned setup_read(unsigned a) {
|
unsigned setup_read(unsigned a) {
|
int errcount = 0;
|
int errcount = 0;
|
unsigned result;
|
unsigned result;
|
m_miss = false; m_err = false;
|
m_miss = false; m_err = false;
|
|
|
printf("WB-READS(%08x)\n", a);
|
printf("WB-READS(%08x)\n", a);
|
|
|
m_core->i_ctrl_cyc_stb = 1;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_stb = 0;
|
m_core->i_wbm_stb = 0;
|
m_core->i_wb_we = 0;
|
m_core->i_wb_we = 0;
|
m_core->i_wb_addr= a;
|
m_core->i_wb_addr= a>>2;
|
|
|
|
if (m_core->i_gie) {
|
|
m_core->i_gie = 0;
|
|
wb_tick();
|
|
}
|
|
|
|
m_core->i_ctrl_cyc_stb = 1;
|
|
|
if (m_core->o_rtn_stall) {
|
if (m_core->o_rtn_stall) {
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
|
tick();
|
tick();
|
} tick();
|
} tick();
|
Line 207... |
Line 258... |
int errcount = 0;
|
int errcount = 0;
|
m_miss = false; m_err = false;
|
m_miss = false; m_err = false;
|
|
|
printf("WB-WRITES(%08x,%08x)\n", a,v);
|
printf("WB-WRITES(%08x,%08x)\n", a,v);
|
|
|
m_core->i_ctrl_cyc_stb = 1;
|
m_core->i_ctrl_cyc_stb = 0;
|
|
m_core->i_exe = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_cyc = 0;
|
m_core->i_wbm_stb = 0;
|
m_core->i_wbm_stb = 0;
|
m_core->i_wb_we = 1;
|
m_core->i_wb_we = 1;
|
m_core->i_wb_addr= a;
|
m_core->i_wb_addr= a>>2;
|
m_core->i_wb_data= v;
|
m_core->i_wb_data= v;
|
|
m_core->i_wb_sel= 15;
|
|
|
|
if (m_core->i_gie) {
|
|
m_core->i_gie = 0;
|
|
wb_tick();
|
|
}
|
|
m_core->i_ctrl_cyc_stb = 1;
|
|
|
if (a & 0x080)
|
|
m_last_tlb_index = (a>>1)&0x3f;
|
if (a & 0x0200)
|
|
m_last_tlb_index = (a>>3)&0x3f;
|
|
|
if (m_core->o_rtn_stall) {
|
if (m_core->o_rtn_stall) {
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
|
tick();
|
tick();
|
} tick();
|
} tick();
|
Line 258... |
Line 318... |
|
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wb_we = 0;
|
m_core->i_wb_we = 0;
|
m_core->i_wb_addr= a;
|
m_core->i_wb_addr= a>>2;
|
|
|
if (m_core->o_rtn_stall) {
|
if (m_core->o_rtn_stall) {
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
|
tick();
|
tick();
|
if ((err)&&((m_core->o_rtn_err)||(m_core->o_rtn_miss))) {
|
if ((err)&&((m_core->o_rtn_err)||(m_core->o_rtn_miss))) {
|
Line 343... |
Line 403... |
|
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wb_we = 0;
|
m_core->i_wb_we = 0;
|
m_core->i_wb_addr = a;
|
m_core->i_wb_addr = a>>2;
|
|
|
rdidx =0; cnt = 0;
|
rdidx =0; cnt = 0;
|
inc = 1;
|
inc = 1;
|
|
|
do {
|
do {
|
Line 415... |
Line 475... |
printf("WB-WRITEM(%08x) <= %08x\n", a, v);
|
printf("WB-WRITEM(%08x) <= %08x\n", a, v);
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wb_we = 1;
|
m_core->i_wb_we = 1;
|
m_core->i_wb_addr= a;
|
m_core->i_wb_addr= a>>2;
|
m_core->i_wb_data= v;
|
m_core->i_wb_data= v;
|
|
m_core->i_wb_sel= 15;
|
|
|
if (m_core->o_rtn_stall)
|
if (m_core->o_rtn_stall)
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
|
printf("Stalled, so waiting, errcount=%d\n", errcount);
|
printf("Stalled, so waiting, errcount=%d\n", errcount);
|
tick();
|
tick();
|
Line 495... |
Line 556... |
printf("WB-WRITEM(%08x, %d, ...)\n", a, ln);
|
printf("WB-WRITEM(%08x, %d, ...)\n", a, ln);
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_ctrl_cyc_stb = 0;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_cyc = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wbm_stb = 1;
|
m_core->i_wb_we = 1;
|
m_core->i_wb_we = 1;
|
|
m_core->i_wb_sel= 15;
|
for(unsigned stbcnt=0; stbcnt<ln; stbcnt++) {
|
for(unsigned stbcnt=0; stbcnt<ln; stbcnt++) {
|
m_core->i_wb_addr= a+stbcnt;
|
m_core->i_wb_addr= (a>>2)+stbcnt;
|
m_core->i_wb_data= buf[stbcnt];
|
m_core->i_wb_data= buf[stbcnt];
|
errcount = 0;
|
errcount = 0;
|
|
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
|
while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
|
tick();
|
tick();
|
Line 590... |
Line 652... |
|
|
void install_page(ZIPMMU_TB *tb, int idx, unsigned va, unsigned pa, int flags) {
|
void install_page(ZIPMMU_TB *tb, int idx, unsigned va, unsigned pa, int flags) {
|
int LGTBL, LGPGSZ, LGCTXT;
|
int LGTBL, LGPGSZ, LGCTXT;
|
int c;
|
int c;
|
unsigned base;
|
unsigned base;
|
bool hdebug = tb->debug();
|
// bool hdebug = tb->debug();
|
|
|
tb->debug(false);
|
// tb->debug(false);
|
c=tb->setup_read(0);
|
c=tb->setup_read(R_CONTROL);
|
printf("CONTEXT-REG = %08x\n", c);
|
printf("CONTEXT-REG = %08x\n", c);
|
LGTBL = ((c>>24)&15);
|
LGTBL = ((c>>24)&15);
|
LGPGSZ= (((c>>20)&15)+8)&31;
|
LGPGSZ= (((c>>20)&15)+10)&31; // In bytes
|
LGCTXT= (((c>>16)&15)+1)&31;
|
LGCTXT= (((c>>16)&15)+1)&31;
|
c &= ((1<<LGCTXT)-1);
|
c &= ((1<<LGCTXT)-1);
|
base = (2<<LGTBL)+(idx<<1);
|
base = R_ENTRYSZ(LGTBL, idx);
|
va &= -(1<<LGPGSZ);
|
va &= -(1<<LGPGSZ);
|
pa &= -(1<<LGPGSZ);
|
pa &= -(1<<LGPGSZ);
|
|
|
printf("INSTALL[%2d] %04x:%08xV -> %08xP %s%s\n",
|
printf("INSTALL[%2d] %04x:%03x[%04x]%xV -> %03x[%04x]%xP %s%s\n",
|
idx, c, va, pa,
|
idx, c,
|
|
(va>>LGPGSZ), LOCONTEXT(c)>>4, flags,
|
|
(pa>>LGPGSZ), HICONTEXT(c)>>4, 0,
|
(flags&MMUFLAG_RONW)?"RO":" ",
|
(flags&MMUFLAG_RONW)?"RO":" ",
|
(flags&MMUFLAG_CCHE)?"Cachable":"");
|
(flags&MMUFLAG_CCHE)?"Cachable":"");
|
tb->setup_write(base , va|(( c &0x0ff)<<4)|flags);
|
tb->setup_write(base , va|(LOCONTEXT(c))|flags);
|
tb->setup_write(base+1, pa|(((c>>8)&0x0ff)<<4)|flags);
|
tb->setup_write(base+4, pa|(HICONTEXT(c)));
|
tb->debug(hdebug);
|
// tb->debug(hdebug);
|
|
tb->tick();
|
|
tb->m_core->i_gie = 1;
|
}
|
}
|
|
|
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
Verilated::commandArgs(argc, argv);
|
Verilated::commandArgs(argc, argv);
|
ZIPMMU_TB *tb = new ZIPMMU_TB;
|
ZIPMMU_TB *tb = new ZIPMMU_TB;
|
unsigned *rdbuf; // *mbuf;
|
unsigned *rdbuf; // *mbuf;
|
unsigned mlen = (1<<LGMEMSIZE), c, blen;
|
unsigned mlen = (1<<LGMEMSIZE), c, blen;
|
|
const unsigned CONTEXT = 0x0fef7;
|
|
|
tb->opentrace("zipmmu_tb.vcd");
|
tb->opentrace("zipmmu_tb.vcd");
|
printf("Giving the core 2 cycles to start up\n");
|
printf("Giving the core 2 cycles to start up\n");
|
// Before testing, let's give the unit time enough to warm up
|
// Before testing, let's give the unit time enough to warm up
|
tb->reset();
|
tb->reset();
|
Line 634... |
Line 701... |
// mbuf = new unsigned[mlen]; // Match buffer
|
// mbuf = new unsigned[mlen]; // Match buffer
|
printf("Charging my memory with random values\n");
|
printf("Charging my memory with random values\n");
|
uload(mlen, rdbuf);
|
uload(mlen, rdbuf);
|
|
|
|
|
int LGADR, LGTBL, LGPGSZ, LGCTXT, sr;
|
int LGADR, LGTBL, LGPGSZ, LGCTXT, sr, PAGESZ;
|
|
|
c=tb->setup_read(0);
|
c=tb->setup_read(R_CONTROL);
|
printf("CONTROL-REG = %08x\n = %2d\n", c, c);
|
printf("CONTROL-REG = %08x\n = %2d\n", c, c);
|
sr = tb->setup_read(1);
|
sr = tb->setup_read(R_STATUS);
|
printf("STATUS-REG = %08x = %2d\n", sr, sr);
|
printf("STATUS-REG = %08x = %2d\n", sr, sr);
|
LGADR = (((c>>28)&15)+17)&31;
|
LGADR = (((c>>28)&15)+17)&31;
|
LGTBL = ((c>>24)&15);
|
LGTBL = ((c>>24)&15);
|
LGPGSZ= (((c>>20)&15)+8)&31;
|
LGPGSZ= (((c>>20)&15)+10)&31;
|
|
PAGESZ= 1ul<<LGPGSZ;
|
LGCTXT= (((c>>16)&15)+1)&31;
|
LGCTXT= (((c>>16)&15)+1)&31;
|
printf("LGADR = %08x = %2d\n", LGADR, LGADR);
|
printf("LGADR = %08x = %2d\n", LGADR, LGADR);
|
printf("LGTBL = %08x = %2d\n", LGTBL, LGTBL);
|
printf("LGTBL = %08x = %2d\n", LGTBL, LGTBL);
|
printf("LGPGSZ = %08x = %2d\n", LGPGSZ, LGPGSZ);
|
printf("LGPGSZ = %08x = %2d\n", LGPGSZ, LGPGSZ);
|
printf("LGCTXT = %08x = %2d\n", LGCTXT, LGCTXT);
|
printf("LGCTXT = %08x = %2d\n", LGCTXT, LGCTXT);
|
|
printf("PAGESZ = %08x = %2d\n", PAGESZ, PAGESZ);
|
|
|
// First, let's make sure we can read/write the context
|
// First, let's make sure we can read/write the context
|
printf("\n\nTest: Can we read/write the context register?\n");
|
printf("\n\nTest: Can we read/write the context register?\n");
|
tb->setup_write(0,0x01fec);
|
tb->setup_write(R_CONTROL,CONTEXT);
|
c=tb->setup_read(0);
|
c=tb->setup_read(R_CONTROL);
|
printf("CONTEXT = %08x (0x1fec?)\n", c&0x0ffff);
|
printf("CONTEXT = %04x (0x%04x)\n", c &0x0ffff, CONTEXT & 0x0ffff);
|
if ((c&0x0ffff) != 0x01fec)
|
if ((c&0x0ffff) != CONTEXT)
|
goto test_failure;
|
goto test_failure;
|
|
|
// Load the table with TLB misses
|
// Load the table with TLB misses
|
printf("\n\nTest: Can we load the table with TLB misses? (%d entries)\n", (1<<LGTBL));
|
printf("\n\nTest: Can we load the table with TLB misses? (%d entries)\n", (1<<LGTBL));
|
for(int i=0; i<(1<<LGTBL); i++) {
|
for(int i=0; i<(1<<LGTBL); i++) {
|
c = 0x0f70; // Context: 0xfef7
|
c = CONTEXT; // Context: 0xfef7, no flags
|
tb->setup_write((2<<LGTBL)+(i<<1) , c+(((1<<LGTBL)-1-i)<<LGPGSZ));
|
tb->setup_write(R_VENTRY(i), (LOCONTEXT(c))
|
c = 0x0fe2; // CCHE flag only
|
|(((1<<LGTBL)-1-i)<<LGPGSZ) | ROFLAG);
|
tb->setup_write((2<<LGTBL)+(i<<1)+1, c+(((1<<LGTBL)-1-i)<<LGPGSZ));
|
tb->setup_write(R_PENTRY(i), (HICONTEXT(c))
|
|
|(((1<<LGTBL)-1-i)<<LGPGSZ));
|
}
|
}
|
|
|
// Dump the table, make sure we got it right
|
// Dump the table, make sure we got it right
|
for(int i=0; i<(1<<LGTBL); i++) {
|
for(int i=0; i<(1<<LGTBL); i++) {
|
unsigned v, p;
|
unsigned v, p, c;
|
v=tb->setup_read((2<<LGTBL)+(i<<1) );
|
|
p=tb->setup_read((2<<LGTBL)+(i<<1)+1);
|
c = 0x0fef7;
|
|
v=tb->setup_read(R_VENTRY(i));
|
|
p=tb->setup_read(R_PENTRY(i));
|
|
|
printf("TBL[%2d] = %08x -> %08x\n", i, v, p);
|
printf("TBL[%2d] = %08x -> %08x", i, v, p);
|
if (v != (unsigned)(0x00f72+(((1<<LGTBL)-1-i)<<LGPGSZ)))
|
printf("\tEXPECTING %08x -> %08x\n",
|
|
(unsigned)((LOCONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ)|ROFLAG),
|
|
(unsigned)(HICONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ));
|
|
if (v != (unsigned)((LOCONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ)|ROFLAG))
|
goto test_failure;
|
goto test_failure;
|
if (p != (unsigned)(0x00fe2+(((1<<LGTBL)-1-i)<<LGPGSZ)))
|
if (p != (unsigned)((HICONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ)))
|
goto test_failure;
|
goto test_failure;
|
}
|
} printf("-- PASS\n\n");
|
|
|
// Now, let's create a fictitious process, context 1, with no pages.
|
// Now, let's create a fictitious process, context 1, with no pages.
|
// See what happens when we try to access his stack at 0xffffffff
|
// See what happens when we try to access his stack at 0xffffffff
|
bool tberr;
|
bool tberr;
|
printf("\n\nTest: Do we get a TLB miss when attempting to find a non-existent page?\n");
|
printf("\n\nTest: Do we get a TLB miss when attempting to find a non-existent page?\n");
|
|
tb->m_core->i_gie = 1;
|
|
tb->tick();
|
tberr = false;
|
tberr = false;
|
tb->wb_write(0xffffffff, 0x0fe, &tberr);
|
tb->wb_write(0xfffffffc, 0x0fe, &tberr);
|
if ((!tberr)||(!tb->miss())||(tb->err())) {
|
if ((!tberr)||(!tb->miss())||(tb->err())) {
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
goto test_failure;
|
goto test_failure;
|
}
|
} printf("-- PASS\n\n");
|
|
|
tberr = false;
|
tberr = false;
|
install_page(tb, 0, 0x0ffffffff, (1<<LGMEMSIZE)+0*(1<<LGPGSZ),
|
install_page(tb, 0, 0xfffffffc, (4<<LGMEMSIZE)+0*PAGESZ,
|
MMUFLAG_RONW);
|
MMUFLAG_RONW);
|
printf("\n\nTest: Do we get a TLB miss when attempting to write a RO page?\n");
|
printf("\n\nTest: Do we get a TLB miss when attempting to write a RO page?\n");
|
tb->wb_write(0xffffffff, 0x0fe, &tberr);
|
tb->wb_write(0xffffffff, 0x0fe, &tberr);
|
if ((!tberr)||(!tb->miss())||(tb->err())) {
|
if ((!tberr)||(!tb->miss())||(tb->err())) {
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
goto test_failure;
|
goto test_failure;
|
}
|
} printf("-- PASS\n\n");
|
|
|
tberr = false;
|
tberr = false;
|
printf("\n\nTest: What if we make this into a writeable page?\n");
|
printf("\n\nTest: What if we make this into a writeable page?\n");
|
install_page(tb, 0, 0xffffffff, (1<<LGMEMSIZE)+0*(1<<LGPGSZ), 0);
|
install_page(tb, 0, 0xfffffffc, (4<<LGMEMSIZE)+0*PAGESZ, 0);
|
tb->wb_write(0xffffffff, 0x0fe, &tberr);
|
tb->m_core->i_gie = 1;
|
|
tb->m_core->i_exe = 0;
|
|
tb->wb_write(0xfffffff8, 0x0fe, &tberr);
|
if (tberr) {
|
if (tberr) {
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
goto test_failure;
|
goto test_failure;
|
}
|
} printf("-- PASS\n\n");
|
printf("\n\nTest: Is the next access done w/in a single clock?\n");
|
printf("\n\nTest: Is the next access done w/in a single clock?\n");
|
tb->wb_write(0xfffffff7, 0xdeadbeef, &tberr);
|
tb->wb_write(0xfffffffc, 0xdeadbeef, &tberr);
|
if (tberr) {
|
if (tberr) {
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
goto test_failure;
|
goto test_failure;
|
}
|
} printf("-- PASS\n\n");
|
|
|
|
|
tberr = false;
|
tberr = false;
|
printf("\n\nTest: What if we make this into a writeable page?\n");
|
printf("\n\nTest: What if we make this into a writeable page?\n");
|
install_page(tb, 0, 0xffffffff, (1<<LGMEMSIZE)+0*(1<<LGPGSZ), 0);
|
install_page(tb, 0, 0xffffffff, (4<<LGMEMSIZE)+0*PAGESZ, 0);
|
tb->wb_write(0xffffffff, 0x0fe, &tberr);
|
tb->wb_write(0xfffffffc, 0x0fe, &tberr);
|
if ((tberr)||((*tb)[0x0fff]!=0x0fe)) {
|
if ((tberr)||((*tb)[0x0ffc]!=0x0fe)) {
|
unsigned v;
|
unsigned v;
|
v = ((*tb)[0x0fff]!=0x0fe);
|
v = ((*tb)[0x0ffc]!=0x0fe);
|
printf("V = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("V = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS = %s\nERR = %s\n",
|
v, (tberr)?"true":"false", (tb->miss())?"true":"false",
|
v, (tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
goto test_failure;
|
goto test_failure;
|
}
|
} printf("-- PASS\n\n");
|
|
|
tberr = false;
|
tberr = false;
|
printf("\n\nTest: How about a read from the same location?\n");
|
printf("\n\nTest: How about a read from the same location?\n");
|
{
|
{
|
unsigned v;
|
unsigned v;
|
v = tb->wb_read(0xffffffff, &tberr);
|
v = tb->wb_read(0xfffffffc, &tberr);
|
if ((tberr)||(v != 0x0fe)) {
|
if ((tberr)||(v != 0x0fe)) {
|
printf("V = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("V = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS = %s\nERR = %s\n",
|
v,
|
v,
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
goto test_failure;
|
goto test_failure;
|
}
|
}
|
}
|
} printf("-- PASS\n\n");
|
|
|
printf("Test: Burst write, within page\n");
|
printf("Test: Burst write, within page (PAGESZ = %04x)\n", PAGESZ);
|
tb->setup_write(0, 0x0dad);
|
tb->setup_write(R_CONTROL, 0x0dad);
|
install_page(tb, 0, ((0x0ffffffffl)&(-(1l<<LGPGSZ)))-2*(1<<LGPGSZ), (1<<LGMEMSIZE)+0*(1<<LGPGSZ), 0);
|
#define TEST_VPAGE ((0x0ffffffffl)&(-(1l<<LGPGSZ)))
|
install_page(tb, 1, ((0x0ffffffffl)&(-(1l<<LGPGSZ)))-1*(1<<LGPGSZ), (1<<LGMEMSIZE)+1*(1<<LGPGSZ), 0);
|
install_page(tb, 0, TEST_VPAGE-2*PAGESZ, (4<<LGMEMSIZE)+0*PAGESZ, 0);
|
install_page(tb, 2, ((0x0ffffffffl)&(-(1l<<LGPGSZ)))+0*(1<<LGPGSZ), (1<<LGMEMSIZE)+2*(1<<LGPGSZ), 0);
|
install_page(tb, 1, TEST_VPAGE-1*PAGESZ, (4<<LGMEMSIZE)+1*PAGESZ, 0);
|
|
install_page(tb, 2, TEST_VPAGE-0*PAGESZ, (4<<LGMEMSIZE)+2*PAGESZ, 0);
|
|
|
tberr = false;
|
tberr = false;
|
blen = (1<<(LGPGSZ-2));
|
blen = (1<<(LGPGSZ-2));
|
tb->wb_write(((0xffffffff)&(-(1l<<LGPGSZ)))-2*(1<<LGPGSZ), blen, rdbuf, &tberr);
|
tb->wb_write(TEST_VPAGE-2*(1<<LGPGSZ), blen, rdbuf, &tberr);
|
if (tberr) {
|
if (tberr) {
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
printf("STATUS= %08x\n", tb->setup_read(1));
|
printf("STATUS= %08x\n", tb->setup_read(R_STATUS));
|
goto test_failure;
|
goto test_failure;
|
} for(unsigned i=0; i<blen; i++) {
|
} for(unsigned i=0; i<blen; i++) {
|
if ((*tb)[i] != rdbuf[i]) {
|
if ((*tb)[i*4] != rdbuf[i]) {
|
printf("MEM[%04x] = %08x (!= %08x as expected)\n",
|
printf("MEM[%04x] = %08x (!= %08x as expected)\n",
|
i, (*tb)[i], rdbuf[i]);
|
i, (*tb)[4*i], rdbuf[i]);
|
goto test_failure;
|
goto test_failure;
|
}
|
}
|
}
|
} printf("-- PASS\n\n");
|
|
|
printf("Test: Burst read\n");
|
printf("Test: Burst read\n");
|
// Try somewhere within that last page
|
// Try somewhere within that last page
|
tberr = false;
|
tberr = false;
|
tb->wb_read(((0xffffffff)&(-(1<<LGPGSZ)))-2*(1<<LGPGSZ)+18, blen, rdbuf, &tberr);
|
tb->wb_read(TEST_VPAGE-2*(1<<LGPGSZ)+(18*4), blen, rdbuf, &tberr);
|
if (tberr) {
|
if (tberr) {
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
printf("TBERR = %s\nMISS = %s\nERR = %s\n",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tberr)?"true":"false", (tb->miss())?"true":"false",
|
(tb->err())?"true":"false");
|
(tb->err())?"true":"false");
|
printf("STATUS= %08x\n", tb->setup_read(1));
|
printf("STATUS= %08x\n", tb->setup_read(R_STATUS));
|
goto test_failure;
|
goto test_failure;
|
} for(unsigned i=0; i<blen; i++) {
|
} for(unsigned i=0; i<blen; i++) {
|
if ((*tb)[i+18] != rdbuf[i]) {
|
if ((*tb)[(i+18)*4] != rdbuf[i]) {
|
printf("MEM[%04x] = %08x (!= %08x as expected)\n",
|
printf("MEM[%04x] = %08x (!= %08x as expected)\n",
|
i+18, (*tb)[i+18], rdbuf[i]);
|
i+18, (*tb)[i+18], rdbuf[i]);
|
goto test_failure;
|
goto test_failure;
|
}
|
}
|
}
|
} printf("-- PASS\n\n");
|
|
|
|
|
printf("Tests not (yet) implemented\n");
|
printf("Tests not (yet) implemented\n");
|
printf("Test: Burst read crossing pages, second page valid\n");
|
printf("Test: Burst read crossing pages, second page valid\n");
|
printf("Test: Burst read crossing pages, second page invalid\n");
|
printf("Test: Burst read crossing pages, second page invalid\n");
|