diff -r edde97a6ea7c -r 9bb72531ffd5 src/arch/isa_parser.py --- a/src/arch/isa_parser.py Sun Apr 18 21:33:59 2010 -0700 +++ b/src/arch/isa_parser.py Wed Apr 28 19:24:20 2010 +0800 @@ -482,6 +482,10 @@ def isControlReg(self): return 0 + # Dec. 2009, phoenix + def isIQoperand(self): + return 0 + def getFlags(self): # note the empty slice '[:]' gives us a copy of self.flags[0] # instead of a reference to it @@ -497,6 +501,117 @@ # to avoid 'uninitialized variable' errors from the compiler. return self.ctype + ' ' + self.base_name + ' = 0;\n'; +################# +# +# Authors: Gou Pengfei +# Date: Dec. 2009 +# +# Purpose: This class is for TRIPS operands of insts +# that should be read from an IQ rather +# than from global register. +# +class IntIQOperand(Operand): + def isIQoperand(self): + return 1 + + def isIntIQoperand(self): + return 1 + + def makeConstructor(self): + c = '' + return c + + def makeRead(self): + if (self.ctype == 'float' or self.ctype == 'double'): + error(0, 'Attempt to read integer operands from float IQ entries\n') + if self.read_code != None: + return self.buildReadCode('xc->getIntIQOperand') + if (self.size == self.dflt_size): + return '%s = xc->getIntIQOperand(%s);\n' % \ + (self.base_name, self.reg_spec) + elif (self.size > self.dflt_size): + int_reg_val = '%s = xc->getIntIQOperand(%s);\n' % \ + (self.base_name, self.reg_spec) + if (self.is_signed): + int_reg_val = 'sext<%d>(%s)' % (self.dflt_size, int_reg_val) + return '%s = %s;\n' % (self.base_name, int_reg_val) + else: + return '%s = bits(xc->getIntIQOperand(%s), %d, 0);\n' % \ + (self.base_name, self.reg_spec, self.size-1) + + def makeWrite(self): + if (self.ctype == 'float' or self.ctype == 'double'): + error(0, 'Attempt to write integer register as FP') + if self.write_code != None: + return self.buildWriteCode('xc->setIntIQOperand') + if (self.size != self.dflt_size and self.is_signed): + final_val = 'sext<%d>(%s)' % (self.size, self.base_name) + else: + final_val = self.base_name + wb = ''' + { + %s final_val = %s; + xc->setIntResult(final_val);\n\n + if (traceData) { traceData->setData(final_val); } + }''' % (self.dflt_ctype, final_val) + return wb + +class FloatIQOperand(Operand): + def isIQoperand(self): + return 1 + + def isFloatIQoperand(self): + return 1 + + def makeConstructor(self): + c = '' + return c + + def makeRead(self): + bit_select = 0 + if (self.ctype == 'float' or self.ctype == 'double'): + if ( self.ctype == 'float' ): + func = 'xc->getFloat32IQOperand' + elif ( self.ctype == 'double' ) : + func = 'xc->getFloatIQOperand' + else: + func = 'xc->getFloatIQOperandBits' + if (self.size != self.dflt_size): + bit_select = 1 + base = '%s(%s);\n' % (func, self.reg_spec) + if self.read_code != None: + return self.buildReadCode(func) + if bit_select: + return '%s = bits(%s, %d, 0);\n' % \ + (self.base_name, base, self.size-1) + else: + return '%s = %s;\n' % (self.base_name, base) + + def makeWrite(self): + final_val = self.base_name + final_ctype = self.ctype + if (self.ctype == 'float' or self.ctype == 'double'): + if ( self.ctype == 'float' ): + func = 'xc->setFloat32Result' + elif ( self.ctype == 'double' ): + func = 'xc->setFloatResult' + elif (self.ctype == 'uint32_t' or self.ctype == 'uint64_t'): + func = 'xc->setFloatResultBits' + else: + func = 'xc->setFloatResultBits' + final_ctype = 'uint%d_t' % self.dflt_size + if (self.size != self.dflt_size and self.is_signed): + final_val = 'sext<%d>(%s)' % (self.size, self.base_name) + if self.write_code != None: + return self.buildWriteCode(func) + wb = ''' + { + %s final_val = %s; + %s(final_val);\n + if (traceData) { traceData->setData(final_val); } + }''' % (final_ctype, final_val, func) + return wb + class IntRegOperand(Operand): def isReg(self): return 1 @@ -687,6 +802,21 @@ def makeWrite(self): return 'xc->setPC(%s);\n' % self.base_name +## +# Author: Gou Pengfei +# Date: Jan. 2010 +# Purpose: Add an operand class for EDGE +## +class NextBlockPCOperand(Operand): + def makeConstructor(self): + return '' + + def makeRead(self): + return '%s = xc->readNextBlockPC();\n' % self.base_name + + def makeWrite(self): + return 'xc->setNextBlockPC(%s);\n' % self.base_name + class UPCOperand(Operand): def makeConstructor(self): return '' @@ -788,8 +918,17 @@ self.numFPDestRegs = 0 self.numIntDestRegs = 0 self.memOperand = None + + # Dec. 2009, Gou Pengfei + self.numOperands = 0 + for op_desc in self.items: - if op_desc.isReg(): + # Dec. 2009, Gou Pengfei + if op_desc.isIQoperand(): + if op_desc.is_src: + op_desc.src_op_idx = self.numOperands + self.numOperands += 1 + elif op_desc.isReg(): if op_desc.is_src: op_desc.src_reg_idx = self.numSrcRegs self.numSrcRegs += 1 @@ -804,6 +943,12 @@ if self.memOperand: error("Code block has more than one memory operand.") self.memOperand = op_desc + + # Dec. 2009, Gou Pengfei + # This is for EDGE + if parser.maxInstOperands < self.numOperands: + parser.maxInstOperands = self.numOperands + if parser.maxInstSrcRegs < self.numSrcRegs: parser.maxInstSrcRegs = self.numSrcRegs if parser.maxInstDestRegs < self.numDestRegs: @@ -941,14 +1086,28 @@ self.operands = OperandList(parser, compositeCode) self.constructor = self.operands.concatAttrStrings('constructor') + + # Dec. 2009, Gou Pengfei + # Purpose: + # If there're operand members in this inst, which means this is a edge inst using operands from + # IQs rather than from registers, the inst class will be EDGEStaticInst in which there's no members + # named _numSrcRegs. There're only _numOperands and _numConsumers in this class. Consequently, + # we merely put _numOperands statments here in its consutructors. + # For this course, I put flags named IQOPerands as one of the op_class flag to achevie this goal. + # For how to define flags both for staticinst and op_class in this parser, you can refer to the comments + # below this if-else block. + if 'IQOPerands' in opt_args: + self.constructor += \ + '\n\t_numOperands = %d;' % self.operands.numOperands + self.constructor += \ - '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs + '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs self.constructor += \ - '\n\t_numDestRegs = %d;' % self.operands.numDestRegs + '\n\t_numDestRegs = %d;' % self.operands.numDestRegs self.constructor += \ - '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs + '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs self.constructor += \ - '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs + '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs self.flags = self.operands.concatAttrLists('flags') # Make a basic guess on the operand class (function unit type). @@ -963,20 +1122,48 @@ else: self.op_class = 'IntAluOp' + # Dec. 2009, Gou Pengfei + # Purpose: + # Get number of conusmers of this EDGE instruction + if 'IsEDGE' in opt_args: + cnum_dict = opt_args[len(opt_args) - 1] + if not isinstance(cnum_dict, dict): + error(0,'Since last member of your opt_args in your InstObjParams is not ' + 'type of dict, you may not follow the instruct of how to set consumer numbers of your EDGE insts.') + try: + num = cnum_dict['numConsumer'] + except KeyError: + error(0,'What does %s mean in InstObjParams?' % cnum_dict.keys()) + for i in range(0,num): + self.constructor += '\n\t_consumerID[%d]=T%d;' % (i, i) + self.constructor += '\n\t_numConsumers=%d;' % num + + if parser.maxInstConsumers < num: + parser.maxInstConsumers = num; + # Optional arguments are assumed to be either StaticInst flags # or an OpClass value. To avoid having to import a complete # list of these values to match against, we do it ad-hoc # with regexps. + + # Dec. 2009, Gou Pengfei + # Purpose: Two cases has been added into code blocks below for two exceptions: + # 1) Add an exception option 'IQOperands' when judging opt_args in InstObjParams, + # indicating that this is an EDGE inst whose operand comes directly from IQ. + # + # 2) Allow a dict member in opt_args for passing num of consumers into this class for oa in opt_args: - if instFlagRE.match(oa): + if isinstance(oa,dict): + print 'Message from phoenix: dict member in opt_args in InstObjParams' + elif instFlagRE.match(oa): self.flags.append(oa) elif opClassRE.match(oa): self.op_class = oa - else: - error('InstObjParams: optional arg "%s" not recognized ' + elif oa != 'IQOPerands': + error(0, 'InstObjParams: optional arg "%s" not recognized ' 'as StaticInst::Flag or OpClass.' % oa) - # add flag initialization to contructor here to include + # add flag initialization to constructor here to include # any flags added via opt_args self.constructor += makeFlagConstructor(self.flags) @@ -987,6 +1174,7 @@ else: self.fp_enable_check = '' + ############## # Stack: a simple stack object. Used for both formats (formatStack) # and default cases (defaultStack). Simply wraps a list to give more @@ -1040,6 +1228,10 @@ const int MaxInstSrcRegs = %(MaxInstSrcRegs)d; const int MaxInstDestRegs = %(MaxInstDestRegs)d; + /// This is for EDGE + const int MaxInstOperands = %(MaxInstOperands)d; + const int MaxInstConsumers = %(MaxInstConsumers)d; + } // namespace %(namespace)s ''' @@ -1075,6 +1267,11 @@ self.maxInstSrcRegs = 0 self.maxInstDestRegs = 0 + # Dec. 2009, Gou Pengfei + # This is for EDGE + self.maxInstOperands = 0 + self.maxInstConsumers = 0 + ##################################################################### # # Lexer @@ -1254,12 +1451,35 @@ isa_name = t[2] namespace = isa_name + "Inst" # wrap the decode block as a function definition - t[4].wrap_decode_block(''' -StaticInstPtr -%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) -{ - using namespace %(namespace)s; -''' % vars(), '}') + # + # Dec. 2009, phoenix + # Purpose: I need to add a BLOCKSTATUS flag to indicate if this inst is in header chunk + # for TRIPS ISA. Note that there're two form of decodeInst() overload function. + # The one with two argument (called in cpu/edge/static_inst.hh) is actually + # available in TripsISA due to some implementation concerns while the one + # with one argument, which is the original form of decodeInst() used in other + # ISAs, has been put here for compalibility with cpu/static_inst.hh file. + # + if isa_name == 'TripsISA': + t[4].wrap_decode_block(''' + StaticInstPtr %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst ) + { + return StaticInst::nullStaticInstPtr; + } + + EDGEStaticInstPtr + %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst, uint8_t BLOCKSTATUS) + { + using namespace %(namespace)s; + ''' % vars(), '}') + else: + t[4].wrap_decode_block(''' + StaticInstPtr + %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) + { + using namespace %(namespace)s; + ''' % vars(), '}') + # both the latter output blocks and the decode block are in # the namespace namespace_code = t[3] + t[4] @@ -2060,6 +2280,18 @@ # value of the globals. MaxInstSrcRegs = self.maxInstSrcRegs MaxInstDestRegs = self.maxInstDestRegs + + # Dec. 2009, phoenix + # This is for EDGE + # + # Actually there're at most 4 consumers in TRIPS ISA. + # For all insts except mov, they have at most 2 cosumers, + # so I add this difference into the maxConsumers variable. + # We need to figure out a better way to handle this. + # + MaxInstOperands = self.maxInstOperands + MaxInstConsumers = self.maxInstConsumers + 2 + # max_inst_regs.hh self.update_if_needed('max_inst_regs.hh', max_inst_regs_template % vars())