单发射就不需要issue stage了吧
过段时间就全忘啊。。
verilator模拟的时候出一大堆Read Miss Addr0,这个是正常的,不知道刚开始怎么着就读到地址0了。
新加模块什么的,重新编译要先make clean,现在没时间改进makefile。
要是make clean_all,一定记得在run_func,也就是make的目录下makdir log,创建log文件夹,要不后面不编译了。
verilator要用的内存文件最后在./tmp/ram.dat
Makefile里有这句,不过tmp目录运行完就删除了。
cat ./tmp/rom.vlog > ./tmp/ram.dat;
确认有ram.dat,verilator就能读内存了。刚开始被一堆的Read Miss Addr0给整不会了,以为是内存文件没生成出来。
而且后来读内存的时候,是从1c000000开始读的,但读出来的是0,开始也是以为内存文件的事。
cpu7模块里本来想完全从头写,先只放cpu7_ifu和cpu7_exu,可发现没有tlb和csr模块控制cache,读内存会出问题。
本打算借着这个机会把cache看看,结果先试了把csr和tlb_wrapper加了回来,结果指令取值正常了。
那就先这样吧,一个inst_req要6个还是7个周期才读成功,inst_addr_ok和inst_valid同时返回,还没有看是因为什么。
先在cpu7_ifu里有cpu7_ifu_fdp和cpu7_ifu_dec,取值,解码。
obj/main.elf: file format elf32-loongarch
obj/main.elf
Disassembly of section .text:
1c000000 <_start>:
kernel_entry():
1c000000: 0280058c addi.w $r12,$r12,1(0x1)
1c000004: 0280098c addi.w $r12,$r12,2(0x2)
1c000008: 02800d8c addi.w $r12,$r12,3(0x3)
1c00000c: 0280118c addi.w $r12,$r12,4(0x4)
1c000010: 0280158c addi.w $r12,$r12,5(0x5)
1c000014: 5c000d80 bne $r12,$r0,12(0xc) # 1c000020 <testbranch>
1c000018: 0280058c addi.w $r12,$r12,1(0x1)
1c00001c: 0280058c addi.w $r12,$r12,1(0x1)
1c000020 <testbranch>:
testbranch():
1c000020: 028041ad addi.w $r13,$r13,16(0x10)
1c000024: 028041ad addi.w $r13,$r13,16(0x10)
1c000028: 028041ad addi.w $r13,$r13,16(0x10)
1c00002c: 02816805 addi.w $r5,$r0,90(0x5a)
ifu_exu_op是解码的信息,但这里面好想没有imm,看来ifu里面也要搞个cpu7_ifu_imd这样的模块把imm解码出来。
issue stage在单发射里就可以不要了
chiplab里有issue stage,是因为后面的功能模块可能被占用,不能2个port同时用。
虽然ALU有两个,port0 port1都可以同时执行alu相关的指令。但浮点,csr模块都只有一个,比如port0执行浮点运算,port1就不能再issue下去了。
这也就是为什么多发射要有issue这样的模块。 在chiplab里,功能模块占用了,有冲突叫做crash。
我现在搞单发射就不需要用issue了。
参考opensparc,sparc_ifu_dec解码模块会解码出不同的信号给如alu,fpu,lsu等不同功能模块的信号。
// to EXU
output [2:0] ifu_exu_aluop_d;// 000 - add/sub
// 001 - and
// 010 - or
// 011 - xor
// 1X0 - movcc
// 1x1 - movr
output ifu_exu_invert_d; // invert rs2 operand
output ifu_exu_useimm_d;
output ifu_exu_usecin_d; // use c from icc
output ifu_exu_enshift_d; // turn on shifter
output ifu_exu_tagop_d,
ifu_exu_tv_d,
ifu_exu_muls_d,
ifu_exu_ialign_d,
ifu_exu_range_check_jlret_d,
ifu_exu_range_check_other_d;
output [2:0] ifu_exu_shiftop_d; // b2 - 32b(0) or 64b(1)
// b1 - unsigned(0) or signed(1)
// b0 - left(0) or right(1) shift
output [4:0] ifu_exu_muldivop_d; // b4 - is_mul
// b3 - is_div
// b2 - 64b if 1, 32b if 0
// b1 - signed if 1, unsigned if 0
// b0 - set cc's
output ifu_exu_wen_d; // write to rd
output ifu_exu_setcc_d; // b0 - write to icc/xcc
output ifu_exu_rd_ifusr_e,
ifu_exu_rd_exusr_e,
ifu_exu_rd_ffusr_e;
output ifu_exu_rs1_vld_d,
ifu_exu_rs2_vld_d,
ifu_exu_rs3e_vld_d,
ifu_exu_rs3o_vld_d;
output ifu_exu_use_rsr_e_l;
output ifu_exu_save_d,
ifu_exu_restore_d,
ifu_exu_return_d,
ifu_exu_flushw_e,
ifu_exu_saved_e,
ifu_exu_restored_e;
// to TLU
output ifu_tlu_rsr_inst_d,
ifu_lsu_wsr_inst_d,
ifu_exu_wsr_inst_d,
ifu_tlu_done_inst_d,
ifu_tlu_retry_inst_d;
// to LSU
output ifu_lsu_ld_inst_e, // ld inst or atomic
ifu_lsu_st_inst_e, // store or atomic
ifu_lsu_pref_inst_e,
ifu_lsu_alt_space_e, // alt space -- to be removed
ifu_lsu_alt_space_d, // never x -- to be removed
ifu_tlu_alt_space_d, // sometimes x but faster
ifu_lsu_memref_d; // alerts lsu of upcoming ldst
// ifu_lsu_imm_asi_vld_d;
output ifu_lsu_sign_ext_e,
ifu_lsu_ldstub_e,
ifu_lsu_casa_e,
ifu_exu_casa_d,
ifu_lsu_swap_e;
output ifu_tlu_mb_inst_e,
ifu_tlu_sir_inst_m,
ifu_tlu_flsh_inst_e;
output ifu_lsu_ldst_dbl_e,
ifu_lsu_ldst_fp_e;
output [1:0] ifu_lsu_ldst_size_e;
// to SPU
// output ifu_spu_scpy_inst_e,
// ifu_spu_scmp_inst_e;
// to FFU
output ifu_ffu_fpop1_d;
output ifu_ffu_visop_d;
output ifu_ffu_fpop2_d;
output ifu_ffu_fld_d;
output ifu_ffu_fst_d;
output ifu_ffu_ldst_size_d;
output ifu_ffu_ldfsr_d,
ifu_ffu_ldxfsr_d,
ifu_ffu_stfsr_d;
output ifu_ffu_quad_op_e;
// within IFU
output dec_fcl_rdsr_sel_pc_d,
dec_fcl_rdsr_sel_thr_d;
output dec_imd_call_inst_d;
output dtu_fcl_flush_sonly_e,
// dec_fcl_kill4sta_e,
dtu_fcl_illinst_e,
dtu_fcl_fpdis_e,
dtu_fcl_privop_e,
dtu_fcl_imask_hit_e,
dtu_fcl_br_inst_d,
dtu_fcl_sir_inst_e;
output dtu_ifq_kill_latest_d;
// within DTU
output dec_swl_wrt_tcr_w,
dec_swl_wrtfprs_w,
dec_swl_ll_done_d,
dec_swl_br_done_d,
dec_swl_rdsr_sel_thr_d,
dec_swl_ld_inst_d,
dec_swl_sta_inst_e,
dec_swl_std_inst_d,
dec_swl_st_inst_d,
dec_swl_fpop_d,
dec_swl_allfp_d,
dec_swl_frf_upper_d,
dec_swl_frf_lower_d,
dec_swl_div_inst_d,
dec_swl_mul_inst_d,
wsr_fixed_inst_w,
ifu_exu_sethi_inst_d; // can be sethi or no-op
output [2:0] dec_dcl_cctype_d; // 0yy - fcc(yy)
// 100 - icc
// 110 - xcc
// 1X1 - illegal inst!
问题来了,是不是要有个信号表示这条指令到底是发给ALU的运算指令,还是发给LSU的读写指令?
到是没看到这样的信号,但有ifu_exu_wen_d。ALU不管怎么算,最终要写回寄存器才有作用。
//-------------------
// Writeback Controls
//-------------------
// write to icc/xcc
assign ifu_exu_setcc_d = arith_inst &
(op3_hi[1] & (~op3[3] | ~op3[1] & ~op3[0]) |
op3_hi[2] & (~op3[3] & ~op3[2])); // tagged op
// write to rd
assign ifu_exu_wen_d = ((~rd_00) & brsethi_inst & sethi_or_nop | // sethi
(~rd_00) & arith_inst & // all single cycle insts
(~op3[5] & ~op3[3] | // alu ops
~op3[5] & op3_lo[8] | // addC
~op3[5] & op3_lo[12] | // subC
op3_hi[2] &
(~op3[3] & ~op3_lo[4] | // shft, tag, ~muls
// need to kill if rd to invalid reg
// all vld regs will retn in W stage
op3_lo[8] & ~rs1_0f | op3_lo[10] | // rd
op3_lo[9] | // rdhpr
op3_lo[12] | op3_lo[15])| // mov
op3_hi[3] &
(op3_lo[8] | // jmpl
op3_lo[12] | // save
op3_lo[13] | // restore
op3_lo[6] & int_align_d) // vis int align
) |
call_inst);
在sparc_exu_ecl里,信号给进sparc_exu_ecl_wb。
input ifu_exu_wen_d; // instruction in d-stage writes to regfile
input ifu_exu_ialign_d;// instruction is alignaddress
// Writeback control logic
sparc_exu_ecl_wb writeback(
...
.rd_m (rd_m[4:0]),
.tid_m (tid_m[1:0]),
.thr_m (thr_m[3:0]),
.tid_w1 (tid_w1[1:0]),
.ifu_exu_wen_d(ifu_exu_wen_d),
.ifu_exu_kill_e(ifu_exu_kill_e),
...
);
还是用chiplab里的alu吧,因为loongarch里好像是有三个操作数的指令?
//alu0
wire [`GRLEN-1:0] alu0_a = ex1_port0_a_lsu_fw ? ex1_lsu_fw_data : ex1_port0_a;
wire [`GRLEN-1:0] alu0_b = ex1_port0_b_lsu_fw ? ex1_lsu_fw_data : ex1_port0_b;
alu alu0( .a (alu0_a),
.b (alu0_b),
.double_word(ex1_port0_double),
.alu_op (ex1_port0_op),
.c (ex1_port0_c),
.Result (ex1_alu0_res)
);