Branch predictor done

This commit is contained in:
waleed-lm 2020-09-29 22:43:23 +05:00
parent f49ed81ddd
commit ffdead1101
12 changed files with 47301 additions and 637 deletions

View File

@ -61,6 +61,33 @@
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_exu_i0_br_index_r" "~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_exu_i0_br_index_r"
] ]
}, },
{
"class":"firrtl.transforms.CombinationalPath",
"sink":"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifu_bp_poffset_f",
"sources":[
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifc_fetch_addr_f",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifc_fetch_req_f",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_flush_leak_one_wb",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_flush_lower_wb",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_br0_r_pkt_br_start_error",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_br0_r_pkt_br_error",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_exu_i0_br_index_r"
]
},
{
"class":"firrtl.transforms.CombinationalPath",
"sink":"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifu_bp_hit_taken_f",
"sources":[
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_bpred_disable",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifc_fetch_req_f",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifc_fetch_addr_f",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_flush_leak_one_wb",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_flush_lower_wb",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_br0_r_pkt_br_start_error",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_br0_r_pkt_br_error",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_exu_i0_br_index_r"
]
},
{ {
"class":"firrtl.transforms.CombinationalPath", "class":"firrtl.transforms.CombinationalPath",
"sink":"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifu_bp_valid_f", "sink":"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifu_bp_valid_f",
@ -88,6 +115,21 @@
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_exu_i0_br_index_r" "~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_exu_i0_br_index_r"
] ]
}, },
{
"class":"firrtl.transforms.CombinationalPath",
"sink":"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifu_bp_inst_mask_f",
"sources":[
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifu_bp_hit_taken_f",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_bpred_disable",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifc_fetch_req_f",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_ifc_fetch_addr_f",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_flush_leak_one_wb",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_flush_lower_wb",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_br0_r_pkt_br_start_error",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_dec_tlu_br0_r_pkt_br_error",
"~el2_ifu_bp_ctl|el2_ifu_bp_ctl>io_exu_i0_br_index_r"
]
},
{ {
"class":"firrtl.EmitCircuitAnnotation", "class":"firrtl.EmitCircuitAnnotation",
"emitter":"firrtl.VerilogEmitter" "emitter":"firrtl.VerilogEmitter"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,16 +6,16 @@ import chisel3.util._
class el2_ifu_bp_ctl extends Module with el2_lib { class el2_ifu_bp_ctl extends Module with el2_lib {
val io = IO (new Bundle { val io = IO (new Bundle {
val clk = Input(Bool()) // val clk = Input(Bool())
val active_clk = Input(Bool()) // val active_clk = Input(Bool())
val rst_l = Input(Bool()) // val rst_l = Input(Bool())
val ic_hit_f = Input(Bool()) val ic_hit_f = Input(Bool())
val ifc_fetch_addr_f = Input(UInt(32.W)) val ifc_fetch_addr_f = Input(UInt(31.W))
val ifc_fetch_req_f = Input(Bool()) // Fetch request generated by the IFC val ifc_fetch_req_f = Input(Bool()) // Fetch request generated by the IFC
// Decode packet containing information if its a brnach or not // Decode packet containing information if its a brnach or not
val dec_tlu_br0_r_pkt = Input(new el2_br_tlu_pkt_t) val dec_tlu_br0_r_pkt = Input(new el2_br_tlu_pkt_t)
val exu_i0_br_fghr_r = Input(UInt(BHT_GHR_SIZE.W)) // Updated GHR from the exu val exu_i0_br_fghr_r = Input(UInt(BHT_GHR_SIZE.W)) // Updated GHR from the exu
val exu_i0_br_index_r = Input(UInt((BTB_ADDR_HI-BTB_ADDR_LO).W)) // Way from where the btb got a hit val exu_i0_br_index_r = Input(UInt((BTB_ADDR_HI-BTB_ADDR_LO+1).W)) // Way from where the btb got a hit
val dec_tlu_flush_lower_wb = Input(Bool()) val dec_tlu_flush_lower_wb = Input(Bool())
val dec_tlu_flush_leak_one_wb = Input(Bool()) val dec_tlu_flush_leak_one_wb = Input(Bool())
val dec_tlu_bpred_disable = Input(Bool()) val dec_tlu_bpred_disable = Input(Bool())
@ -23,7 +23,7 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val exu_mp_pkt = Input(new el2_predict_pkt_t) val exu_mp_pkt = Input(new el2_predict_pkt_t)
val exu_mp_eghr = Input(UInt(BHT_GHR_SIZE.W)) val exu_mp_eghr = Input(UInt(BHT_GHR_SIZE.W))
val exu_mp_fghr = Input(UInt(BHT_GHR_SIZE.W)) val exu_mp_fghr = Input(UInt(BHT_GHR_SIZE.W))
val exu_mp_index = Input(UInt((BTB_ADDR_HI-BTB_ADDR_LO).W)) // Misprediction index val exu_mp_index = Input(UInt((BTB_ADDR_HI-BTB_ADDR_LO+1).W)) // Misprediction index
val exu_mp_btag = Input(UInt(BTB_BTAG_SIZE.W)) val exu_mp_btag = Input(UInt(BTB_BTAG_SIZE.W))
val exu_flush_final = Input(Bool()) val exu_flush_final = Input(Bool())
@ -38,20 +38,7 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val ifu_bp_pc4_f = Output(UInt(2.W)) val ifu_bp_pc4_f = Output(UInt(2.W))
val ifu_bp_valid_f = Output(UInt(2.W)) val ifu_bp_valid_f = Output(UInt(2.W))
val ifu_bp_poffset_f = Output(UInt(12.W)) val ifu_bp_poffset_f = Output(UInt(12.W))
// val test = Output(Vec(8,UInt(32.W)))
}) })
io.ifu_bp_hit_taken_f := 0.U
io.ifu_bp_btb_target_f := 0.U
io.ifu_bp_inst_mask_f := 0.U
io.ifu_bp_fghr_f := 0.U
io.ifu_bp_way_f := 0.U
io.ifu_bp_ret_f := 0.U
io.ifu_bp_hist1_f := 0.U
io.ifu_bp_hist0_f := 0.U
io.ifu_bp_pc4_f := 0.U
io.ifu_bp_valid_f := 0.U
io.ifu_bp_poffset_f := 0.U
val TAG_START = 16+BTB_BTAG_SIZE val TAG_START = 16+BTB_BTAG_SIZE
val PC4 = 4 val PC4 = 4
@ -64,9 +51,21 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val NUM_BHT_LOOP_INNER_HI = if(BHT_ARRAY_DEPTH > 16) BHT_ADDR_LO+3 else BHT_ADDR_HI val NUM_BHT_LOOP_INNER_HI = if(BHT_ARRAY_DEPTH > 16) BHT_ADDR_LO+3 else BHT_ADDR_HI
val NUM_BHT_LOOP_OUTER_LO = if(BHT_ARRAY_DEPTH > 16) BHT_ADDR_LO+4 else BHT_ADDR_LO val NUM_BHT_LOOP_OUTER_LO = if(BHT_ARRAY_DEPTH > 16) BHT_ADDR_LO+4 else BHT_ADDR_LO
val BHT_NO_ADDR_MATCH = BHT_ARRAY_DEPTH <= 16 val BHT_NO_ADDR_MATCH = BHT_ARRAY_DEPTH <= 16
/////////////////////////////////////////////////////////
val leak_one_f = WireInit(Bool(), 0.U) val leak_one_f = WireInit(Bool(), 0.U)
val exu_mp_valid = io.exu_mp_pkt.misp & ~leak_one_f val bht_dir_f = WireInit(UInt(2.W), 0.U)
val dec_tlu_error_wb = WireInit(Bool(), 0.U)
val btb_error_addr_wb = WireInit(UInt((BTB_ADDR_HI-BTB_ADDR_LO).W), 0.U)
val btb_bank0_rd_data_way0_f = WireInit(UInt((TAG_START+1).W), 0.U)
val btb_bank0_rd_data_way1_f = WireInit(UInt((TAG_START+1).W), 0.U)
val btb_bank0_rd_data_way0_p1_f = WireInit(UInt((TAG_START+1).W), 0.U)
val btb_bank0_rd_data_way1_p1_f = WireInit(UInt((TAG_START+1).W), 0.U)
val eoc_mask = WireInit(Bool(), 0.U)
val btb_lru_b0_f = WireInit(UInt(LRU_SIZE.W), init = 0.U)
val dec_tlu_way_wb = WireInit(Bool(), 0.U)
/////////////////////////////////////////////////////////
// Misprediction packet
val exu_mp_valid = io.exu_mp_pkt.misp & !leak_one_f
val exu_mp_boffset = io.exu_mp_pkt.boffset val exu_mp_boffset = io.exu_mp_pkt.boffset
val exu_mp_pc4 = io.exu_mp_pkt.pc4 val exu_mp_pc4 = io.exu_mp_pkt.pc4
val exu_mp_call = io.exu_mp_pkt.pcall val exu_mp_call = io.exu_mp_pkt.pcall
@ -78,7 +77,7 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val exu_mp_addr = io.exu_mp_index val exu_mp_addr = io.exu_mp_index
val exu_mp_ataken = io.exu_mp_pkt.ataken val exu_mp_ataken = io.exu_mp_pkt.ataken
// LM: Its a commit or update packet // Its a commit or update packet
val dec_tlu_br0_v_wb = io.dec_tlu_br0_r_pkt.valid val dec_tlu_br0_v_wb = io.dec_tlu_br0_r_pkt.valid
val dec_tlu_br0_hist_wb = io.dec_tlu_br0_r_pkt.hist val dec_tlu_br0_hist_wb = io.dec_tlu_br0_r_pkt.hist
val dec_tlu_br0_addr_wb = io.exu_i0_br_index_r val dec_tlu_br0_addr_wb = io.exu_i0_br_index_r
@ -88,20 +87,6 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val dec_tlu_br0_start_error_wb = io.dec_tlu_br0_r_pkt.br_start_error val dec_tlu_br0_start_error_wb = io.dec_tlu_br0_r_pkt.br_start_error
val exu_i0_br_fghr_wb = io.exu_i0_br_fghr_r val exu_i0_br_fghr_wb = io.exu_i0_br_fghr_r
//val fetch_rd_tag_p1_f = WireInit(UInt(BTB_BTAG_SIZE.W), 0.U)
//val fetch_rd_tag_f = WireInit(UInt(BTB_BTAG_SIZE.W), 0.U)
val bht_dir_f = WireInit(UInt(2.W), 0.U)
val dec_tlu_error_wb = WireInit(Bool(), 0.U)
val btb_error_addr_wb = WireInit(UInt((BTB_ADDR_HI-BTB_ADDR_LO).W), 0.U)
val btb_bank0_rd_data_way0_f = WireInit(UInt((TAG_START+1).W), 0.U)
val btb_bank0_rd_data_way1_f = WireInit(UInt((TAG_START+1).W), 0.U)
val btb_bank0_rd_data_way0_p1_f = WireInit(UInt((TAG_START+1).W), 0.U)
val btb_bank0_rd_data_way1_p1_f = WireInit(UInt((TAG_START+1).W), 0.U)
val eoc_mask = WireInit(Bool(), 0.U)
val btb_lru_b0_f = WireInit(UInt(LRU_SIZE.W), init = 0.U)
val dec_tlu_way_wb = WireInit(Bool(), 0.U)
// Hash the first PC // Hash the first PC
val btb_rd_addr_f = el2_btb_addr_hash(io.ifc_fetch_addr_f) val btb_rd_addr_f = el2_btb_addr_hash(io.ifc_fetch_addr_f)
// Second pc = pc +4 // Second pc = pc +4
@ -113,7 +98,7 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val btb_sel_f = Cat(~bht_dir_f(0),bht_dir_f(0)) val btb_sel_f = Cat(~bht_dir_f(0),bht_dir_f(0))
// Checking of the pc is a multiple of 4, if it is fetch-start will be "01" // Checking of the pc is a multiple of 4, if it is fetch-start will be "01"
val fetch_start_f = Cat(io.ifc_fetch_addr_f(1),~io.ifc_fetch_addr_f(1)) val fetch_start_f = Cat(io.ifc_fetch_addr_f(0),~io.ifc_fetch_addr_f(0))
// If there is an error write-back from the dec check if the current pc is equal to the write-bcak pc // If there is an error write-back from the dec check if the current pc is equal to the write-bcak pc
val branch_error_collision_f = dec_tlu_error_wb & (btb_error_addr_wb === btb_rd_addr_f) val branch_error_collision_f = dec_tlu_error_wb & (btb_error_addr_wb === btb_rd_addr_f)
@ -138,30 +123,30 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
// For a tag to match the branch should be valid tag should match and a fetch request should be generated // For a tag to match the branch should be valid tag should match and a fetch request should be generated
val tag_match_way0_f = btb_bank0_rd_data_way0_f(BV) & (btb_bank0_rd_data_way0_f(TAG_START,17) === fetch_rd_tag_f) & val tag_match_way0_f = btb_bank0_rd_data_way0_f(BV) & (btb_bank0_rd_data_way0_f(TAG_START,17) === fetch_rd_tag_f) &
~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f !(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & !leak_one_f
val tag_match_way1_f = btb_bank0_rd_data_way1_f(BV) & (btb_bank0_rd_data_way1_f(TAG_START,17) === fetch_rd_tag_f) & val tag_match_way1_f = btb_bank0_rd_data_way1_f(BV) & (btb_bank0_rd_data_way1_f(TAG_START,17) === fetch_rd_tag_f) &
~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f !(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & !leak_one_f
val tag_match_way0_p1_f = btb_bank0_rd_data_way0_p1_f(BV) & (btb_bank0_rd_data_way0_p1_f(TAG_START,17) === fetch_rd_tag_p1_f) & val tag_match_way0_p1_f = btb_bank0_rd_data_way0_p1_f(BV) & (btb_bank0_rd_data_way0_p1_f(TAG_START,17) === fetch_rd_tag_p1_f) &
~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f !(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & !leak_one_f
val tag_match_way1_p1_f = btb_bank0_rd_data_way1_p1_f(BV) & (btb_bank0_rd_data_way1_p1_f(TAG_START,17) === fetch_rd_tag_p1_f) & val tag_match_way1_p1_f = btb_bank0_rd_data_way1_p1_f(BV) & (btb_bank0_rd_data_way1_p1_f(TAG_START,17) === fetch_rd_tag_p1_f) &
~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & ~leak_one_f !(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & io.ifc_fetch_req_f & !leak_one_f
// Reordering to avoid multiple hit // Reordering to avoid multiple hit
val tag_match_way0_expanded_f = Cat(tag_match_way0_f & (btb_bank0_rd_data_way0_f(BOFF) ^ btb_bank0_rd_data_way0_f(PC4)), val tag_match_way0_expanded_f = Cat(tag_match_way0_f & (btb_bank0_rd_data_way0_f(BOFF) ^ btb_bank0_rd_data_way0_f(PC4)),
tag_match_way0_f & ~(btb_bank0_rd_data_way0_f(BOFF) ^ btb_bank0_rd_data_way0_f(PC4))) tag_match_way0_f & !(btb_bank0_rd_data_way0_f(BOFF) ^ btb_bank0_rd_data_way0_f(PC4)))
val tag_match_way1_expanded_f = Cat(tag_match_way1_f & (btb_bank0_rd_data_way1_f(BOFF) ^ btb_bank0_rd_data_way1_f(PC4)), val tag_match_way1_expanded_f = Cat(tag_match_way1_f & (btb_bank0_rd_data_way1_f(BOFF) ^ btb_bank0_rd_data_way1_f(PC4)),
tag_match_way1_f & ~(btb_bank0_rd_data_way1_f(BOFF) ^ btb_bank0_rd_data_way1_f(PC4))) tag_match_way1_f & !(btb_bank0_rd_data_way1_f(BOFF) ^ btb_bank0_rd_data_way1_f(PC4)))
val tag_match_way0_expanded_p1_f = Cat(tag_match_way0_p1_f & (btb_bank0_rd_data_way0_p1_f(BOFF) ^ btb_bank0_rd_data_way0_p1_f(PC4)), val tag_match_way0_expanded_p1_f = Cat(tag_match_way0_p1_f & (btb_bank0_rd_data_way0_p1_f(BOFF) ^ btb_bank0_rd_data_way0_p1_f(PC4)),
tag_match_way0_p1_f & ~(btb_bank0_rd_data_way0_p1_f(BOFF) ^ btb_bank0_rd_data_way0_p1_f(PC4))) tag_match_way0_p1_f & !(btb_bank0_rd_data_way0_p1_f(BOFF) ^ btb_bank0_rd_data_way0_p1_f(PC4)))
val tag_match_way1_expanded_p1_f = Cat(tag_match_way1_p1_f & (btb_bank0_rd_data_way1_p1_f(BOFF) ^ btb_bank0_rd_data_way1_p1_f(PC4)), val tag_match_way1_expanded_p1_f = Cat(tag_match_way1_p1_f & (btb_bank0_rd_data_way1_p1_f(BOFF) ^ btb_bank0_rd_data_way1_p1_f(PC4)),
tag_match_way1_p1_f & ~(btb_bank0_rd_data_way1_p1_f(BOFF) ^ btb_bank0_rd_data_way1_p1_f(PC4))) tag_match_way1_p1_f & !(btb_bank0_rd_data_way1_p1_f(BOFF) ^ btb_bank0_rd_data_way1_p1_f(PC4)))
val wayhit_f = tag_match_way0_expanded_f | tag_match_way1_expanded_f val wayhit_f = tag_match_way0_expanded_f | tag_match_way1_expanded_f
@ -178,26 +163,30 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
tag_match_way1_expanded_p1_f(1).asBool->btb_bank0_rd_data_way1_p1_f)) tag_match_way1_expanded_p1_f(1).asBool->btb_bank0_rd_data_way1_p1_f))
// Making virtual banks, made bit 1 of the pc to check // Making virtual banks, made bit 1 of the pc to check
val btb_vbank0_rd_data_f = Mux1H(Seq(~io.ifc_fetch_addr_f(1)->btb_bank0e_rd_data_f, val btb_vbank0_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(1)->btb_bank0e_rd_data_f,
io.ifc_fetch_addr_f(1)->btb_bank0o_rd_data_f)) io.ifc_fetch_addr_f(1)->btb_bank0o_rd_data_f))
val btb_vbank1_rd_data_f = Mux1H(Seq(~io.ifc_fetch_addr_f(1)->btb_bank0o_rd_data_f, val btb_vbank1_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(1)->btb_bank0o_rd_data_f,
io.ifc_fetch_addr_f(1)->btb_bank0e_rd_data_p1_f)) io.ifc_fetch_addr_f(1)->btb_bank0e_rd_data_p1_f))
// Implimenting the LRU for a 2-way BTB // Implimenting the LRU for a 2-way BTB
val mp_wrindex_dec = 1.U(LRU_SIZE) << exu_mp_addr val mp_wrindex_dec = 1.U(LRU_SIZE) << exu_mp_addr
val fetch_wrindex_dec = 1.U(LRU_SIZE) << btb_rd_addr_f val fetch_wrindex_dec = 1.U(LRU_SIZE) << btb_rd_addr_f
val fetch_wrindex_p1_dec = 1.U(LRU_SIZE) << btb_rd_addr_p1_f val fetch_wrindex_p1_dec = 1.U(LRU_SIZE) << btb_rd_addr_p1_f
val mp_wrlru_b0 = mp_wrindex_dec & Fill(LRU_SIZE, exu_mp_valid) val mp_wrlru_b0 = mp_wrindex_dec & Fill(LRU_SIZE, exu_mp_valid)
val vwayhit_f = Mux1H(Seq(~io.ifc_fetch_addr_f(1).asBool->wayhit_f, val vwayhit_f = Mux1H(Seq(~io.ifc_fetch_addr_f(0).asBool->wayhit_f,
io.ifc_fetch_addr_f(1).asBool->Cat(wayhit_p1_f(0), wayhit_f(1)))) & Cat(eoc_mask, 1.U(1.W)) io.ifc_fetch_addr_f(0).asBool->Cat(wayhit_p1_f(0), wayhit_f(1)))) & Cat(eoc_mask, 1.U(1.W))
val lru_update_valid_f = (vwayhit_f(0) | vwayhit_f(1)) & io.ifc_fetch_req_f & ~leak_one_f
val lru_update_valid_f = (vwayhit_f(0) | vwayhit_f(1)) & io.ifc_fetch_req_f & !leak_one_f
val fetch_wrlru_b0 = fetch_wrindex_dec & Fill(fetch_wrindex_dec.getWidth, lru_update_valid_f) val fetch_wrlru_b0 = fetch_wrindex_dec & Fill(fetch_wrindex_dec.getWidth, lru_update_valid_f)
val fetch_wrlru_p1_b0 = fetch_wrindex_p1_dec & Fill(fetch_wrindex_dec.getWidth, lru_update_valid_f) val fetch_wrlru_p1_b0 = fetch_wrindex_p1_dec & Fill(fetch_wrindex_dec.getWidth, lru_update_valid_f)
val btb_lru_b0_hold = ~mp_wrlru_b0 & ~fetch_wrlru_b0 val btb_lru_b0_hold = !mp_wrlru_b0 & !fetch_wrlru_b0
val use_mp_way = fetch_mp_collision_f val use_mp_way = fetch_mp_collision_f
val use_mp_way_p1 = fetch_mp_collision_p1_f val use_mp_way_p1 = fetch_mp_collision_p1_f
@ -206,6 +195,7 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
tag_match_way0_p1_f.asBool->fetch_wrlru_p1_b0)) | btb_lru_b0_hold & btb_lru_b0_f tag_match_way0_p1_f.asBool->fetch_wrlru_p1_b0)) | btb_lru_b0_hold & btb_lru_b0_f
val btb_lru_rd_f = Mux(use_mp_way.asBool, exu_mp_way_f, (fetch_wrindex_dec & btb_lru_b0_f).orR) val btb_lru_rd_f = Mux(use_mp_way.asBool, exu_mp_way_f, (fetch_wrindex_dec & btb_lru_b0_f).orR)
val btb_lru_rd_p1_f = Mux(use_mp_way_p1.asBool, exu_mp_way_f, (fetch_wrindex_p1_dec & btb_lru_b0_f).orR) val btb_lru_rd_p1_f = Mux(use_mp_way_p1.asBool, exu_mp_way_f, (fetch_wrindex_p1_dec & btb_lru_b0_f).orR)
val btb_vlru_rd_f = Mux1H(Seq(!io.ifc_fetch_addr_f(1) -> Cat(btb_lru_rd_f, btb_lru_rd_f), val btb_vlru_rd_f = Mux1H(Seq(!io.ifc_fetch_addr_f(1) -> Cat(btb_lru_rd_f, btb_lru_rd_f),
@ -214,12 +204,14 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val tag_match_vway1_expanded_f = Mux1H(Seq(~io.ifc_fetch_addr_f(1).asBool->tag_match_way1_expanded_f, val tag_match_vway1_expanded_f = Mux1H(Seq(~io.ifc_fetch_addr_f(1).asBool->tag_match_way1_expanded_f,
io.ifc_fetch_addr_f(1).asBool->Cat(tag_match_way1_expanded_p1_f(0),tag_match_way1_expanded_f(1)))) io.ifc_fetch_addr_f(1).asBool->Cat(tag_match_way1_expanded_p1_f(0),tag_match_way1_expanded_f(1))))
val way_raw = tag_match_vway1_expanded_f | (~vwayhit_f & btb_vlru_rd_f) val way_raw = tag_match_vway1_expanded_f | (!vwayhit_f & btb_vlru_rd_f)
btb_lru_b0_f := RegEnable(btb_lru_b0_ns, init = 0.U, (io.ifc_fetch_req_f|exu_mp_valid).asBool) btb_lru_b0_f := RegEnable(btb_lru_b0_ns, init = 0.U, (io.ifc_fetch_req_f|exu_mp_valid).asBool)
val eoc_near = io.ifc_fetch_addr_f(ICACHE_BEAT_ADDR_HI, 3).andR val eoc_near = io.ifc_fetch_addr_f(ICACHE_BEAT_ADDR_HI, 3).andR
eoc_mask := !eoc_near | !io.ifc_fetch_addr_f(2,1).orR()
eoc_mask := !eoc_near | (!io.ifc_fetch_addr_f(1,0).orR())
val btb_sel_data_f = WireInit(UInt(17.W), init = 0.U) val btb_sel_data_f = WireInit(UInt(17.W), init = 0.U)
val hist1_raw = WireInit(UInt(2.W), init = 0.U) val hist1_raw = WireInit(UInt(2.W), init = 0.U)
val btb_rd_tgt_f = btb_sel_data_f(16,5) val btb_rd_tgt_f = btb_sel_data_f(16,5)
@ -227,10 +219,10 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val btb_rd_call_f = btb_sel_data_f(2) val btb_rd_call_f = btb_sel_data_f(2)
val btb_rd_ret_f = btb_sel_data_f(1) val btb_rd_ret_f = btb_sel_data_f(1)
btb_sel_data_f := Mux1H(Seq(btb_sel_f(1).asBool->Cat(btb_vbank1_rd_data_f(16,1),0.U), btb_sel_data_f := Mux1H(Seq(btb_sel_f(1).asBool-> btb_vbank1_rd_data_f(16,1),
btb_sel_f(0).asBool->Cat(btb_vbank1_rd_data_f(16,1),0.U))) btb_sel_f(0).asBool-> btb_vbank1_rd_data_f(16,1)))
val ifu_bp_hit_taken_f = (vwayhit_f & hist1_raw).orR & io.ifc_fetch_req_f & ~leak_one_f_d1 & ~io.dec_tlu_bpred_disable io.ifu_bp_hit_taken_f := (vwayhit_f & hist1_raw).orR & io.ifc_fetch_req_f & !leak_one_f_d1 & !io.dec_tlu_bpred_disable
val bht_force_taken_f = Cat( btb_vbank1_rd_data_f(CALL) | btb_vbank1_rd_data_f(RET) , val bht_force_taken_f = Cat( btb_vbank1_rd_data_f(CALL) | btb_vbank1_rd_data_f(RET) ,
btb_vbank0_rd_data_f(CALL) | btb_vbank0_rd_data_f(RET)) btb_vbank0_rd_data_f(CALL) | btb_vbank0_rd_data_f(RET))
@ -241,15 +233,16 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val bht_bank0_rd_data_f =WireInit(UInt(2.W), 0.U) val bht_bank0_rd_data_f =WireInit(UInt(2.W), 0.U)
val bht_bank0_rd_data_p1_f =WireInit(UInt(2.W), 0.U) val bht_bank0_rd_data_p1_f =WireInit(UInt(2.W), 0.U)
val bht_vbank0_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(1).asBool->bht_bank0_rd_data_f, val bht_vbank0_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0).asBool->bht_bank0_rd_data_f,
io.ifc_fetch_addr_f(1).asBool->bht_bank1_rd_data_f)) io.ifc_fetch_addr_f(0).asBool->bht_bank1_rd_data_f))
val bht_vbank1_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(0).asBool->bht_bank1_rd_data_f,
io.ifc_fetch_addr_f(0).asBool->bht_bank0_rd_data_p1_f))
val bht_vbank1_rd_data_f = Mux1H(Seq(!io.ifc_fetch_addr_f(1).asBool->bht_bank1_rd_data_f,
io.ifc_fetch_addr_f(1).asBool->bht_bank0_rd_data_p1_f))
bht_dir_f := Cat((bht_force_taken_f(1) | bht_vbank1_rd_data_f(1)) & bht_valid_f(1), bht_dir_f := Cat((bht_force_taken_f(1) | bht_vbank1_rd_data_f(1)) & bht_valid_f(1),
(bht_force_taken_f(0) | bht_vbank0_rd_data_f(1)) & bht_valid_f(0)) (bht_force_taken_f(0) | bht_vbank0_rd_data_f(1)) & bht_valid_f(0))
val ifu_bp_inst_mask_f = (ifu_bp_hit_taken_f & btb_sel_f(1)) | ~ifu_bp_hit_taken_f io.ifu_bp_inst_mask_f := (io.ifu_bp_hit_taken_f & btb_sel_f(1)) | !io.ifu_bp_hit_taken_f
// Bank explination // Bank explination
hist1_raw := bht_force_taken_f | Cat(bht_vbank1_rd_data_f(1), bht_vbank0_rd_data_f(1)) hist1_raw := bht_force_taken_f | Cat(bht_vbank1_rd_data_f(1), bht_vbank0_rd_data_f(1))
@ -259,15 +252,16 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val pc4_raw = Cat(vwayhit_f(1) & btb_vbank1_rd_data_f(PC4), val pc4_raw = Cat(vwayhit_f(1) & btb_vbank1_rd_data_f(PC4),
vwayhit_f(0) & btb_vbank0_rd_data_f(PC4)) vwayhit_f(0) & btb_vbank0_rd_data_f(PC4))
val pret_raw = Cat(vwayhit_f(1) & ~btb_vbank1_rd_data_f(CALL) & btb_vbank1_rd_data_f(RET), val pret_raw = Cat(vwayhit_f(1) & !btb_vbank1_rd_data_f(CALL) & btb_vbank1_rd_data_f(RET),
vwayhit_f(0) & ~btb_vbank0_rd_data_f(CALL) & btb_vbank0_rd_data_f(RET)) vwayhit_f(0) & !btb_vbank0_rd_data_f(CALL) & btb_vbank0_rd_data_f(RET))
//GHR //GHR
val num_valids = bht_valid_f(1) +& bht_valid_f(0) val num_valids = bht_valid_f(1) +& bht_valid_f(0) // countones
val final_h = (btb_sel_f & bht_dir_f).andR val final_h = (btb_sel_f & bht_dir_f).andR
val fghr = WireInit(UInt(BHT_GHR_SIZE.W), 0.U) val fghr = WireInit(UInt(BHT_GHR_SIZE.W), 0.U)
val merged_ghr = Mux1H(Seq((num_valids===2.U).asBool->Cat(fghr(BHT_GHR_SIZE-3,0), 0.U, final_h), val merged_ghr = Mux1H(Seq((num_valids===2.U).asBool->Cat(fghr(BHT_GHR_SIZE-3,0), 0.U, final_h),
(num_valids===1.U).asBool->Cat(fghr(BHT_GHR_SIZE-2,0), final_h), (num_valids===1.U).asBool->Cat(fghr(BHT_GHR_SIZE-2,0), final_h),
(num_valids===0.U).asBool->Cat(fghr(BHT_GHR_SIZE-1,0)))) (num_valids===0.U).asBool->Cat(fghr(BHT_GHR_SIZE-1,0))))
@ -275,10 +269,11 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val exu_flush_ghr = io.exu_mp_fghr val exu_flush_ghr = io.exu_mp_fghr
val fghr_ns = Mux1H(Seq(exu_flush_final_d1.asBool->exu_flush_ghr, val fghr_ns = Mux1H(Seq(exu_flush_final_d1.asBool->exu_flush_ghr,
(~exu_flush_final_d1 & io.ifc_fetch_req_f & io.ic_hit_f & ~leak_one_f_d1).asBool -> merged_ghr, (!exu_flush_final_d1 & io.ifc_fetch_req_f & io.ic_hit_f & !leak_one_f_d1).asBool -> merged_ghr,
(~exu_flush_final_d1 & ~(io.ifc_fetch_req_f & io.ic_hit_f & ~leak_one_f_d1)).asBool -> fghr)) (!exu_flush_final_d1 & !(io.ifc_fetch_req_f & io.ic_hit_f & !leak_one_f_d1)).asBool -> fghr))
fghr := RegNext(fghr_ns, init = 0.U) fghr := RegNext(fghr_ns, init = 0.U)
io.ifu_bp_fghr_f := fghr io.ifu_bp_fghr_f := fghr
io.ifu_bp_way_f := way_raw io.ifu_bp_way_f := way_raw
@ -297,34 +292,37 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val btb_fg_crossing_f = fetch_start_f(0) & btb_sel_f(0) & btb_rd_pc4_f val btb_fg_crossing_f = fetch_start_f(0) & btb_sel_f(0) & btb_rd_pc4_f
val bp_total_branch_offset_f = bloc_f(1)^btb_rd_pc4_f val bp_total_branch_offset_f = bloc_f(1)^btb_rd_pc4_f
val ifc_fetch_adder_prior = RegEnable(io.ifc_fetch_addr_f, 0.U, (io.ifc_fetch_req_f & ~ifu_bp_hit_taken_f & io.ic_hit_f).asBool) val ifc_fetch_adder_prior = RegEnable(io.ifc_fetch_addr_f, 0.U, (io.ifc_fetch_req_f & !io.ifu_bp_hit_taken_f & io.ic_hit_f).asBool)
val ifu_bp_poffset_f = btb_rd_tgt_f io.ifu_bp_poffset_f := btb_rd_tgt_f
val adder_pc_in_f = Mux1H(Seq(use_fa_plus.asBool->fetch_addr_p1_f, val adder_pc_in_f = Mux1H(Seq(use_fa_plus.asBool->fetch_addr_p1_f,
btb_fg_crossing_f.asBool->ifc_fetch_adder_prior, btb_fg_crossing_f.asBool->ifc_fetch_adder_prior,
(!btb_fg_crossing_f & !use_fa_plus).asBool->io.ifc_fetch_addr_f(31,2))) (!btb_fg_crossing_f & !use_fa_plus).asBool->io.ifc_fetch_addr_f(30,1)))
val bp_btb_target_adder_f = rvbradder(Cat(adder_pc_in_f(29,0),bp_total_branch_offset_f, 0.U), Cat(btb_rd_tgt_f,0.U))
val bp_btb_target_adder_f = rvbradder(Cat(adder_pc_in_f(31,2),bp_total_branch_offset_f, 0.U), Cat(btb_rd_tgt_f,0.U))
val rets_out = Wire(Vec(RET_STACK_SIZE, UInt(32.W))) val rets_out = Wire(Vec(RET_STACK_SIZE, UInt(32.W)))
rets_out := (0 until RET_STACK_SIZE).map(i=>0.U) rets_out := (0 until RET_STACK_SIZE).map(i=>0.U)
//io.test := bp_btb_target_adder_f io.ifu_bp_btb_target_f := Mux((btb_rd_ret_f & !btb_rd_call_f & rets_out(0)(0)).asBool,
io.ifu_bp_btb_target_f := Mux((btb_rd_ret_f & ~btb_rd_call_f & rets_out(0)(0)).asBool,
rets_out(0)(31,1),bp_btb_target_adder_f(31,1)) rets_out(0)(31,1),bp_btb_target_adder_f(31,1))
// Return stack // Return stack
val bp_rs_call_target_f = rvbradder(Cat(adder_pc_in_f(31,2),bp_total_branch_offset_f, 0.U), Cat(Fill(11, 0.U),~btb_rd_pc4_f, 0.U)) val bp_rs_call_target_f = rvbradder(Cat(adder_pc_in_f(29,0),bp_total_branch_offset_f, 0.U), Cat(Fill(11, 0.U),~btb_rd_pc4_f, 0.U))
val rs_push = btb_rd_call_f & ~btb_rd_ret_f & ifu_bp_hit_taken_f val rs_push = btb_rd_call_f & !btb_rd_ret_f & io.ifu_bp_hit_taken_f
val rs_pop = btb_rd_ret_f & ~btb_rd_call_f & ifu_bp_hit_taken_f val rs_pop = btb_rd_ret_f & !btb_rd_call_f & io.ifu_bp_hit_taken_f
val rs_hold = ~rs_push & ~rs_pop val rs_hold = !rs_push & !rs_pop
val rsenable = (0 until RET_STACK_SIZE).map(i=> if(i==0) !rs_hold else if(i==RET_STACK_SIZE-1) rs_push else rs_push | rs_pop) val rsenable = (0 until RET_STACK_SIZE).map(i=> if(i==0) !rs_hold else if(i==RET_STACK_SIZE-1) rs_push else rs_push | rs_pop)
val rets_in = (0 until RET_STACK_SIZE).map(i=> if(i==0) val rets_in = (0 until RET_STACK_SIZE).map(i=> if(i==0)
Mux1H(Seq(rs_push.asBool -> Cat(bp_rs_call_target_f(31,1),1.U), rs_pop.asBool -> rets_out(1))) Mux1H(Seq(rs_push.asBool -> Cat(bp_rs_call_target_f(31,1),1.U),
rs_pop.asBool -> rets_out(1)))
else if(i==RET_STACK_SIZE-1) rets_out(i-1) else if(i==RET_STACK_SIZE-1) rets_out(i-1)
else Mux1H(Seq(rs_push.asBool->rets_out(i-1), rs_pop.asBool->rets_out(i+1)))) else Mux1H(Seq(rs_push.asBool->rets_out(i-1),
rs_pop.asBool ->rets_out(i+1))))
rets_out := (0 until RET_STACK_SIZE).map(i=>RegEnable(rets_in(i),0.U,rsenable(i).asBool)) rets_out := (0 until RET_STACK_SIZE).map(i=>RegEnable(rets_in(i),0.U,rsenable(i).asBool))
dec_tlu_error_wb := dec_tlu_br0_start_error_wb | dec_tlu_br0_error_wb dec_tlu_error_wb := dec_tlu_br0_start_error_wb | dec_tlu_br0_error_wb
@ -346,10 +344,10 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val bht_wr_data0 = exu_mp_hist val bht_wr_data0 = exu_mp_hist
val bht_wr_data2 = dec_tlu_br0_hist_wb val bht_wr_data2 = dec_tlu_br0_hist_wb
val mp_hashed = el2_btb_ghr_hash(exu_mp_addr, io.exu_mp_eghr) val mp_hashed = el2_btb_ghr_hash(Cat(exu_mp_addr,0.U(2.W)), io.exu_mp_eghr)
val br0_hashed_wb = el2_btb_ghr_hash(dec_tlu_br0_addr_wb, exu_i0_br_fghr_wb) val br0_hashed_wb = el2_btb_ghr_hash(Cat(dec_tlu_br0_addr_wb,0.U(2.W)), exu_i0_br_fghr_wb)
val bht_rd_addr_hashed_f = el2_btb_ghr_hash(btb_rd_addr_f, fghr) val bht_rd_addr_hashed_f = el2_btb_ghr_hash(Cat(btb_rd_addr_f,0.U(2.W)), fghr)
val bht_rd_addr_hashed_p1_f = el2_btb_ghr_hash(btb_rd_addr_p1_f, fghr) val bht_rd_addr_hashed_p1_f = el2_btb_ghr_hash(Cat(btb_rd_addr_p1_f,0.U(2.W)), fghr)
val bht_wr_addr0 = mp_hashed val bht_wr_addr0 = mp_hashed
val bht_wr_addr2 = br0_hashed_wb val bht_wr_addr2 = br0_hashed_wb
@ -362,9 +360,27 @@ class el2_ifu_bp_ctl extends Module with el2_lib {
val btb_bank0_rd_data_way0_out = (0 until LRU_SIZE).map(i=>RegEnable(btb_wr_data,0.U,((btb_wr_addr===i.U) & btb_wr_en_way0).asBool)) val btb_bank0_rd_data_way0_out = (0 until LRU_SIZE).map(i=>RegEnable(btb_wr_data,0.U,((btb_wr_addr===i.U) & btb_wr_en_way0).asBool))
val btb_bank0_rd_data_way1_out = (0 until LRU_SIZE).map(i=>RegEnable(btb_wr_data,0.U,((btb_wr_addr===i.U) & btb_wr_en_way1).asBool)) val btb_bank0_rd_data_way1_out = (0 until LRU_SIZE).map(i=>RegEnable(btb_wr_data,0.U,((btb_wr_addr===i.U) & btb_wr_en_way1).asBool))
// TODO:BTB_rd_mux for normal address btb_bank0_rd_data_way0_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_f===i.U).asBool->btb_bank0_rd_data_way0_out(i)))
btb_bank0_rd_data_way1_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_f===i.U).asBool->btb_bank0_rd_data_way1_out(i)))
// TODO:BTB_rd_mux for p1 address btb_bank0_rd_data_way0_p1_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_p1_f===i.U).asBool->btb_bank0_rd_data_way0_out(i)))
btb_bank0_rd_data_way1_p1_f := Mux1H((0 until LRU_SIZE).map(i=>(btb_rd_addr_p1_f===i.U).asBool->btb_bank0_rd_data_way1_out(i)))
val bht_bank_wr_data = (0 until 2).map(i=>(0 until BHT_ARRAY_DEPTH/NUM_BHT_LOOP).map(k=>(0 until NUM_BHT_LOOP).map(j=>
Mux((bht_wr_en2(i)&(bht_wr_addr2(NUM_BHT_LOOP_INNER_HI-BHT_ADDR_LO,0)===j.asUInt)&(bht_wr_addr2(BHT_ADDR_HI-NUM_BHT_LOOP_OUTER_LO+1,NUM_BHT_LOOP_OUTER_LO-BHT_ADDR_LO)===k.asUInt)|BHT_NO_ADDR_MATCH.B).asBool, bht_wr_data2, bht_wr_data0))))
val bht_bank_sel = (0 until 2).map(i=>(0 until BHT_ARRAY_DEPTH/NUM_BHT_LOOP).map(k=>(0 until NUM_BHT_LOOP).map(j=>
bht_wr_en0(i) & (bht_wr_addr0(NUM_BHT_LOOP_INNER_HI-BHT_ADDR_LO,0)===j.asUInt) & (bht_wr_addr0(BHT_ADDR_HI-NUM_BHT_LOOP_OUTER_LO+1, NUM_BHT_LOOP_OUTER_LO-BHT_ADDR_LO)===k.asUInt) | BHT_NO_ADDR_MATCH.B | bht_wr_en2(i) &
(bht_wr_addr2(NUM_BHT_LOOP_INNER_HI-BHT_ADDR_LO,0)===j.asUInt) & (bht_wr_addr2(BHT_ADDR_HI-NUM_BHT_LOOP_OUTER_LO+1, NUM_BHT_LOOP_OUTER_LO-BHT_ADDR_LO)===k.asUInt) | BHT_NO_ADDR_MATCH.B)))
val bht_bank_rd_data_out = Wire(Vec(2, Vec(BHT_ARRAY_DEPTH, UInt(2.W))))
for(i<-0 until 2; k<-0 until BHT_ARRAY_DEPTH/NUM_BHT_LOOP; j<-0 until NUM_BHT_LOOP){
bht_bank_rd_data_out(i)((16*k)+j) := RegEnable(bht_bank_wr_data(i)(j)(k), 0.U, bht_bank_sel(i)(j)(k))
}
bht_bank0_rd_data_f := Mux1H((0 until BHT_ARRAY_DEPTH).map(i=>(bht_rd_addr_f(BHT_ADDR_HI-BHT_ADDR_LO,0)===i.U).asBool->bht_bank_rd_data_out(0)(i)))
bht_bank1_rd_data_f := Mux1H((0 until BHT_ARRAY_DEPTH).map(i=>(bht_rd_addr_f(BHT_ADDR_HI-BHT_ADDR_LO,0)===i.U).asBool->bht_bank_rd_data_out(1)(i)))
bht_bank0_rd_data_p1_f := Mux1H((0 until BHT_ARRAY_DEPTH).map(i=>(bht_rd_addr_p1_f(BHT_ADDR_HI-BHT_ADDR_LO,0)===i.U).asBool->bht_bank_rd_data_out(1)(i)))
} }

