cpu: Generalize how register files are serialized.
Instead of explicitly serializing each type of register explicitly, and using custom types, etc, store them as generic blocks of data. This lets us get rid of the final use of TheISA::VecRegContainer and TheISA::VecPredRegContainer. Change-Id: I61dbd7825ffe35c41e1b7c8317590d06c21b4513 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/50252 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Gabe Black <gabe.black@gmail.com>
This commit is contained in:
@@ -92,7 +92,7 @@ board.set_se_binary_workload(
|
||||
# Getting the pre-taken checkpoint from gem5-resources. This checkpoint
|
||||
# was taken from running this gem5 configuration script,
|
||||
# configs/example/gem5_library/checkpoints/riscv-hello-save-checkpoint.py
|
||||
checkpoint_resource = Resource("riscv-hello-example-checkpoint")
|
||||
checkpoint_resource = Resource("riscv-hello-example-checkpoint-v22-1")
|
||||
|
||||
# Now we restore the checkpoint by passing the path to the checkpoint to
|
||||
# the Simulator object. The checkpoint_path could be a string containing
|
||||
|
||||
@@ -210,43 +210,24 @@ ThreadContext::setRegFlat(const RegId ®, RegVal val)
|
||||
void
|
||||
serialize(const ThreadContext &tc, CheckpointOut &cp)
|
||||
{
|
||||
// Cast away the const so we can get the non-const ISA ptr, which we then
|
||||
// use to get the const register classes.
|
||||
auto &nc_tc = const_cast<ThreadContext &>(tc);
|
||||
const auto ®Classes = nc_tc.getIsaPtr()->regClasses();
|
||||
for (const auto *reg_class: tc.getIsaPtr()->regClasses()) {
|
||||
// MiscRegs are serialized elsewhere.
|
||||
if (reg_class->type() == MiscRegClass)
|
||||
continue;
|
||||
|
||||
const size_t numFloats = regClasses.at(FloatRegClass)->numRegs();
|
||||
RegVal floatRegs[numFloats];
|
||||
for (auto &id: *regClasses.at(FloatRegClass))
|
||||
floatRegs[id.index()] = tc.getRegFlat(id);
|
||||
// This is a bit ugly, but needed to maintain backwards
|
||||
// compatibility.
|
||||
arrayParamOut(cp, "floatRegs.i", floatRegs, numFloats);
|
||||
const size_t reg_bytes = reg_class->regBytes();
|
||||
const size_t reg_count = reg_class->numRegs();
|
||||
const size_t array_bytes = reg_bytes * reg_count;
|
||||
|
||||
const size_t numVecs = regClasses.at(VecRegClass)->numRegs();
|
||||
std::vector<TheISA::VecRegContainer> vecRegs(numVecs);
|
||||
for (auto &id: *regClasses.at(VecRegClass))
|
||||
tc.getRegFlat(id, &vecRegs[id.index()]);
|
||||
SERIALIZE_CONTAINER(vecRegs);
|
||||
uint8_t regs[array_bytes];
|
||||
auto *reg_ptr = regs;
|
||||
for (const auto &id: *reg_class) {
|
||||
tc.getRegFlat(id, reg_ptr);
|
||||
reg_ptr += reg_bytes;
|
||||
}
|
||||
|
||||
const size_t numPreds = regClasses.at(VecPredRegClass)->numRegs();
|
||||
std::vector<TheISA::VecPredRegContainer> vecPredRegs(numPreds);
|
||||
for (auto &id: *regClasses.at(VecPredRegClass))
|
||||
tc.getRegFlat(id, &vecPredRegs[id.index()]);
|
||||
SERIALIZE_CONTAINER(vecPredRegs);
|
||||
|
||||
const size_t numInts = regClasses.at(IntRegClass)->numRegs();
|
||||
RegVal intRegs[numInts];
|
||||
for (auto &id: *regClasses.at(IntRegClass))
|
||||
intRegs[id.index()] = tc.getRegFlat(id);
|
||||
SERIALIZE_ARRAY(intRegs, numInts);
|
||||
|
||||
const size_t numCcs = regClasses.at(CCRegClass)->numRegs();
|
||||
if (numCcs) {
|
||||
RegVal ccRegs[numCcs];
|
||||
for (auto &id: *regClasses.at(CCRegClass))
|
||||
ccRegs[id.index()] = tc.getRegFlat(id);
|
||||
SERIALIZE_ARRAY(ccRegs, numCcs);
|
||||
arrayParamOut(cp, std::string("regs.") + reg_class->name(), regs,
|
||||
array_bytes);
|
||||
}
|
||||
|
||||
tc.pcState().serialize(cp);
|
||||
@@ -257,40 +238,24 @@ serialize(const ThreadContext &tc, CheckpointOut &cp)
|
||||
void
|
||||
unserialize(ThreadContext &tc, CheckpointIn &cp)
|
||||
{
|
||||
const auto ®Classes = tc.getIsaPtr()->regClasses();
|
||||
for (const auto *reg_class: tc.getIsaPtr()->regClasses()) {
|
||||
// MiscRegs are serialized elsewhere.
|
||||
if (reg_class->type() == MiscRegClass)
|
||||
continue;
|
||||
|
||||
const size_t numFloats = regClasses.at(FloatRegClass)->numRegs();
|
||||
RegVal floatRegs[numFloats];
|
||||
// This is a bit ugly, but needed to maintain backwards
|
||||
// compatibility.
|
||||
arrayParamIn(cp, "floatRegs.i", floatRegs, numFloats);
|
||||
for (auto &id: *regClasses.at(FloatRegClass))
|
||||
tc.setRegFlat(id, floatRegs[id.index()]);
|
||||
const size_t reg_bytes = reg_class->regBytes();
|
||||
const size_t reg_count = reg_class->numRegs();
|
||||
const size_t array_bytes = reg_bytes * reg_count;
|
||||
|
||||
const size_t numVecs = regClasses.at(VecRegClass)->numRegs();
|
||||
std::vector<TheISA::VecRegContainer> vecRegs(numVecs);
|
||||
UNSERIALIZE_CONTAINER(vecRegs);
|
||||
for (auto &id: *regClasses.at(VecRegClass))
|
||||
tc.setRegFlat(id, &vecRegs[id.index()]);
|
||||
uint8_t regs[array_bytes];
|
||||
arrayParamIn(cp, std::string("regs.") + reg_class->name(), regs,
|
||||
array_bytes);
|
||||
|
||||
const size_t numPreds = regClasses.at(VecPredRegClass)->numRegs();
|
||||
std::vector<TheISA::VecPredRegContainer> vecPredRegs(numPreds);
|
||||
UNSERIALIZE_CONTAINER(vecPredRegs);
|
||||
for (auto &id: *regClasses.at(VecPredRegClass))
|
||||
tc.setRegFlat(id, &vecPredRegs[id.index()]);
|
||||
|
||||
const size_t numInts = regClasses.at(IntRegClass)->numRegs();
|
||||
RegVal intRegs[numInts];
|
||||
UNSERIALIZE_ARRAY(intRegs, numInts);
|
||||
for (auto &id: *regClasses.at(IntRegClass))
|
||||
tc.setRegFlat(id, intRegs[id.index()]);
|
||||
|
||||
const size_t numCcs = regClasses.at(CCRegClass)->numRegs();
|
||||
if (numCcs) {
|
||||
RegVal ccRegs[numCcs];
|
||||
UNSERIALIZE_ARRAY(ccRegs, numCcs);
|
||||
for (auto &id: *regClasses.at(CCRegClass))
|
||||
tc.setRegFlat(id, ccRegs[id.index()]);
|
||||
auto *reg_ptr = regs;
|
||||
for (const auto &id: *reg_class) {
|
||||
tc.setRegFlat(id, reg_ptr);
|
||||
reg_ptr += reg_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PCStateBase> pc_state(tc.pcState().clone());
|
||||
|
||||
80
util/cpt_upgraders/register-files.py
Normal file
80
util/cpt_upgraders/register-files.py
Normal file
@@ -0,0 +1,80 @@
|
||||
# Rename register files to their new systematic names.
|
||||
def upgrader(cpt):
|
||||
is_arm = cpt.get('root', 'isa', fallback='') == 'arm'
|
||||
|
||||
import re
|
||||
|
||||
is_cpu = lambda sec: 'intRegs' in cpt[sec]
|
||||
cpu_sections = filter(is_cpu, cpt.sections())
|
||||
|
||||
for sec in cpu_sections:
|
||||
items = cpt[sec]
|
||||
|
||||
# Almost all registers are 64 bits, except vectors and predicate
|
||||
# vectors in ARM.
|
||||
regval_bits = 64
|
||||
arm_vec_bits = 2048
|
||||
|
||||
byte_bits = 8
|
||||
byte_mask = (0x1 << byte_bits) - 1
|
||||
|
||||
# If there's vecRegs, create regs.vector_element from it.
|
||||
vec_regs = items.get('vecRegs')
|
||||
if vec_regs is not None:
|
||||
reg_vals = vec_regs.split()
|
||||
if is_arm:
|
||||
full_bits = arm_vec_bits
|
||||
else:
|
||||
full_bits = regval_bits
|
||||
reg_vals = ['0']
|
||||
elem_bits = 32
|
||||
elem_mask = (0x1 << elem_bits) - 1
|
||||
|
||||
bytes = []
|
||||
for full in reg_vals:
|
||||
full = int(full)
|
||||
for idx in range(full_bits // elem_bits):
|
||||
# Extract one element.
|
||||
elem = full & elem_mask
|
||||
full = full >> elem_bits
|
||||
|
||||
# Treat the element as a RegVal value, even if it's
|
||||
# fewer bits in the vector registers.
|
||||
for chunk in range(regval_bits // byte_bits):
|
||||
bytes.append(f'{elem & byte_mask}')
|
||||
elem = elem >> byte_bits
|
||||
|
||||
items['regs.vector_element'] = ' '.join(bytes)
|
||||
|
||||
name_map = {
|
||||
'floatRegs.i': 'regs.floating_point',
|
||||
'vecRegs': 'regs.vector',
|
||||
'vecPredRegs': 'regs.vector_predicate',
|
||||
'intRegs': 'regs.integer',
|
||||
'ccRegs': 'regs.condition_code',
|
||||
}
|
||||
|
||||
for old, new in name_map.items():
|
||||
if old in items:
|
||||
if is_arm and old in ('vecRegs', 'vecPredRegs'):
|
||||
reg_bits = 2048
|
||||
else:
|
||||
reg_bits = regval_bits
|
||||
|
||||
reg_vals = items[old].split()
|
||||
if not is_arm and old in ('vecRegs', 'vecPredRegs'):
|
||||
reg_vals = ['0']
|
||||
|
||||
bytes = []
|
||||
for reg in reg_vals:
|
||||
reg = int(reg)
|
||||
for chunk in range(reg_bits // byte_bits):
|
||||
bytes.append(f'{reg & byte_mask}')
|
||||
reg = reg >> byte_bits
|
||||
|
||||
items[new] = ' '.join(bytes)
|
||||
del items[old]
|
||||
|
||||
items.setdefault('regs.condition_code', '')
|
||||
|
||||
legacy_version = 16
|
||||
Reference in New Issue
Block a user