///////////////////////////////////////////////////////////////////////////////////// // //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" module predictor( input clk, input rst, input imem_req, input `N(`XLEN) imem_addr, output `N(2*`BUS_LEN) imem_predict, input jcond_vld, input `N(`XLEN) jcond_pc, input jcond_hit, input jcond_taken ); //--------------------------------------------------------------------------- //function defination //--------------------------------------------------------------------------- function predict_bit( input `N(`PDT_BLEN) bits ); begin case(bits) 5'b00000 : predict_bit = 0; 5'b00001 : predict_bit = 0; 5'b00010 : predict_bit = 0; 5'b00011 : predict_bit = 1; 5'b00100 : predict_bit = 0; 5'b00101 : predict_bit = 0; 5'b00110 : predict_bit = 0; 5'b00111 : predict_bit = 1; 5'b01000 : predict_bit = 0; 5'b01001 : predict_bit = 0; 5'b01010 : predict_bit = 1; 5'b01011 : predict_bit = 1; 5'b01100 : predict_bit = 0; 5'b01101 : predict_bit = 1; 5'b01110 : predict_bit = 0; 5'b01111 : predict_bit = 1; 5'b10000 : predict_bit = 0; 5'b10001 : predict_bit = 0; 5'b10010 : predict_bit = 1; 5'b10011 : predict_bit = 1; 5'b10100 : predict_bit = 0; 5'b10101 : predict_bit = 0; 5'b10110 : predict_bit = 1; 5'b10111 : predict_bit = 1; 5'b11000 : predict_bit = 0; 5'b11001 : predict_bit = 1; 5'b11010 : predict_bit = 1; 5'b11011 : predict_bit = 1; 5'b11100 : predict_bit = 0; 5'b11101 : predict_bit = 1; 5'b11110 : predict_bit = 1; 5'b11111 : predict_bit = 1; endcase end endfunction //--------------------------------------------------------------------------- //signal defination //--------------------------------------------------------------------------- reg `N(`PDT_LEN) pdt_vld; reg `N(`PDT_ADDR*`PDT_LEN) pdt_address; reg `N(`PDT_BLEN*`PDT_LEN) pdt_bits; wire `N(2*`BUS_LEN) chain_predict `N(`PDT_LEN+1); reg `N(2*`BUS_LEN) get_predict; genvar i; //--------------------------------------------------------------------------- //statements area //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //output predict bit //--------------------------------------------------------------------------- assign chain_predict[0] = 0; `ifdef INSTR_MISALLIGNED wire `N(`PDT_ADDR) target_original = imem_addr>>1; wire `N(`BUS_OFF) target_shift = target_original; wire `N(`PDT_ADDR-`BUS_OFF) target_address = target_original>>`BUS_OFF; generate for (i=0;i<`PDT_LEN;i=i+1) begin:gen_imem_predict wire `N(`BUS_OFF) this_shift = pdt_address[`IDX(i,`PDT_ADDR)]; wire `N(`PDT_ADDR-`BUS_OFF) this_address = pdt_address[`IDX(i,`PDT_ADDR)]>>`BUS_OFF; wire bigger = this_shift>=target_shift; wire `N(`PDT_ADDR-`BUS_OFF) to_address = bigger ? target_address : ( target_address + 1'b1 ); wire this_bit = pdt_vld[i] & (to_address==this_address) & predict_bit(pdt_bits[`IDX(i,`PDT_BLEN)]); wire `N(`BUS_OFF) to_shift = this_shift - target_shift; assign chain_predict[i+1] = chain_predict[i]|(this_bit<>(1+`BUS_OFF); generate for (i=0;i<`PDT_LEN;i=i+1) begin:gen_imem_predict wire `N(`BUS_OFF) this_shift = pdt_address[`IDX(i,`PDT_ADDR)]; wire `N(`PDT_ADDR-`BUS_OFF) this_address = pdt_address[`IDX(i,`PDT_ADDR)]>>`BUS_OFF; wire this_bit = pdt_vld[i] & (target_address==this_address) & predict_bit(pdt_bits[`IDX(i,`PDT_BLEN)]); assign chain_predict[i+1] = chain_predict[i]|(this_bit<>1; generate for (i=0;i<`PDT_LEN;i=i+1) begin:gen_find_index assign chain_find_vld[i+1] = chain_find_vld[i]|(pdt_vld[i] & (pdt_address[`IDX(i,`PDT_ADDR)]==find_aim)); assign chain_find_index[i+1] = (pdt_vld[i] & (pdt_address[`IDX(i,`PDT_ADDR)]==find_aim)) ? i : chain_find_index[i]; end endgenerate wire find_vld = chain_find_vld[`PDT_LEN]; wire `N(`PDT_OFF) find_index = chain_find_index[`PDT_LEN]; wire `N(`PDT_OFF) high_shift = find_index + find_vld; wire `N(`PDT_LEN) high_vld = pdt_vld & ( ~((1'b1<>(find_index*`PDT_BLEN) ) : 5'b11111; wire `N(`PDT_BLEN) new_bits = { old_bits,jcond_taken }; wire `N(`PDT_LEN) go_vld = ( high_vld<<(find_vld ? 1'b0 : 1'b1) )|( low_vld<<1 )|new_vld; wire `N(`PDT_ADDR*`PDT_LEN) go_address = ( high_address<<(find_vld ? 0 : `PDT_ADDR) )|( low_address<<`PDT_ADDR )|new_address; wire `N(`PDT_BLEN*`PDT_LEN) go_bits = ( high_bits<<(find_vld ? 0 : `PDT_BLEN) )|( low_bits<<`PDT_BLEN )|new_bits; `FFx(pdt_vld,0) if ( new_vld ) pdt_vld <= go_vld; else; `FFx(pdt_address,0) if ( new_vld ) pdt_address <= go_address; else; `FFx(pdt_bits,0) if ( new_vld ) pdt_bits <= go_bits; else; endmodule