View File

@ -12,6 +12,7 @@ class el2_ifu_compress_ctl extends Module {
def pat(y : List[Int]) = (0 until y.size).map(i=> if(y(i)>=0) io.din(y(i)) else !io.din(y(i).abs)).reduce(_&_) def pat(y : List[Int]) = (0 until y.size).map(i=> if(y(i)>=0) io.din(y(i)) else !io.din(y(i).abs)).reduce(_&_)
val out = Wire(Vec(32, UInt(1.W))) val out = Wire(Vec(32, UInt(1.W)))
out := (0 until 32).map(i=> 0.U.asBool) out := (0 until 32).map(i=> 0.U.asBool)
out(30) := pat(List(15, -14, -13, 10, -6, -5, 0)) | pat(List(15, -14, -13, -11, 10, 0)) out(30) := pat(List(15, -14, -13, 10, -6, -5, 0)) | pat(List(15, -14, -13, -11, 10, 0))
out(20) := pat(List(-14, 12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, 1)) out(20) := pat(List(-14, 12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, 1))
out(14) := pat(List(15, -14, -13, -11, 0)) | pat(List(15, -14, -13, -10, 0)) | pat(List(15, -14, -13, 6, 0)) | out(14) := pat(List(15, -14, -13, -11, 0)) | pat(List(15, -14, -13, -10, 0)) | pat(List(15, -14, -13, 6, 0)) |