* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: rz3iu.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
* rz3 instr unit data structures
// #include "spix_sparc.h"
#include "rz_insttypes.h"
/* we use a simple fast branch predictor similar to the one on cheetah
* the bpa is a 4k array of 2-bit up/down saturating counters
* the bpa is indexed by a combination of the branch PC and global branch history
bpa
= new uint8_t [1<<14];
update_nottaken
[i
] = i
-1;
// up-down counters saturate at strongly taken/not-taken
enum brpred_feedback_e
{ bp_feedback_INV
=0, bp_no_feedback
, bp_feedback_hit
, bp_feedback_miss
};
// there are two operating modes of the predictor:
// 1. we know the actual outcome of the branch. generate a prediction and return the *accuracy* of the prediction
// 2. we know the *accuracy* of the prediction. generate the prediction and return the *actual outcome* of the branch
int pred_hit(uint64_t pc
, int actual_outcome
)
int index
= (int) (((pc
>>2) & 0x3fff) ^ (bhr
<< 2));
uint8_t countervalue
= bpa
[index
];
int pred
= (countervalue
>> 1);
bpa
[index
] = actual_outcome
? update_taken
[countervalue
] : update_nottaken
[countervalue
];
return (pred
== actual_outcome
);
int actual_outcome(uint64_t pc
, int pred_hit
)
int index
= (int) (((pc
>>2) & 0x3fff) ^ (bhr
<< 2));
uint8_t countervalue
= bpa
[index
];
int pred
= (countervalue
>> 1);
int actual_outcome
= (pred
== pred_hit
);
bpa
[index
] = actual_outcome
? update_taken
[countervalue
] : update_nottaken
[countervalue
];
uint16_t bhr
; // 12-bit branch history
uint8_t update_nottaken
[4];
}; // struct rz3iu_brpred
unsigned isubranch_nottaken
: 1;
unsigned isindirect
: 1; // jmpl
unsigned is_done_retry
: 1;
// union dcti_info_u gen_dcti_info(uint32_t instr, spix_sparc_iop_t iop);
union dcti_info_u
gen_dcti_info(uint32_t instr
);
union dcti_info_u
gen_dcti_info_v317(uint32_t instr
);
/* instructions that we emulate to regenerate value records:
* AND, OR, ANDCC, ORCC, XOR
* SRLX, SLLX, SRA, SLL, SRA
/* icache with predecode information for DCTIs */
struct rz3iu_icache_data
{
void gen_target(uint64_t pc
);
}; // struct rz3iu_icache_data
static const int rz3iu_icache_bshift
= 0; // 8-instr block
static const uint64_t rz3iu_icache_bsize
= 1<<rz3iu_icache_bshift
;
static const uint64_t rz3iu_icache_size
= 256<<10;
static const uint64_t rz3iu_icache_sets
= rz3iu_icache_size
>> 1+rz3iu_icache_bshift
; // 2-way set-assoc
static const uint64_t rz3iu_icache_blocks
= rz3iu_icache_size
>> rz3iu_icache_bshift
;
rz3iu_icache_data
* data
;
tags
= new uint64_t [rz3iu_icache_blocks
];
data
= new rz3iu_icache_data
[rz3iu_icache_size
];
lru
= new uint8_t [rz3iu_icache_sets
];
memset(tags
, 0, rz3iu_icache_blocks
*sizeof(uint64_t));
memset(data
, 0, rz3iu_icache_size
* sizeof(rz3iu_icache_data
));
memset(lru
, 0, rz3iu_icache_sets
* sizeof(uint8_t));
rz3iu_icache_data
* set(uint64_t pc
, uint32_t instr
, uint8_t rz3_major_version
, uint8_t rz3_minor_version
) {
tag_idx_ofs(pc
, tag
, idx
, offset
);
} else if (tags
[idx
+rz3iu_icache_sets
] == tag
) {
int w
= idx
+ (lruway
? rz3iu_icache_sets
: 0);
int loc
= (w
<< rz3iu_icache_bshift
) | offset
;
rz3iu_icache_data
* icdata
= &(data
[loc
]);
// icdata->iop = spix_sparc_iop(SPIX_SPARC_V9, &(instr));
// icdata->dinfo = gen_dcti_info(instr, icdata->iop);
if (rz3_minor_version
> 17) {
icdata
->dinfo
= gen_dcti_info(instr
);
icdata
->dinfo
= gen_dcti_info_v317(instr
);
icdata
->target
= 0x0; // target of cti inst
if (!icdata
->dinfo
.flags
.isdcti
&& ! icdata
->dinfo
.flags
.is_done_retry
) {
// icdata->is_ldstpf = (spix_sparc_iop_isload(icdata->iop) || spix_sparc_iop_isustore(icdata->iop) || spix_sparc_iop_iscstore(icdata->iop) || (icdata->iop == SPIX_SPARC_IOP_PREFETCH));
icdata
->is_ldstpf
= rz_is_ldstpf(instr
);
icdata
->is_ldstpf
= false;
struct rz3iu_icache_data
* get(uint64_t pc
) {
tag_idx_ofs(pc
, tag
, idx
, offset
);
int loc
= (idx
<< rz3iu_icache_bshift
);
} else if (tags
[idx
+rz3iu_icache_sets
] == tag
) {
int loc
= (idx
+rz3iu_icache_sets
) << rz3iu_icache_bshift
;
void tag_idx_ofs(uint64_t pc
, uint64_t & tag
, int & idx
, int & ofs
)
tag
= (pc
>> (2+rz3iu_icache_bshift
));
idx
= (int) (tag
& (rz3iu_icache_sets
- 1));
ofs
= (pc
>> 2) & (rz3iu_icache_bsize
- 1);
}; // struct rz3iu_icache
enum consts_e
{ ras_sz
= 16 };
int idx
= (top
+1) % ras_sz
;