-
verilog 里 order of priority 实现的方式
a的priority最高。 wire event_a; wire event_b; wire event_c; wire event_d; wire a_select; wire b_select; wire c_select; wire d_select; assign a_select = event_a; assign b_select = ~event_a & event_b; assign c_select = ~event_a & ~event_b & event_c; assign d_select = ~event_a & ~event_b & ~event_c & event_d; 如果2进制编码的话,可以这样,3bit没用完,就不搞太多x_select。 wire [2:0] encode; assign...
-
折腾了下IFU
IFU decode后的一堆_d的信号全给EXU了,这回把这部分信号放在ifu_dec里,给EXU的基本都是_e的信号。 register file还是放在EXU里。 ifu_exu_valid_d变成了在ifu fdp和dec之间的fdp_dec_inst_vld_kill_d,表示这条指令valid并且没有被kill_d。 cpu7_ifu_dec里也就放了些d2e的寄存器,本来这些是在cpu7_exu_ecl里的。 这样exu_ecl就看起来轻松了不少,exu接收_e的信号。 不过将来实现更多的机制,不知道ifu是不是又要折腾。 进到exu的_e信号,基本也都是先进到exu_ecl里,因为可能有一些简单的逻辑要处理,然后由ecl转发给各个功能模块alu lsu bru等。 IFU IFU can be stalled through exu_ifu_stall_req as many cycles as it is pulled high. When IFU is stalled, pc_bf keeps fetching the same address, pc_f : ifu_pcbf_sel_old_bf_l. kill_f is not effective during exu_ifu_stall_req. pc_f2d_reg.en —\ valid_d_reg.en \...
-
处理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...