Gives separate methods for initiating and completing a memory access, which will be helpful for the merged memory model.
arch/alpha/isa/mem.isa: Include methods that allow a memory operation to be split between the part that initiates the access, and the part that completes the access. In these functions the Mem variable is explicitly declared; in the default execute functions, the Mem variable is still handled through %(op_decl)s. arch/isa_parser.py: Include recording the type of the memory access variable so that it can be used if it needs to be explicitly declared in a template. Have memory operands consider themselves neither a source nor a destination to avoid including themselves on the op_src_decl list or the op_dest_decl list. Record op_src_decl and op_dest_decl lists to allow for declaring only source or destination operands. This is needed for the split memory access methods. --HG-- extra : convert_revision : f674f7a2f747ae40ba8c3a0933b0337c87ee0b6c
This commit is contained in:
parent
7b42d61f13
commit
2d04f18674
2 changed files with 170 additions and 1 deletions
|
@ -164,9 +164,24 @@ def template LoadStoreDeclare {{
|
||||||
%(class_name)s(MachInst machInst);
|
%(class_name)s(MachInst machInst);
|
||||||
|
|
||||||
%(BasicExecDeclare)s
|
%(BasicExecDeclare)s
|
||||||
|
|
||||||
|
%(InitiateAccDeclare)s
|
||||||
|
|
||||||
|
%(CompleteAccDeclare)s
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def template InitiateAccDeclare {{
|
||||||
|
Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def template CompleteAccDeclare {{
|
||||||
|
Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
def template LoadStoreConstructor {{
|
def template LoadStoreConstructor {{
|
||||||
/** TODO: change op_class to AddrGenOp or something (requires
|
/** TODO: change op_class to AddrGenOp or something (requires
|
||||||
* creating new member of OpClass enum in op_class.hh, updating
|
* creating new member of OpClass enum in op_class.hh, updating
|
||||||
|
@ -267,6 +282,54 @@ def template LoadExecute {{
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def template LoadInitiateAcc {{
|
||||||
|
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
Addr EA;
|
||||||
|
Fault fault = No_Fault;
|
||||||
|
%(mem_acc_type)s Mem = 0;
|
||||||
|
|
||||||
|
%(fp_enable_check)s;
|
||||||
|
%(op_src_decl)s;
|
||||||
|
%(op_rd)s;
|
||||||
|
%(ea_code)s;
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def template LoadCompleteAcc {{
|
||||||
|
Fault %(class_name)s::completeAcc(uint8_t *data,
|
||||||
|
%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
Fault fault = No_Fault;
|
||||||
|
%(mem_acc_type)s Mem = 0;
|
||||||
|
|
||||||
|
%(fp_enable_check)s;
|
||||||
|
%(op_dest_decl)s;
|
||||||
|
|
||||||
|
memcpy(&Mem, data, sizeof(Mem));
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
%(memacc_code)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
%(op_wb)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
def template StoreMemAccExecute {{
|
def template StoreMemAccExecute {{
|
||||||
Fault
|
Fault
|
||||||
%(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
|
%(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
|
||||||
|
@ -339,6 +402,60 @@ def template StoreExecute {{
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
def template StoreInitiateAcc {{
|
||||||
|
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
Addr EA;
|
||||||
|
Fault fault = No_Fault;
|
||||||
|
uint64_t write_result = 0;
|
||||||
|
%(mem_acc_type)s Mem = 0;
|
||||||
|
|
||||||
|
%(fp_enable_check)s;
|
||||||
|
%(op_src_decl)s;
|
||||||
|
%(op_rd)s;
|
||||||
|
%(ea_code)s;
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
%(memacc_code)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
|
||||||
|
memAccessFlags, &write_result);
|
||||||
|
if (traceData) { traceData->setData(Mem); }
|
||||||
|
}
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def template StoreCompleteAcc {{
|
||||||
|
Fault %(class_name)s::completeAcc(uint8_t *data,
|
||||||
|
%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
Fault fault = No_Fault;
|
||||||
|
uint64_t write_result = 0;
|
||||||
|
|
||||||
|
%(fp_enable_check)s;
|
||||||
|
%(op_dest_decl)s;
|
||||||
|
|
||||||
|
memcpy(&write_result, data, sizeof(write_result));
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
%(postacc_code)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
%(op_wb)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
def template MiscMemAccExecute {{
|
def template MiscMemAccExecute {{
|
||||||
Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
|
Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
|
||||||
|
@ -380,6 +497,36 @@ def template MiscExecute {{
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
def template MiscInitiateAcc {{
|
||||||
|
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
Addr EA;
|
||||||
|
Fault fault = No_Fault;
|
||||||
|
|
||||||
|
%(fp_enable_check)s;
|
||||||
|
%(op_decl)s;
|
||||||
|
%(op_rd)s;
|
||||||
|
%(ea_code)s;
|
||||||
|
|
||||||
|
if (fault == No_Fault) {
|
||||||
|
%(memacc_code)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return No_Fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def template MiscCompleteAcc {{
|
||||||
|
Fault %(class_name)s::completeAcc(uint8_t *data,
|
||||||
|
%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
return No_Fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
// load instructions use Ra as dest, so check for
|
// load instructions use Ra as dest, so check for
|
||||||
// Ra == 31 to detect nops
|
// Ra == 31 to detect nops
|
||||||
def template LoadNopCheckDecode {{
|
def template LoadNopCheckDecode {{
|
||||||
|
@ -455,13 +602,17 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||||
# select templates
|
# select templates
|
||||||
memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
|
memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
|
||||||
fullExecTemplate = eval(exec_template_base + 'Execute')
|
fullExecTemplate = eval(exec_template_base + 'Execute')
|
||||||
|
initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
|
||||||
|
completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
|
||||||
|
|
||||||
# (header_output, decoder_output, decode_block, exec_output)
|
# (header_output, decoder_output, decode_block, exec_output)
|
||||||
return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
|
return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
|
||||||
decode_template.subst(iop),
|
decode_template.subst(iop),
|
||||||
EACompExecute.subst(ea_iop)
|
EACompExecute.subst(ea_iop)
|
||||||
+ memAccExecTemplate.subst(memacc_iop)
|
+ memAccExecTemplate.subst(memacc_iop)
|
||||||
+ fullExecTemplate.subst(iop))
|
+ fullExecTemplate.subst(iop)
|
||||||
|
+ initiateAccTemplate.subst(iop)
|
||||||
|
+ completeAccTemplate.subst(iop))
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1138,6 +1138,7 @@ class Operand(object):
|
||||||
# template must be careful not to use it if it doesn't apply.
|
# template must be careful not to use it if it doesn't apply.
|
||||||
if self.isMem():
|
if self.isMem():
|
||||||
self.mem_acc_size = self.makeAccSize()
|
self.mem_acc_size = self.makeAccSize()
|
||||||
|
self.mem_acc_type = self.ctype
|
||||||
|
|
||||||
# Finalize additional fields (primarily code fields). This step
|
# Finalize additional fields (primarily code fields). This step
|
||||||
# is done separately since some of these fields may depend on the
|
# is done separately since some of these fields may depend on the
|
||||||
|
@ -1148,15 +1149,23 @@ class Operand(object):
|
||||||
self.constructor = self.makeConstructor()
|
self.constructor = self.makeConstructor()
|
||||||
self.op_decl = self.makeDecl()
|
self.op_decl = self.makeDecl()
|
||||||
|
|
||||||
|
if self.isMem():
|
||||||
|
self.is_src = ''
|
||||||
|
self.is_dest = ''
|
||||||
|
|
||||||
if self.is_src:
|
if self.is_src:
|
||||||
self.op_rd = self.makeRead()
|
self.op_rd = self.makeRead()
|
||||||
|
self.op_src_decl = self.makeDecl()
|
||||||
else:
|
else:
|
||||||
self.op_rd = ''
|
self.op_rd = ''
|
||||||
|
self.op_src_decl = ''
|
||||||
|
|
||||||
if self.is_dest:
|
if self.is_dest:
|
||||||
self.op_wb = self.makeWrite()
|
self.op_wb = self.makeWrite()
|
||||||
|
self.op_dest_decl = self.makeDecl()
|
||||||
else:
|
else:
|
||||||
self.op_wb = ''
|
self.op_wb = ''
|
||||||
|
self.op_dest_decl = ''
|
||||||
|
|
||||||
def isMem(self):
|
def isMem(self):
|
||||||
return 0
|
return 0
|
||||||
|
@ -1589,6 +1598,14 @@ class CodeBlock:
|
||||||
|
|
||||||
self.op_decl = self.operands.concatAttrStrings('op_decl')
|
self.op_decl = self.operands.concatAttrStrings('op_decl')
|
||||||
|
|
||||||
|
is_src = lambda op: op.is_src
|
||||||
|
is_dest = lambda op: op.is_dest
|
||||||
|
|
||||||
|
self.op_src_decl = \
|
||||||
|
self.operands.concatSomeAttrStrings(is_src, 'op_src_decl')
|
||||||
|
self.op_dest_decl = \
|
||||||
|
self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl')
|
||||||
|
|
||||||
self.op_rd = self.operands.concatAttrStrings('op_rd')
|
self.op_rd = self.operands.concatAttrStrings('op_rd')
|
||||||
self.op_wb = self.operands.concatAttrStrings('op_wb')
|
self.op_wb = self.operands.concatAttrStrings('op_wb')
|
||||||
|
|
||||||
|
@ -1596,6 +1613,7 @@ class CodeBlock:
|
||||||
|
|
||||||
if self.operands.memOperand:
|
if self.operands.memOperand:
|
||||||
self.mem_acc_size = self.operands.memOperand.mem_acc_size
|
self.mem_acc_size = self.operands.memOperand.mem_acc_size
|
||||||
|
self.mem_acc_type = self.operands.memOperand.mem_acc_type
|
||||||
|
|
||||||
# Make a basic guess on the operand class (function unit type).
|
# Make a basic guess on the operand class (function unit type).
|
||||||
# These are good enough for most cases, and will be overridden
|
# These are good enough for most cases, and will be overridden
|
||||||
|
|
Loading…
Reference in a new issue