u@home:~$

  • 处理exception interrupt的时机

    纠结在流水线的什么阶段处理exception和interrupt。 interrupt可以算做是exception的一种,在loogarch里interrupt是exception cdoe的里的一个,处理函数入口点是同一个,eentry。 但本质的不同是interrupt是async,任意时间都可以发生的。exception看作是同步的,但在流水线的不同阶段是有不同种类的异常。 比如illegal instruction是在decode阶段,ale是在_e计算地址的时候。 具体在流水线哪个阶段处理,这是个需要搞清楚的问题。 大改了解了其它的代码,应该是在completion或者说指令retire,commit的时候,看看指令有没有exception。exception code也是跟着指令一起通过流水线。 这说的是乱序的核。 顺序核的话就是_w的阶段,在这里处理exception,包括interrupt,最主要的问题就是流水线前面所有的指令都要刷掉。但如果流水线里有store指令,在进入到_w之前就已经写内存了,没有办法取消了。如果是流水线只要产生exception或有interrupt就设置标志位让后面已经进到pipeline的store指令不写内存,这样似乎是可以,但感觉有点奇怪。因为这样等同于stall fetch,然后刷新pipeline里的其它指令,并且让当前指令顺着pipeline走到_w再去处理。那为什么不马上处理呢? 所以现在的想法是,在_e的时候处理exception和interrupt。因为指令到_e,就一定是branch走对了的指令。进eentry的时候,era里存的也是pc_e的值,等ertn的时候从之前_e的指令重新执行。 如果是decode的exception,比如illegal instruction,exception code跟着pipeline到_e的地方处理。 如果是store或load指令出异常,比如页面不存在,这种虽然可能在_m,但因为stall了fetch,所以pipeline里并没有其它指令,也可以马上处理,只是era里要存什么还要到时候想清楚。 这种方式解决了前面说的test21_timer_intr_right_after_branch里的bug。 加了kill_e,在exu_ifu_except的时候exu里kill_d, kill_e。 在ifu里加了kill_f。其实以前就有kill_f的功能,只是没这么叫。 wire kill_f; assign kill_f = exu_ifu_stall_req | br_taken | exu_ifu_except | exu_ifu_ertn_e; assign fdp_dec_valid = inst_valid_f & (~kill_f); // pc_f shoudl not be passed to pc_d if a branch...

  • timer中断发生在branch指令后的下一条指令

    例子就是下面这样,设置好timer,正好在1c000044的时候触发,在beq指令的下一句。 这么测的原因是interrupt和branch都会改pc_bf,看看这俩会不会冲突。 Disassembly of section .text: 1c000000 <_start>: kernel_entry(): 1c000000: 14380006 lu12i.w $r6,114688(0x1c000) 1c000004: 028230c6 addi.w $r6,$r6,140(0x8c) 1c000008: 04003026 csrwr $r6,0xc 1c00000c: 02802805 addi.w $r5,$r0,10(0xa) 1c000010: 02801006 addi.w $r6,$r0,4(0x4) 1c000014: 04000026 csrwr $r6,0x0 1c000018: 02804406 addi.w $r6,$r0,17(0x11) 1c00001c: 04010426 csrwr $r6,0x41 1c000020: 02800005 addi.w $r5,$r0,0 1c000024: 02800000 addi.w $r0,$r0,0 1c000028:...

  • cpu7b csr timer

    这次实现csr里的timer,遇到的问题估计以前遇到过,但忘了怎么处理了。 问题是:timer倒数到0后,产生timer_intr,这个信号是存在一个cycle的。 但timer要做成level中断,也就是在不清理中断源之前,timer中断的信号一直都是高的。只有一个cycle,就是edge中断了。 exu_ifu_except通知ifu,这个信号只能是一个cycle,否则会stall住ifu。 应该给自己规定下,模块之间传递的信号,都是1 cycle。如果需要一直拉高的信号,由接收的模块自己提供寄存器解决。 比如这个timer的level interrupt,在csr模块里确实是有一个1bit寄存器一直给出1,作为中断源,直到写ticlr寄存器关掉这个中断源。 但csr给ecl的csr_ecl_timer_intr,是只有一个cycle。这个是通过crmd.ie位的参与实现的,因为进了中断处理函数,crmd.ie存入prmd.pie,当前crmd.ie置0,关中断。表示当前中断处理函数不会被打断,但中断处理函数返回后中断又可以了。 ticlr_clr ____--------- crmd_ie -----________ csr_ecl_timer_intr ____-________