///////////////////////////////////////////////////////////////////////////////////// // //Copyright 2019 Li Xinbing // //Licensed under the Apache License, Version 2.0 (the "License"); //you may not use this file except in compliance with the License. //You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. // ///////////////////////////////////////////////////////////////////////////////////// `include "define.v" `define TIMING_STYLE module schedule( input clk, input rst, output `N(`SDBUF_OFF) sdbuf_left_num, input `N(`FETCH_LEN) fetch_vld, input `N(`FETCH_LEN*`XLEN) fetch_instr, input `N(`FETCH_LEN*`XLEN) fetch_pc, input `N(`FETCH_LEN*`EXEC_PARA_LEN) fetch_para, input `N(`FETCH_LEN*`JCBUF_OFF) fetch_level, output `N(`EXEC_LEN) exec_vld, output reg `N(`EXEC_LEN*`XLEN) exec_instr, output reg `N(`EXEC_LEN*`XLEN) exec_pc, output reg `N(`EXEC_LEN*`EXEC_PARA_LEN) exec_para, output reg `N(`EXEC_LEN*`JCBUF_OFF) exec_level, output reg `N(`EXEC_LEN*`MMCMB_OFF) exec_order, input `N(`RGBIT) mmbuf_check_rdnum, input `N(`RGLEN) mmbuf_check_rdlist, input `N(`RGLEN) mmbuf_instr_rdlist, input `N(`MMBUF_OFF) mmbuf_mem_num, input `N(`RFBUF_OFF) rfbuf_alu_num, input `N(`MEM_OFF) mem_release, input clear_pipeline, input level_decrease, input level_clear, output `N(`RGLEN) pipeline_instr_rdlist, output pipeline_is_empty, output schd_intflag, output `N(`XLEN) schd_intpc ); //--------------------------------------------------------------------------- //function defination //--------------------------------------------------------------------------- `include "include_func.v" `ifdef TIMING_STYLE function check_hard( input `N(`EXEC_PARA_LEN) a_para,b_para ); reg a_mem,a_alu,b_mem,b_alu; reg `N(`RGBIT) a_rs0,a_rs1,a_rd,b_rs0,b_rs1,b_rd; begin a_mem = (a_para>>((3*`RGBIT)+1)); a_alu = (a_para>>(3*`RGBIT)); a_rs0 = a_para; a_rs1 = a_para>>`RGBIT; a_rd = a_para>>(2*`RGBIT); b_mem = (b_para>>((3*`RGBIT)+1)); b_alu = (b_para>>(3*`RGBIT)); b_rs0 = b_para; b_rs1 = b_para>>`RGBIT; b_rd = b_para>>(2*`RGBIT); check_hard = (a_rd!=0)&(((a_rd==b_rs0)|(a_rd==b_rs1))|(a_mem&(a_rd==b_rd))); end endfunction function check_soft( input `N(`EXEC_PARA_LEN) a_para,b_para ); reg a_mem,a_alu,b_mem,b_alu; reg `N(`RGBIT) a_rs0,a_rs1,a_rd,b_rs0,b_rs1,b_rd; begin a_mem = (a_para>>((3*`RGBIT)+1)); a_alu = (a_para>>(3*`RGBIT)); a_rs0 = a_para; a_rs1 = a_para>>`RGBIT; a_rd = a_para>>(2*`RGBIT); b_mem = (b_para>>((3*`RGBIT)+1)); b_alu = (b_para>>(3*`RGBIT)); b_rs0 = b_para; b_rs1 = b_para>>`RGBIT; b_rd = b_para>>(2*`RGBIT); check_soft = (b_rd!=0)&((a_rs0==b_rd)|(a_rs1==b_rd)|(a_alu&(a_rd==b_rd))); end endfunction `endif function check_blacklist( input `N(`EXEC_PARA_LEN) para, input `N(`RGLEN) rd_list,rs_list ); reg `N(`RGBIT) rs0,rs1,rd; reg rd_hit, rs_hit; begin rs0 = para; rs1 = para>>`RGBIT; rd = para>>(2*`RGBIT); rd_hit = |( ( rd_list & `LASTBIT_MASK ) & ( 1'b1<>`RGBIT; rd = para>>(2*`RGBIT); check_gray = ((rs0==gray_num)|(rs1==gray_num)|(rd==gray_num))&(gray_num!=0); end endfunction //--------------------------------------------------------------------------- //signal defination //--------------------------------------------------------------------------- wire `N((`FETCH_LEN+1)*`MMCMB_OFF) chain_order; wire `N(`FETCH_LEN*`MMCMB_OFF) fetch_order; wire `N(`SDBUF_LEN) go_vld; wire `N(`SDBUF_LEN*`XLEN) go_instr; wire `N(`SDBUF_LEN*`XLEN) go_pc; wire `N(`SDBUF_LEN*`EXEC_PARA_LEN) go_para; wire `N(`SDBUF_LEN*`MMCMB_OFF) go_order; wire `N(`SDBUF_LEN*`JCBUF_OFF) go_level; wire `N(`SDBUF_LEN) go_stay; wire `N(`RGBIT) check_num; wire `N(`RGLEN) check_rdlist; `ifndef TIMING_STYLE wire `N(`RGLEN) rd_checklist `N(`SDBUF_LEN+1); wire `N(`RGLEN) rs_checklist `N(`SDBUF_LEN+1); `endif wire `N(`MMBUF_LEN) mem_active `N(`SDBUF_LEN+1); wire `N(`RFBUF_LEN) rf_active `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN) exec_active `N(`SDBUF_LEN+1); wire `N(`EXEC_OFF) exec_num `N(`SDBUF_LEN+1); wire `N(`SDBUF_OFF) sdbuf_num `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN) chain_exec_direct `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN) chain_exec_preload `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN*`XLEN) chain_exec_instr `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN*`XLEN) chain_exec_pc `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN*`EXEC_PARA_LEN) chain_exec_para `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN*`MMCMB_OFF) chain_exec_order `N(`SDBUF_LEN+1); wire `N(`EXEC_LEN*`JCBUF_OFF) chain_exec_level `N(`SDBUF_LEN+1); wire `N(`SDBUF_LEN) chain_sdbuf_direct `N(`SDBUF_LEN+1); wire `N(`SDBUF_LEN) chain_sdbuf_preload `N(`SDBUF_LEN+1); wire `N(`SDBUF_LEN*`XLEN) chain_sdbuf_instr `N(`SDBUF_LEN+1); wire `N(`SDBUF_LEN*`XLEN) chain_sdbuf_pc `N(`SDBUF_LEN+1); wire `N(`SDBUF_LEN*`EXEC_PARA_LEN) chain_sdbuf_para `N(`SDBUF_LEN+1); wire `N(`SDBUF_LEN*`MMCMB_OFF) chain_sdbuf_order `N(`SDBUF_LEN+1); wire `N(`SDBUF_LEN*`JCBUF_OFF) chain_sdbuf_level `N(`SDBUF_LEN+1); wire `N(`SDBUF_OFF) chain_sdexec_mem_num `N(`SDBUF_LEN+1); wire `N(`RGLEN) chain_sdbuf_instr_rdlist `N(`SDBUF_LEN+1); wire `N(`EXEC_OFF) chain_exec_mem_num0 `N(`SDBUF_LEN+1); wire `N(`EXEC_OFF) chain_exec_mem_num1 `N(`SDBUF_LEN+1); wire `N(`EXEC_OFF) chain_exec_alu_num0 `N(`SDBUF_LEN+1); wire `N(`EXEC_OFF) chain_exec_alu_num1 `N(`SDBUF_LEN+1); wire chain_find_mem `N(`SDBUF_LEN+1); wire `N(`XLEN) chain_find_pc `N(`SDBUF_LEN+1); reg `N(`EXEC_LEN) exec_direct; reg `N(`EXEC_LEN) exec_preload; reg `N(`SDBUF_LEN) sdbuf_direct; reg `N(`SDBUF_LEN) sdbuf_preload; wire `N(`SDBUF_LEN) sdbuf_vld; reg `N(`SDBUF_LEN*`XLEN) sdbuf_instr; reg `N(`SDBUF_LEN*`XLEN) sdbuf_pc; reg `N(`SDBUF_LEN*`EXEC_PARA_LEN) sdbuf_para; reg `N(`SDBUF_LEN*`MMCMB_OFF) sdbuf_order; reg `N(`SDBUF_LEN*`JCBUF_OFF) sdbuf_level; reg `N(`SDBUF_OFF) sdbuf_length; reg `N(`SDBUF_OFF) sdexec_mem_num; reg `N(`RGLEN) sdbuf_instr_rdlist; reg `N(`EXEC_OFF) exec_mem_num0; reg `N(`EXEC_OFF) exec_mem_num1; wire `N(`EXEC_OFF) exec_mem_num; reg `N(`EXEC_OFF) exec_alu_num0; reg `N(`EXEC_OFF) exec_alu_num1; wire `N(`EXEC_OFF) exec_alu_num; reg `N(`RGBIT) exec_check_rdnum0; reg `N(`RGBIT) exec_check_rdnum1; wire `N(`RGBIT) exec_check_rdnum; reg `N(`RGLEN) exec_check_rdlist0; reg `N(`RGLEN) exec_check_rdlist1; wire `N(`RGLEN) exec_check_rdlist; genvar i,j; //--------------------------------------------------------------------------- //statements area //--------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- //to get order for every instuction: how many MEM instructions exist in membuf and sdbuf. //------------------------------------------------------------------------------------------- assign chain_order[`IDX(0,`MMCMB_OFF)] = mmbuf_mem_num + sdexec_mem_num; generate for (i=0;i<`FETCH_LEN;i=i+1) begin:gen_fetch_order wire vld = fetch_vld>>i; wire `N(`EXEC_PARA_LEN) para = fetch_para>>(i*`EXEC_PARA_LEN); wire mem = para>>(1+3*`RGBIT); assign chain_order[`IDX(i+1,`MMCMB_OFF)] = chain_order[`IDX(i,`MMCMB_OFF)] + (vld&mem); end endgenerate assign fetch_order = chain_order>>`MMCMB_OFF; //------------------------------------------------------------------------------------------- //to evaluate sdbuf //------------------------------------------------------------------------------------------- //to combine incoming instructions and sdbuf instructions. assign go_vld = sdbuf_vld|(fetch_vld<>(mmbuf_mem_num + exec_mem_num); //membuf left space assign rf_active[0] = {`RFBUF_LEN{1'b1}}>>(rfbuf_alu_num + exec_alu_num); //rfbuf left space assign exec_active[0] = {`EXEC_LEN{1'b1}}; assign exec_num[0] = 0; assign sdbuf_num[0] = 0; assign chain_exec_direct[0] = 0; assign chain_exec_preload[0] = 0; assign chain_exec_instr[0] = 0; assign chain_exec_pc[0] = 0; assign chain_exec_para[0] = 0; assign chain_exec_order[0] = 0; assign chain_exec_level[0] = 0; assign chain_sdbuf_direct[0] = 0; assign chain_sdbuf_preload[0] = 0; assign chain_sdbuf_instr[0] = 0; assign chain_sdbuf_pc[0] = 0; assign chain_sdbuf_para[0] = 0; assign chain_sdbuf_order[0] = 0; assign chain_sdbuf_level[0] = 0; assign chain_sdexec_mem_num[0] = 0; assign chain_sdbuf_instr_rdlist[0] = 0; assign chain_exec_mem_num0[0] = 0; assign chain_exec_mem_num1[0] = 0; assign chain_exec_alu_num0[0] = 0; assign chain_exec_alu_num1[0] = 0; assign chain_find_mem[0] = 0; assign chain_find_pc[0] = 0; generate for (i=0;i<`SDBUF_LEN;i=i+1) begin:gen_sdbuf //basic info wire `N(`XLEN) instr = go_instr>>(i*`XLEN); wire `N(`XLEN) pc = go_pc>>(i*`XLEN); wire `N(`EXEC_PARA_LEN) para = go_para>>(i*`EXEC_PARA_LEN); wire mem = para>>(1+3*`RGBIT); wire alu = para>>(3*`RGBIT); wire `N(`RGBIT) rs0 = para; wire `N(`RGBIT) rs1 = para>>`RGBIT; wire `N(`RGBIT) rd = para>>(2*`RGBIT); wire `N(`MMCMB_OFF) order = go_order>>(i*`MMCMB_OFF); wire `N(`MMCMB_OFF) orderx = sub_order(order,mem_release); wire `N(`JCBUF_OFF) level = go_level>>(i*`JCBUF_OFF); wire `N(`JCBUF_OFF) levelx = sub_level(level,level_decrease); wire level_zero = (level==0)|((level==1)&level_decrease); `ifdef TIMING_STYLE wire hit_common = check_blacklist(para,check_rdlist,check_rdlist); wire hit_hard,hit_soft; if (i==0) begin:gen_hit_zero assign hit_hard = 0; assign hit_soft = 0; end else begin:gen_hit_other wire `N(i) bits_hard, bits_soft; for (j=0;j>( alu2exec|mem2exec ); assign mem_active[i+1] = mem2sdbuf ? 0 : (mem_active[i]>>mem2exec); assign rf_active[i+1] = rf_active[i]>>alu2exec; assign exec_num[i+1] = exec_num[i] + ( alu2exec|mem2exec ); assign sdbuf_num[i+1] = sdbuf_num[i] + ( alu2sdbuf|mem2sdbuf ); //clear is a flag to signal this instruction is invalid. wire clear = (alu & (rd==0))|( clear_pipeline & ~((orderx==0)&(level==0)) )|( level_clear & (level!=0) ); //special instruction should be assigned to the last exec ALU. wire `N(`EXEC_OFF) exec_shift = ( alu2exec|mem2exec ) ? exec_num[i] : `EXEC_LEN; assign chain_exec_direct[i+1] = chain_exec_direct[i]|( ((clear|preload) ? 1'b0 : 1'b1)<