E203 CSR rtl实现分析
CSR状态控制寄存器,每个hart都有自己的CSR。对于每个hart,可以配置的状态寄存器是4k。CSR寄存器的功能见:https://www.cnblogs.com/mikewolf2002/p/11314583.html
CSR实现的rtl代码是e203_exu_csr.v,下面我们分析一下代码实现:
输出输入信号如下:
module e203_exu_csr( input csr_ena, //csr readwrite enable signal from alu,csr读写使能信号,
input csr_wr_en, //csr write enable,csr写使能信号
input csr_rd_en, //csr read enable,csr读使能信号
input [11:0] csr_idx,//csr address index,csr地址索引 output tm_stop, //time stop, counterstop[1],输出time counter是否停止
output core_cgstop,//not is used by isa, 0xbfe, self-defined, core clock gating,核心clock gating设置
output tcm_cgstop,//not is used by isa, 0xbfe, Stop TCM clock gating, tight coupled memory,tcm 访问clock gating
output itcm_nohold, //not is used by isa,itcm是否hold上一次的读数据
output mdv_nob2b, //not is used by isa,是否是两个临接的乘除指令 output [`E203_XLEN-1:0] read_csr_dat,//read return data from csr,从csr读取的数据
input [`E203_XLEN-1:0] wbck_csr_dat,//data write back to csr,写数据到csr input [`E203_HART_ID_W-1:0] core_mhartid, //point mhartid, if read mhartid register, return this value,e203只有一个核,所以为0
//mip register
input ext_irq_r,//external interrupt,是否是外部中断请求
input sft_irq_r,//software interrupt 是否是软件中断请求
input tmr_irq_r,//time interrupt, 是否是计时器中断请求 output status_mie_r,//输出状态寄存器的mie值,表示是否使能全局中断
//interrupt enble value for mie
output mtie_r, //机器模式定时器中断是否屏蔽, mie.mtie位
output msie_r, //机器方式软件中断是否屏蔽,
output meie_r, //机器模式外部中断是否屏蔽, mie.meie位//0x7b0 Debug Control and Status //0x7b1 Debug PC //0x7b2 Debug Scratch Register //0x7a0 Trigger selection register output wr_dcsr_ena , //debug 模式下,写csr 使能
output wr_dpc_ena , //debug模式下,pc写使能
output wr_dscratch_ena, //debug模式下,scratch写使能 input [`E203_XLEN-1:0] dcsr_r , //输入dcsr值
input [`E203_PC_SIZE-1:0] dpc_r , //输入dpc值
input [`E203_XLEN-1:0] dscratch_r, //输入dscratch值 output [`E203_XLEN-1:0] wr_csr_nxt , //=wbck_csr_dat; input dbg_mode, //debug模式
input dbg_stopcycle, //如果在debug模式,且置位这个信号,则停止perf counter计数 output u_mode, //输出当前的模式,如果为那个模式,则这个信号置1
output s_mode,
output h_mode,
output m_mode, input [`E203_ADDR_SIZE-1:0] cmt_badaddr, //输入异常指令或者异常访存地址到mtval/mbadaddr
input cmt_badaddr_ena, //badaddr 使能信号
input [`E203_PC_SIZE-1:0] cmt_epc, //异常返回地址
input cmt_epc_ena, //epc使能信号
input [`E203_XLEN-1:0] cmt_cause, //异常原因输入
input cmt_cause_ena, //cause使能
input cmt_status_ena, //status使能
input cmt_instret_ena, //instret使能 input cmt_mret_ena, //mret使能
output[`E203_PC_SIZE-1:0] csr_epc_r, //输出epc值,异常地址
output[`E203_PC_SIZE-1:0] csr_dpc_r, //输出dpc,debug模式的pc值
output[`E203_XLEN-1:0] csr_mtvec_r, //输出异常模式基地址 input clk_aon, //常开时钟信号,不会受clock gating影响
input clk, //时钟信号
input rst_n //复位信号 );
E203仅支持机器模式,所以priv_mode=2’b11。接着实现mstatus的rtl代码
wire wbck_csr_wen = csr_wr_en & csr_ena ;
wire read_csr_ena = csr_rd_en & csr_ena ; wire [1:0] priv_mode = u_mode ? 2'b00 :
s_mode ? 2'b01 :
h_mode ? 2'b10 :
m_mode ? 2'b11 :
2'b11; //0x000 URW ustatus User status register.
// * Since we support the user-level interrupt, hence we need to support UIE
//0x300 MRW mstatus Machine status register.
wire sel_ustatus = (csr_idx == 12'h000);
wire sel_mstatus = (csr_idx == 12'h300); wire rd_ustatus = sel_ustatus & csr_rd_en;
wire rd_mstatus = sel_mstatus & csr_rd_en;
wire wr_ustatus = sel_ustatus & csr_wr_en;
wire wr_mstatus = sel_mstatus & csr_wr_en; /////////////////////////////////////////////////////////////////////
// Note: the below implementation only apply to Machine-mode config,
// if other mode is also supported, these logics need to be updated //////////////////////////
// Implement MPIE field
//
wire status_mpie_r;
// The MPIE Feilds will be updates when: //在中断发生或者中断完成,返回时候,或者直接写该寄存器时候,使能该寄存器
wire status_mpie_ena =
// The CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) |
// The MRET instruction commited
cmt_mret_ena |
// The Trap is taken
cmt_status_ena; wire status_mpie_nxt =
// See Priv SPEC:
// When a trap is taken from privilege mode y into privilege
// mode x, xPIE is set to the value of xIE;
// So, When the Trap is taken, the MPIE is updated with the current MIE value
cmt_status_ena ? status_mie_r : //进入中断的时候,保存mie的值。
// See Priv SPEC:
// When executing an xRET instruction, supposing xPP holds the value y, xIE
// is set to xPIE; the privilege mode is changed to y;
// xPIE is set to 1;
// So, When the MRET instruction commited, the MPIE is updated with 1
cmt_mret_ena ? 1'b1 : //从中断返回时候更新为0
// When the CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) ? wbck_csr_dat[7] : // MPIE is in field 7 of mstatus
status_mpie_r; // Unchanged sirv_gnrl_dfflr #(1) status_mpie_dfflr (status_mpie_ena, status_mpie_nxt, status_mpie_r, clk, rst_n); //////////////////////////
// Implement MIE field
//
// The MIE Feilds will be updates same as MPIE
wire status_mie_ena = status_mpie_ena;
wire status_mie_nxt =
// See Priv SPEC:
// When a trap is taken from privilege mode y into privilege
// mode x, xPIE is set to the value of xIE,
// xIE is set to 0;
// So, When the Trap is taken, the MIE is updated with 0
cmt_status_ena ? 1'b0 : //进入中断时候,关闭中断
// See Priv SPEC:
// When executing an xRET instruction, supposing xPP holds the value y, xIE
// is set to xPIE; the privilege mode is changed to y, xPIE is set to 1;
// So, When the MRET instruction commited, the MIE is updated with MPIE
cmt_mret_ena ? status_mpie_r : //从中断返回时候,恢复保存在mpie中的值。
// When the CSR is written by CSR instructions
(wr_mstatus & wbck_csr_wen) ? wbck_csr_dat[3] : // MIE is in field 3 of mstatus
status_mie_r; // Unchanged sirv_gnrl_dfflr #(1) status_mie_dfflr (status_mie_ena, status_mie_nxt, status_mie_r, clk, rst_n); //////////////////////////
// Implement SD field
//
// See Priv SPEC:
// The SD bit is read-only
// And is set when either the FS or XS bits encode a Dirty
// state (i.e., SD=((FS==11) OR (XS==11))).//因为没有浮点单元和协处理器,fs,xs域都为0
wire [1:0] status_fs_r;
wire [1:0] status_xs_r;
wire status_sd_r = (status_fs_r == 2'b11) | (status_xs_r == 2'b11); //////////////////////////
// Implement XS field
//
// See Priv SPEC:
// XS field is read-only
// The XS field represents a summary of all extensions' status
// But in E200 we implement XS exactly same as FS to make it usable by software to
// disable extended accelerators
// If no EAI coprocessor interface configured, the XS is just hardwired to 0
assign status_xs_r = 2'b0; //////////////////////////
// Implement FS field
// `ifndef E203_HAS_FPU
// If no FPU configured, the FS is just hardwired to 0
assign status_fs_r = 2'b0;
`endif //////////////////////////
// Pack to the full mstatus register
//
wire [`E203_XLEN-1:0] status_r;
assign status_r[31] = status_sd_r; //SD
assign status_r[30:23] = 8'b0; // Reserved
assign status_r[22:17] = 6'b0; // TSR--MPRV
assign status_r[16:15] = status_xs_r; // XS
assign status_r[14:13] = status_fs_r; // FS
assign status_r[12:11] = 2'b11; // MPP
assign status_r[10:9] = 2'b0; // Reserved
assign status_r[8] = 1'b0; // SPP
assign status_r[7] = status_mpie_r; // MPIE
assign status_r[6] = 1'b0; // Reserved
assign status_r[5] = 1'b0; // SPIE
assign status_r[4] = 1'b0; // UPIE
assign status_r[3] = status_mie_r; // MIE
assign status_r[2] = 1'b0; // Reserved
assign status_r[1] = 1'b0; // SIE
assign status_r[0] = 1'b0; // UIE wire [`E203_XLEN-1:0] csr_mstatus = status_r;
mie/mip rtl实现
//0x004 URW uie User interrupt-enable register.
// * Since we dont delegate interrupt to user mode, hence it is as all 0s
//0x304 MRW mie Machine interrupt-enable register.
wire sel_mie = (csr_idx == 12'h304);
wire rd_mie = sel_mie & csr_rd_en;
wire wr_mie = sel_mie & csr_wr_en;
wire mie_ena = wr_mie & wbck_csr_wen;
wire [`E203_XLEN-1:0] mie_r;
wire [`E203_XLEN-1:0] mie_nxt;
assign mie_nxt[31:12] = 20'b0;
assign mie_nxt[11] = wbck_csr_dat[11];//MEIE
assign mie_nxt[10:8] = 3'b0;
assign mie_nxt[ 7] = wbck_csr_dat[ 7];//MTIE
assign mie_nxt[6:4] = 3'b0;
assign mie_nxt[ 3] = wbck_csr_dat[ 3];//MSIE
assign mie_nxt[2:0] = 3'b0;
sirv_gnrl_dfflr #(`E203_XLEN) mie_dfflr (mie_ena, mie_nxt, mie_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mie = mie_r; assign meie_r = csr_mie[11];
assign mtie_r = csr_mie[ 7];
assign msie_r = csr_mie[ 3]; //0x044 URW uip User interrupt pending.
// We dont support delegation scheme, so no need to support the uip
//0x344 MRW mip Machine interrupt pending
wire sel_mip = (csr_idx == 12'h344);
wire rd_mip = sel_mip & csr_rd_en;
//wire wr_mip = sel_mip & csr_wr_en;
// The MxIP is read-only
wire meip_r;
wire msip_r;
wire mtip_r;
sirv_gnrl_dffr #(1) meip_dffr (ext_irq_r, meip_r, clk, rst_n);
sirv_gnrl_dffr #(1) msip_dffr (sft_irq_r, msip_r, clk, rst_n);
sirv_gnrl_dffr #(1) mtip_dffr (tmr_irq_r, mtip_r, clk, rst_n); wire [`E203_XLEN-1:0] ip_r;
assign ip_r[31:12] = 20'b0;
assign ip_r[11] = meip_r;
assign ip_r[10:8] = 3'b0;
assign ip_r[ 7] = mtip_r;
assign ip_r[6:4] = 3'b0;
assign ip_r[ 3] = msip_r;
assign ip_r[2:0] = 3'b0;
wire [`E203_XLEN-1:0] csr_mip = ip_r;
mtvec和mscratch rtl实现
//0x005 URW utvec User trap handler base address.
// We dont support user trap, so no utvec needed
//0x305 MRW mtvec Machine trap-handler base address.
wire sel_mtvec = (csr_idx == 12'h305);
wire rd_mtvec = csr_rd_en & sel_mtvec;
`ifdef E203_SUPPORT_MTVEC //{
wire wr_mtvec = sel_mtvec & csr_wr_en;
wire mtvec_ena = (wr_mtvec & wbck_csr_wen);
wire [`E203_XLEN-1:0] mtvec_r;
wire [`E203_XLEN-1:0] mtvec_nxt = wbck_csr_dat;
sirv_gnrl_dfflr #(`E203_XLEN) mtvec_dfflr (mtvec_ena, mtvec_nxt, mtvec_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mtvec = mtvec_r;
`else//}{
// THe vector table base is a configurable parameter, so we dont support writeable to it
wire [`E203_XLEN-1:0] csr_mtvec = `E203_MTVEC_TRAP_BASE;
`endif//}
assign csr_mtvec_r = csr_mtvec; //0x340 MRW mscratch
wire sel_mscratch = (csr_idx == 12'h340);
wire rd_mscratch = sel_mscratch & csr_rd_en;
`ifdef E203_SUPPORT_MSCRATCH //{
wire wr_mscratch = sel_mscratch & csr_wr_en;
wire mscratch_ena = (wr_mscratch & wbck_csr_wen);
wire [`E203_XLEN-1:0] mscratch_r;
wire [`E203_XLEN-1:0] mscratch_nxt = wbck_csr_dat;
sirv_gnrl_dfflr #(`E203_XLEN) mscratch_dfflr (mscratch_ena, mscratch_nxt, mscratch_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mscratch = mscratch_r;
`else//}{
wire [`E203_XLEN-1:0] csr_mscratch = `E203_XLEN'b0;
`endif//}
mcycle/mcycleh/minstret/minstreth/counterstop/cgstop/itcmnohold/mdvnob2b等的rtl实现。
// 0xB00 MRW mcycle
// 0xB02 MRW minstret
// 0xB80 MRW mcycleh
// 0xB82 MRW minstreth
wire sel_mcycle = (csr_idx == 12'hB00);
wire sel_mcycleh = (csr_idx == 12'hB80);
wire sel_minstret = (csr_idx == 12'hB02);
wire sel_minstreth = (csr_idx == 12'hB82); // 0xBFF MRW counterstop
// This register is our self-defined register to stop
// the cycle/time/instret counters to save dynamic powers
wire sel_counterstop = (csr_idx == 12'hBFF);// This address is not used by ISA
// 0xBFE MRW mcgstop
// This register is our self-defined register to disable the
// automaticall clock gating for CPU logics for debugging purpose
wire sel_mcgstop = (csr_idx == 12'hBFE);// This address is not used by ISA
// 0xBFD MRW itcmnohold
// This register is our self-defined register to disble the
// ITCM SRAM output holdup feature, if set, then we assume
// ITCM SRAM output cannot holdup last read value
wire sel_itcmnohold = (csr_idx == 12'hBFD);// This address is not used by ISA
// 0xBF0 MRW mdvnob2b
// This register is our self-defined register to disble the
// Mul/div back2back feature
wire sel_mdvnob2b = (csr_idx == 12'hBF0);// This address is not used by ISA wire rd_mcycle = csr_rd_en & sel_mcycle ;
wire rd_mcycleh = csr_rd_en & sel_mcycleh ;
wire rd_minstret = csr_rd_en & sel_minstret ;
wire rd_minstreth = csr_rd_en & sel_minstreth; wire rd_itcmnohold = csr_rd_en & sel_itcmnohold;
wire rd_mdvnob2b = csr_rd_en & sel_mdvnob2b;
wire rd_counterstop = csr_rd_en & sel_counterstop;
wire rd_mcgstop = csr_rd_en & sel_mcgstop; `ifdef E203_SUPPORT_MCYCLE_MINSTRET //{
wire wr_mcycle = csr_wr_en & sel_mcycle ;
wire wr_mcycleh = csr_wr_en & sel_mcycleh ;
wire wr_minstret = csr_wr_en & sel_minstret ;
wire wr_minstreth = csr_wr_en & sel_minstreth; wire wr_itcmnohold = csr_wr_en & sel_itcmnohold ;
wire wr_mdvnob2b = csr_wr_en & sel_mdvnob2b ;
wire wr_counterstop = csr_wr_en & sel_counterstop;
wire wr_mcgstop = csr_wr_en & sel_mcgstop ; wire mcycle_wr_ena = (wr_mcycle & wbck_csr_wen);
wire mcycleh_wr_ena = (wr_mcycleh & wbck_csr_wen);
wire minstret_wr_ena = (wr_minstret & wbck_csr_wen);
wire minstreth_wr_ena = (wr_minstreth & wbck_csr_wen); wire itcmnohold_wr_ena = (wr_itcmnohold & wbck_csr_wen);
wire mdvnob2b_wr_ena = (wr_mdvnob2b & wbck_csr_wen);
wire counterstop_wr_ena = (wr_counterstop & wbck_csr_wen);
wire mcgstop_wr_ena = (wr_mcgstop & wbck_csr_wen); wire [`E203_XLEN-1:0] mcycle_r ;
wire [`E203_XLEN-1:0] mcycleh_r ;
wire [`E203_XLEN-1:0] minstret_r ;
wire [`E203_XLEN-1:0] minstreth_r; wire cy_stop;
wire ir_stop; wire stop_cycle_in_dbg = dbg_stopcycle & dbg_mode;
wire mcycle_ena = mcycle_wr_ena |
((~cy_stop) & (~stop_cycle_in_dbg) & (1'b1));
wire mcycleh_ena = mcycleh_wr_ena |
((~cy_stop) & (~stop_cycle_in_dbg) & ((mcycle_r == (~(`E203_XLEN'b0)))));
wire minstret_ena = minstret_wr_ena |
((~ir_stop) & (~stop_cycle_in_dbg) & (cmt_instret_ena));
wire minstreth_ena = minstreth_wr_ena |
((~ir_stop) & (~stop_cycle_in_dbg) & ((cmt_instret_ena & (minstret_r == (~(`E203_XLEN'b0))))));
//auto increment
wire [`E203_XLEN-1:0] mcycle_nxt = mcycle_wr_ena ? wbck_csr_dat : (mcycle_r + 1'b1);
wire [`E203_XLEN-1:0] mcycleh_nxt = mcycleh_wr_ena ? wbck_csr_dat : (mcycleh_r + 1'b1);
wire [`E203_XLEN-1:0] minstret_nxt = minstret_wr_ena ? wbck_csr_dat : (minstret_r + 1'b1);
wire [`E203_XLEN-1:0] minstreth_nxt = minstreth_wr_ena ? wbck_csr_dat : (minstreth_r + 1'b1); //We need to use the always-on clock for this counter
sirv_gnrl_dfflr #(`E203_XLEN) mcycle_dfflr (mcycle_ena, mcycle_nxt, mcycle_r , clk_aon, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) mcycleh_dfflr (mcycleh_ena, mcycleh_nxt, mcycleh_r , clk_aon, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) minstret_dfflr (minstret_ena, minstret_nxt, minstret_r , clk, rst_n);
sirv_gnrl_dfflr #(`E203_XLEN) minstreth_dfflr (minstreth_ena, minstreth_nxt, minstreth_r, clk, rst_n); wire [`E203_XLEN-1:0] counterstop_r;
wire counterstop_ena = counterstop_wr_ena;
wire [`E203_XLEN-1:0] counterstop_nxt = {29'b0,wbck_csr_dat[2:0]};// Only LSB 3bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) counterstop_dfflr (counterstop_ena, counterstop_nxt, counterstop_r, clk, rst_n); wire [`E203_XLEN-1:0] csr_mcycle = mcycle_r;
wire [`E203_XLEN-1:0] csr_mcycleh = mcycleh_r;
wire [`E203_XLEN-1:0] csr_minstret = minstret_r;
wire [`E203_XLEN-1:0] csr_minstreth = minstreth_r;
wire [`E203_XLEN-1:0] csr_counterstop = counterstop_r;
`else//}{
wire [`E203_XLEN-1:0] csr_mcycle = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_mcycleh = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_minstret = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_minstreth = `E203_XLEN'b0;
wire [`E203_XLEN-1:0] csr_counterstop = `E203_XLEN'b0;
`endif//} wire [`E203_XLEN-1:0] itcmnohold_r;
wire itcmnohold_ena = itcmnohold_wr_ena;
wire [`E203_XLEN-1:0] itcmnohold_nxt = {31'b0,wbck_csr_dat[0]};// Only LSB 1bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) itcmnohold_dfflr (itcmnohold_ena, itcmnohold_nxt, itcmnohold_r, clk, rst_n); wire [`E203_XLEN-1:0] csr_itcmnohold = itcmnohold_r; wire [`E203_XLEN-1:0] mdvnob2b_r;
wire mdvnob2b_ena = mdvnob2b_wr_ena;
wire [`E203_XLEN-1:0] mdvnob2b_nxt = {31'b0,wbck_csr_dat[0]};// Only LSB 1bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) mdvnob2b_dfflr (mdvnob2b_ena, mdvnob2b_nxt, mdvnob2b_r, clk, rst_n); wire [`E203_XLEN-1:0] csr_mdvnob2b = mdvnob2b_r; assign cy_stop = counterstop_r[0];// Stop CYCLE counter
assign tm_stop = counterstop_r[1];// Stop TIME counter
assign ir_stop = counterstop_r[2];// Stop INSTRET counter,instruction number counter assign itcm_nohold = itcmnohold_r[0];// ITCM no-hold up feature
assign mdv_nob2b = mdvnob2b_r[0];// Mul/Div no back2back feature wire [`E203_XLEN-1:0] mcgstop_r;
wire mcgstop_ena = mcgstop_wr_ena;
wire [`E203_XLEN-1:0] mcgstop_nxt = {30'b0,wbck_csr_dat[1:0]};// Only LSB 2bits are useful
sirv_gnrl_dfflr #(`E203_XLEN) mcgstop_dfflr (mcgstop_ena, mcgstop_nxt, mcgstop_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcgstop = mcgstop_r;
assign core_cgstop = mcgstop_r[0];// Stop Core clock gating
assign tcm_cgstop = mcgstop_r[1];// Stop TCM clock gating
mepc/mcause/mbadaddr/misa等的rtl实现。
//0x041 URW uepc User exception program counter.
// We dont support user trap, so no uepc needed
//0x341 MRW mepc Machine exception program counter.
wire sel_mepc = (csr_idx == 12'h341);
wire rd_mepc = sel_mepc & csr_rd_en;
wire wr_mepc = sel_mepc & csr_wr_en;
wire epc_ena = (wr_mepc & wbck_csr_wen) | cmt_epc_ena;
wire [`E203_PC_SIZE-1:0] epc_r;
wire [`E203_PC_SIZE-1:0] epc_nxt;
assign epc_nxt[`E203_PC_SIZE-1:1] = cmt_epc_ena ? cmt_epc[`E203_PC_SIZE-1:1] : wbck_csr_dat[`E203_PC_SIZE-1:1];
assign epc_nxt[0] = 1'b0;// Must not hold PC which will generate the misalign exception according to ISA
sirv_gnrl_dfflr #(`E203_PC_SIZE) epc_dfflr (epc_ena, epc_nxt, epc_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mepc;
wire dummy_0;
assign {dummy_0,csr_mepc} = {{`E203_XLEN+1-`E203_PC_SIZE{1'b0}},epc_r};
assign csr_epc_r = csr_mepc; //0x042 URW ucause User trap cause.
// We dont support user trap, so no ucause needed
//0x342 MRW mcause Machine trap cause.
wire sel_mcause = (csr_idx == 12'h342);
wire rd_mcause = sel_mcause & csr_rd_en;
wire wr_mcause = sel_mcause & csr_wr_en;
wire cause_ena = (wr_mcause & wbck_csr_wen) | cmt_cause_ena;
wire [`E203_XLEN-1:0] cause_r;
wire [`E203_XLEN-1:0] cause_nxt;
assign cause_nxt[31] = cmt_cause_ena ? cmt_cause[31] : wbck_csr_dat[31];
assign cause_nxt[30:4] = 27'b0;
assign cause_nxt[3:0] = cmt_cause_ena ? cmt_cause[3:0] : wbck_csr_dat[3:0];
sirv_gnrl_dfflr #(`E203_XLEN) cause_dfflr (cause_ena, cause_nxt, cause_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mcause = cause_r; //0x043 URW ubadaddr User bad address.
// We dont support user trap, so no ubadaddr needed
//0x343 MRW mbadaddr Machine bad address.
wire sel_mbadaddr = (csr_idx == 12'h343);
wire rd_mbadaddr = sel_mbadaddr & csr_rd_en;
wire wr_mbadaddr = sel_mbadaddr & csr_wr_en;
wire cmt_trap_badaddr_ena = cmt_badaddr_ena;
wire badaddr_ena = (wr_mbadaddr & wbck_csr_wen) | cmt_trap_badaddr_ena;
wire [`E203_ADDR_SIZE-1:0] badaddr_r;
wire [`E203_ADDR_SIZE-1:0] badaddr_nxt;
assign badaddr_nxt = cmt_trap_badaddr_ena ? cmt_badaddr : wbck_csr_dat[`E203_ADDR_SIZE-1:0];
sirv_gnrl_dfflr #(`E203_ADDR_SIZE) badaddr_dfflr (badaddr_ena, badaddr_nxt, badaddr_r, clk, rst_n);
wire [`E203_XLEN-1:0] csr_mbadaddr;
wire dummy_1;
assign {dummy_1,csr_mbadaddr} = {{`E203_XLEN+1-`E203_ADDR_SIZE{1'b0}},badaddr_r}; // We dont support the delegation scheme, so no need to implement
// delegete registers //0x301 MRW misa ISA and extensions
wire sel_misa = (csr_idx == 12'h301);
wire rd_misa = sel_misa & csr_rd_en;
// Only implemented the M mode, IMC or EMC
wire [`E203_XLEN-1:0] csr_misa = {
2'b1
,4'b0 //WIRI
,1'b0 // 25 Z Reserved
,1'b0 // 24 Y Reserved
,1'b0 // 23 X Non-standard extensions present
,1'b0 // 22 W Reserved
,1'b0 // 21 V Tentatively reserved for Vector extension 20 U User mode implemented
,1'b0 // 20 U User mode implemented
,1'b0 // 19 T Tentatively reserved for Transactional Memory extension
,1'b0 // 18 S Supervisor mode implemented
,1'b0 // 17 R Reserved
,1'b0 // 16 Q Quad-precision floating-point extension
,1'b0 // 15 P Tentatively reserved for Packed-SIMD extension
,1'b0 // 14 O Reserved
,1'b0 // 13 N User-level interrupts supported
,1'b1 // 12 M Integer Multiply/Divide extension
,1'b0 // 11 L Tentatively reserved for Decimal Floating-Point extension
,1'b0 // 10 K Reserved
,1'b0 // 9 J Reserved
`ifdef E203_RFREG_NUM_IS_32
,1'b1 // 8 I RV32I/64I/128I base ISA
`else
,1'b0
`endif
,1'b0 // 7 H Hypervisor mode implemented
,1'b0 // 6 G Additional standard extensions present
`ifndef E203_HAS_FPU//{
,1'b0 // 5 F Single-precision floating-point extension
`endif//
`ifdef E203_RFREG_NUM_IS_32
,1'b0 // 4 E RV32E base ISA
`else
,1'b1 //
`endif
`ifndef E203_HAS_FPU//{
,1'b0 // 3 D Double-precision floating-point extension
`endif//
,1'b1 // 2 C Compressed extension
,1'b0 // 1 B Tentatively reserved for Bit operations extension
`ifdef E203_SUPPORT_AMO//{
,1'b1 // 0 A Atomic extension
`endif//E203_SUPPORT_AMO}
`ifndef E203_SUPPORT_AMO//{
,1'b0 // 0 A Atomic extension
`endif//}
}; //Machine Information Registers
//0xF11 MRO mvendorid Vendor ID.
//0xF12 MRO marchid Architecture ID.
//0xF13 MRO mimpid Implementation ID.
//0xF14 MRO mhartid Hardware thread ID.
wire [`E203_XLEN-1:0] csr_mvendorid = `E203_XLEN'h`E203_MVENDORID;
wire [`E203_XLEN-1:0] csr_marchid = `E203_XLEN'h`E203_MARCHID ;
wire [`E203_XLEN-1:0] csr_mimpid = `E203_XLEN'h`E203_MIMPID ;
wire [`E203_XLEN-1:0] csr_mhartid = {{`E203_XLEN-`E203_HART_ID_W{1'b0}},core_mhartid};
wire rd_mvendorid = csr_rd_en & (csr_idx == 12'hF11);
wire rd_marchid = csr_rd_en & (csr_idx == 12'hF12);
wire rd_mimpid = csr_rd_en & (csr_idx == 12'hF13);
wire rd_mhartid = csr_rd_en & (csr_idx == 12'hF14); //0x7b0 Debug Control and Status
//0x7b1 Debug PC
//0x7b2 Debug Scratch Register
//0x7a0 Trigger selection register
wire sel_dcsr = (csr_idx == 12'h7b0);
wire sel_dpc = (csr_idx == 12'h7b1);
wire sel_dscratch = (csr_idx == 12'h7b2); wire rd_dcsr = dbg_mode & csr_rd_en & sel_dcsr ;
wire rd_dpc = dbg_mode & csr_rd_en & sel_dpc ;
wire rd_dscratch = dbg_mode & csr_rd_en & sel_dscratch; assign wr_dcsr_ena = dbg_mode & csr_wr_en & sel_dcsr ;
assign wr_dpc_ena = dbg_mode & csr_wr_en & sel_dpc ;
assign wr_dscratch_ena = dbg_mode & csr_wr_en & sel_dscratch; assign wr_csr_nxt = wbck_csr_dat; wire [`E203_XLEN-1:0] csr_dcsr = dcsr_r ;
`ifdef E203_PC_SIZE_IS_16
wire [`E203_XLEN-1:0] csr_dpc = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
`endif
`ifdef E203_PC_SIZE_IS_24
wire [`E203_XLEN-1:0] csr_dpc = {{`E203_XLEN-`E203_PC_SIZE{1'b0}},dpc_r};
`endif
`ifdef E203_PC_SIZE_IS_32
wire [`E203_XLEN-1:0] csr_dpc = dpc_r ;
`endif
wire [`E203_XLEN-1:0] csr_dscratch = dscratch_r; assign csr_dpc_r = dpc_r;
下面是我的写的一个testbench,
`include "e203_defines.v"
module e203_exu_csr_tb; reg csr_ena; //csr readwrite enable signal from alu
reg csr_wr_en; //csr write enable
reg csr_rd_en; //csr read enable
reg [11:0] csr_idx;//csr address index wire tm_stop;
wire core_cgstop;
wire tcm_cgstop;
wire itcm_nohold;
wire mdv_nob2b; wire [`E203_XLEN-1:0] read_csr_dat;
reg [`E203_XLEN-1:0] wbck_csr_dat; reg [`E203_HART_ID_W-1:0] core_mhartid;
reg ext_irq_r;
reg sft_irq_r;
reg tmr_irq_r; wire status_mie_r;
wire mtie_r;
wire msie_r;
wire meie_r; wire wr_dcsr_ena ;
wire wr_dpc_ena ;
wire wr_dscratch_ena; reg [`E203_XLEN-1:0] dcsr_r ;
reg [`E203_PC_SIZE-1:0] dpc_r ;
reg [`E203_XLEN-1:0] dscratch_r; wire [`E203_XLEN-1:0] wr_csr_nxt ; reg dbg_mode;
reg dbg_stopcycle; wire u_mode;
wire s_mode;
wire h_mode;
wire m_mode; reg [`E203_ADDR_SIZE-1:0] cmt_badaddr;
reg cmt_badaddr_ena;
reg [`E203_PC_SIZE-1:0] cmt_epc;
reg cmt_epc_ena;
reg [`E203_XLEN-1:0] cmt_cause;
reg cmt_cause_ena;
reg cmt_status_ena;
reg cmt_instret_ena; reg cmt_mret_ena;
wire[`E203_PC_SIZE-1:0] csr_epc_r;
wire[`E203_PC_SIZE-1:0] csr_dpc_r;
wire[`E203_XLEN-1:0] csr_mtvec_r; reg clk=0;
reg rst_n; e203_exu_csr mycsr(
.csr_ena(csr_ena),
.csr_wr_en(csr_wr_en),
.csr_rd_en(csr_rd_en),
.csr_idx(csr_idx),
.tm_stop(tm_stop),
.core_cgstop(core_cgstop),
.tcm_cgstop(tcm_cgstop),
.itcm_nohold(itcm_nohold),
.mdv_nob2b(mdv_nob2b),
.read_csr_dat(read_csr_dat),
.wbck_csr_dat(wbck_csr_dat),
.core_mhartid(core_mhartid),
.ext_irq_r(ext_irq_r),
.sft_irq_r(sft_irq_r),
.tmr_irq_r(tmr_irq_r),
.status_mie_r(status_mie_r),
.mtie_r(mtie_r),
.msie_r(msie_r),
.meie_r(meie_r),
.wr_dcsr_ena(wr_dcsr_ena),
.wr_dpc_ena(wr_dpc_ena),
.wr_dscratch_ena(wr_dscratch_ena),
.dcsr_r(dcsr_r),
.dpc_r(dpc_r),
.dscratch_r(dscratch_r),
.wr_csr_nxt(wr_csr_nxt),
.dbg_mode(dbg_mode),
.dbg_stopcycle(dbg_stopcycle),
.u_mode(u_mode),
.s_mode(s_mode),
.h_mode(h_mode),
.m_mode(m_mode),
.cmt_badaddr(cmt_badaddr),
.cmt_badaddr_ena(cmt_badaddr_ena),
.cmt_epc(cmt_epc),
.cmt_epc_ena(cmt_epc_ena),
.cmt_cause(cmt_cause),
.cmt_cause_ena(cmt_cause_ena),
.cmt_status_ena(cmt_status_ena),
.cmt_instret_ena(cmt_instret_ena),
.cmt_mret_ena(cmt_mret_ena),
.csr_epc_r(csr_epc_r),
.csr_dpc_r(csr_dpc_r),
.csr_mtvec_r(csr_mtvec_r),
.clk_aon(clk),
.clk(clk),
.rst_n(rst_n)
); always #10 clk=~clk; initial
begin
rst_n = 1'b1;
#20
rst_n= 1'b0;
#20
rst_n=1'b1;
csr_ena = 1'b1;
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
csr_idx = 11'h300; //mstatus
wbck_csr_dat = 32'h0001f888;
core_mhartid = `E203_HART_ID_W'h0;
ext_irq_r = 1'b0;
sft_irq_r = 1'b0;
tmr_irq_r = 1'b0;
dcsr_r = `E203_XLEN'h5;
dpc_r = `E203_PC_SIZE'h5;
dscratch_r = `E203_XLEN'h5;
dbg_mode = 1'b0;
dbg_stopcycle= 1'b0;
cmt_badaddr=`E203_ADDR_SIZE'h4;
cmt_badaddr_ena = 1'b0;
cmt_epc=`E203_PC_SIZE'h4;
cmt_epc_ena = 1'b0;
cmt_cause=`E203_XLEN'h4;
cmt_cause_ena = 1'b0;
cmt_status_ena = 1'b0;
cmt_instret_ena = 1'b0;
cmt_mret_ena = 1'b0; #20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20 csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h80;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h888;
csr_idx = 12'h304; //mie
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h800;
csr_idx = 12'h344; //mip
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'hff;
csr_idx = 12'h305; //mtvec
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'hff00;
csr_idx = 12'h340; //mscratch
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h7;
csr_idx = 12'hbff; //counterstop
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h3;
csr_idx = 12'hbfe; //mcgstop
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h1;
csr_idx = 12'hbfd; //itcmnohold
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h1;
csr_idx = 12'hbf0; //mdvnob2b
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'h1;
csr_idx = 12'h341; //mepc
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'haa;
csr_idx = 12'h342; //mcasue
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b1;
csr_rd_en = 1'b0;
wbck_csr_dat = 32'hffff;
csr_idx = 12'h343; //mbadaddr/mtval
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'h301; //misa
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf11; //mvendorid
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf12; //marchid
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf13; //mimpid
#20
csr_wr_en = 1'b0;
csr_rd_en = 1'b1;
csr_idx = 12'hf14; //mhartid
#100 $finish;
end //initial
// $monitor($time,,,"clk=%b,i_instr=0x%h,i_pc=%h",clk,i_instr,i_pc);
initial
begin
//$dumpfile("dump.vcd");
//$dumpvars;
$fsdbDumpfile("dump.fsdb");
$fsdbDumpvars("+all");
end endmodule
Makefile
# VCS flags, if want to use dump fsdb in verilog file, need to add args -fsdb, otherwise will be compiled fail
VCS_FLAGS = -sverilog -full64 -fsdb -debug_all +v2k -timescale=1ns/1ns +define+DISABLE_SV_ASSERTION # Source files
SRC_FILES = e203_exu_csr.v \
sirv_gnrl_dffs.v \
sirv_gnrl_xchecker.v \
e203_exu_csr_tb.v \ # Source directories
INCDIR = +incdir+./ all:
vcs $(VCS_FLAGS) $(INCDIR) $(SRC_FILES)
clean:
rm -rf ./csrc *.daidir ./csrc *.log *.vpd *.vdb simv* *.key *race.out* *vcd *fsdb
debug:
verdi -sv -ssf dump.fsdb -f verdi.f &
E203 CSR rtl实现分析的更多相关文章
- E203 CSR寄存器
RiscV架构则定义了一些控制和状态寄存器(CSR),用于配置或记录一些运行的状态.CSR寄存器是处理器内核内部的寄存器,使用专有的12位地址编码空间,对一个hart,可以配置4k的CSR寄存器. 蜂 ...
- OpenRisc-41-or1200的cache模块分析
引言 为CPU提供足够的,稳定的指令流和数据流是计算机体系结构设计中两个永恒的话题.为了给CPU提供指令流,需要设计分支预测机构,为了给CPU提供数据流,就需要设计cache了.其实,无论是insn还 ...
- 使用Verdi理解RTL design
使用Verdi理解RTL design 接触到一些RTL代码,在阅读与深入理解的过程中的一些思考记录 协议与设计框图 认真反复阅读理解相关协议与设计框图,一个design的设计文档中,设计框图展示了这 ...
- 带你了解强大的Cadence家族,你可能只用到了它1/10的工具
[转载自 SI-list[中国]http://mp.weixin.qq.com/s/qsdfzQwIVjvwHXuCdvrPXA ] 本篇对2017年初版Cadence的全套所有EDA工具的技术特性特 ...
- orpsocv2 从ROM(bootrom)启动分析--以atlys板子的启动为例子
1 复位后的启动地址 1) 复位后,启动地址在or1200_defines.v最后宏定义,atlys板子的目录:orpsocv2\boards\xilinx\atlys\rtl\verilog\inc ...
- 性能分析工具-PerfView
Roslyn的PM(程序经理) Bill Chiles,Roslyn使用纯托管代码开发,但性能超过之前使用C++编写的原生实现,这有什么秘诀呢?他最近写了一篇文章叫做<Essential Per ...
- bidi(双向文字)与RTL布局总结
BIDI 双向文字就是一个字符串中包含了两种文字,既包含从左到右的文字又包含从右到左的文字. 大多数文字都是从左到右的书写习惯,比如拉丁文字(英文字母)和汉字,少数文字是从右到左的书写方式比如阿拉伯文 ...
- [转载] TLS协议分析 与 现代加密通信协议设计
https://blog.helong.info/blog/2015/09/06/tls-protocol-analysis-and-crypto-protocol-design/?from=time ...
- Form_通过Trace分析Concurrent和Form性能和异常详解(案例)
2014-06-21 Created By BaoXinjian
随机推荐
- Java 的 IO 流
接着上一篇的 “Java 的 File 类” 的随笔,在File类的基础上,我们就走进Java的IO流吧. 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在 ...
- SAP MCH1表和MCHA表更新逻辑
SAP MCH1表和MCHA表更新逻辑 笔者所在的A项目里,批次是在material level 唯一, 意味着不同物料号可以有相同的批次号,只要物料号+批次号组合是唯一的即可. SE11 看MCH1 ...
- UIPageControl页面控制的控件
#import "ViewController.h" #import "LazyScrollView.h" @interface ViewController ...
- linux中OTG识别到一个U盘后产生一个sg节点的全过程
注:本篇文章暂时不做流程图,如果有需求后续补做. 1. 需要准备的源码文件列表: base部分: kernel\base\core.c kernel\base\bus.c kernel\base\dd ...
- AudioRecord 录制播放PCM音频
AudioRecord 与 MediaRecorder 区别 AudioRecord 基于字节流录制,输出的是pcm数据,未进行压缩,直接保存的pcm文件不能被播放器识别播放. 可以对音频文件进行实时 ...
- 【一】Gradle 初识
1.Gradle和Maven的对比 gradle 使用groovy语言,可以进行逻辑判断,maven基于xml,无法进行逻辑判断. gradle 可以在一个项目中,根据需求,生成2个不同的jar, m ...
- swoole1--搭建echo服务器
1.安装swoole :pecl install swoole,然后修改php.ini 开启swoole扩展:extension=swoole.so 2.写一个服务器Server.php 1 < ...
- 201871010123-吴丽丽 《面向对象程序设计(Java)》第十六周学习总结
201871010123-吴丽丽 <面向对象程序设计(Java)>第十六周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) F2. Wrong Answer on test 233 (Hard Version) dp 数学
F2. Wrong Answer on test 233 (Hard Version) Your program fails again. This time it gets "Wrong ...
- AtCoder Grand Contest 039
Preface 我发现我现在打AT真的是只会D-Before-- E,F都是抄曲明姐姐的,然后D还是几何画板猜结论做的(证明都是陈指导想的) 看来再这样下去就真的要退役了啊233 A - Connec ...