rename store conditional stuff as extra data so it can be used for conditional swaps...
authorAli Saidi <saidi@eecs.umich.edu>
Mon, 12 Feb 2007 18:06:30 +0000 (13:06 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Mon, 12 Feb 2007 18:06:30 +0000 (13:06 -0500)
Add support for a twin 64 bit int load
Add Memory barrier and write barrier flags as appropriate
Make atomic memory ops atomic

src/arch/alpha/isa/mem.isa:
src/arch/alpha/locked_mem.hh:
src/cpu/base_dyn_inst.hh:
src/mem/cache/cache_blk.hh:
src/mem/cache/cache_impl.hh:
    rename store conditional stuff as extra data so it can be used for conditional swaps as well
src/arch/alpha/types.hh:
src/arch/mips/types.hh:
src/arch/sparc/types.hh:
    add a largest read data type for statically allocating read buffers in atomic simple cpu
src/arch/isa_parser.py:
    Add support for a twin 64 bit int load
src/arch/sparc/isa/decoder.isa:
    Make atomic memory ops atomic
    Add Memory barrier and write barrier flags as appropriate
src/arch/sparc/isa/formats/mem/basicmem.isa:
    add post access code block and define a twinload format for twin loads
src/arch/sparc/isa/formats/mem/blockmem.isa:
    remove old microcoded twin load coad
src/arch/sparc/isa/formats/mem/mem.isa:
    swap.isa replaces the code in loadstore.isa
src/arch/sparc/isa/formats/mem/util.isa:
    add a post access code block
src/arch/sparc/isa/includes.isa:
    need bigint.hh for Twin64_t
src/arch/sparc/isa/operands.isa:
    add a twin 64 int type
src/cpu/simple/atomic.cc:
src/cpu/simple/atomic.hh:
src/cpu/simple/base.hh:
src/cpu/simple/timing.cc:
    add support for twinloads
    add support for swap and conditional swap instructions
    rename store conditional stuff as extra data so it can be used for conditional swaps as well
src/mem/packet.cc:
src/mem/packet.hh:
    Add support for atomic swap memory commands
src/mem/packet_access.hh:
    Add endian conversion function for Twin64_t type
src/mem/physical.cc:
src/mem/physical.hh:
src/mem/request.hh:
    Add support for atomic swap memory commands
    Rename sc code to extradata

--HG--
extra : convert_revision : 69d908512fb34a4e28b29a6e58b807fb1a6b1656

28 files changed:
src/arch/alpha/isa/mem.isa
src/arch/alpha/locked_mem.hh
src/arch/alpha/types.hh
src/arch/isa_parser.py
src/arch/mips/types.hh
src/arch/sparc/isa/decoder.isa
src/arch/sparc/isa/formats/mem/basicmem.isa
src/arch/sparc/isa/formats/mem/blockmem.isa
src/arch/sparc/isa/formats/mem/mem.isa
src/arch/sparc/isa/formats/mem/swap.isa [new file with mode: 0644]
src/arch/sparc/isa/formats/mem/util.isa
src/arch/sparc/isa/includes.isa
src/arch/sparc/isa/operands.isa
src/arch/sparc/types.hh
src/base/bigint.hh [new file with mode: 0644]
src/cpu/base_dyn_inst.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/base.hh
src/cpu/simple/timing.cc
src/mem/cache/cache_blk.hh
src/mem/cache/cache_impl.hh
src/mem/packet.cc
src/mem/packet.hh
src/mem/packet_access.hh
src/mem/physical.cc
src/mem/physical.hh
src/mem/request.hh

index c0bdd2c059e77651cc630a6f82f357112b53669e..a82435a85463aecee0dd847609a6e5e7fc8f9a15 100644 (file)
@@ -475,7 +475,7 @@ def template StoreCondCompleteAcc {{
         %(fp_enable_check)s;
         %(op_dest_decl)s;
 
-        uint64_t write_result = pkt->req->getScResult();
+        uint64_t write_result = pkt->req->getExtraData();
 
         if (fault == NoFault) {
             %(postacc_code)s;
index 52fe241738d50898c470494afe7834f396d62b01..44b002c6c7039764922d4e4d08932f8aa0191721 100644 (file)
@@ -60,7 +60,7 @@ handleLockedWrite(XC *xc, Request *req)
     if (req->isUncacheable()) {
         // Funky Turbolaser mailbox access...don't update
         // result register (see stq_c in decoder.isa)
-        req->setScResult(2);
+        req->setExtraData(2);
     } else {
         // standard store conditional
         bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG);
@@ -68,7 +68,7 @@ handleLockedWrite(XC *xc, Request *req)
         if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
             // Lock flag not set or addr mismatch in CPU;
             // don't even bother sending to memory system
-            req->setScResult(0);
+            req->setExtraData(0);
             xc->setMiscReg(MISCREG_LOCKFLAG, false);
             // the rest of this code is not architectural;
             // it's just a debugging aid to help detect
index ae42552d89f24b3b0e52897e8c98547f17e33dc1..6433ea3ca7de5df46c4dd2f10b03c3150c0dbdd3 100644 (file)
@@ -42,6 +42,7 @@ namespace AlphaISA
     typedef uint8_t  RegIndex;
 
     typedef uint64_t IntReg;
+    typedef uint64_t LargestRead;
 
     // floating point register file entry type
     typedef double FloatReg;
index 07ae72cb802c524b0441aebacbc819f9d3b30805..39500df36082a4950cfba1947a021ede7d983105 100755 (executable)
@@ -1124,6 +1124,9 @@ def buildOperandTypeMap(userDict, lineno):
                 ctype = 'float'
             elif size == 64:
                 ctype = 'double'
+        elif desc == 'twin int':
+            is_signed = 0
+            ctype = 'Twin64_t'
         if ctype == '':
             error(lineno, 'Unrecognized type description "%s" in userDict')
         operandTypeMap[ext] = (size, ctype, is_signed)
@@ -1156,7 +1159,10 @@ class Operand(object):
         # template must be careful not to use it if it doesn't apply.
         if self.isMem():
             self.mem_acc_size = self.makeAccSize()
-            self.mem_acc_type = self.ctype
+            if self.ctype == 'Twin64_t':
+                self.mem_acc_type = 'Twin'
+            else:
+                self.mem_acc_type = 'uint'
 
     # Finalize additional fields (primarily code fields).  This step
     # is done separately since some of these fields may depend on the
@@ -1386,6 +1392,9 @@ class MemOperand(Operand):
         # Note that initializations in the declarations are solely
         # to avoid 'uninitialized variable' errors from the compiler.
         # Declare memory data variable.
+        if self.ctype == 'Twin64_t':
+            return "%s %s; %s.a = 0; %s.b = 0;\n" % (self.ctype, self.base_name,
+                    self.base_name, self.base_name)
         c = '%s %s = 0;\n' % (self.ctype, self.base_name)
         return c
 
index d4fa296fd6c093fbe7cc132c1905e162a69866aa..fc45ea253ca0beacce03f24120cda585f97d851d 100644 (file)
@@ -40,6 +40,8 @@ namespace MipsISA
     typedef uint8_t  RegIndex;
 
     typedef uint32_t IntReg;
+    typedef uint64_t LargestRead;
+
 
     // floating point register file entry type
     typedef uint32_t FloatReg32;
index fb606c7cce58f49fa7ec45d6e3f71a9bd2454c6f..0be7defba9a81c42d8370027b13a17707ccf092d 100644 (file)
@@ -472,8 +472,8 @@ decode OP default Unknown::unknown()
                 }});
                 //7-14 should cause an illegal instruction exception
                 0x0F: decode I {
-                    0x0: Nop::stbar({{/*stuff*/}});
-                    0x1: Nop::membar({{/*stuff*/}});
+                    0x0: Nop::stbar({{/*stuff*/}}, IsWriteBarrier, MemWriteOp);
+                    0x1: Nop::membar({{/*stuff*/}}, IsMemBarrier, MemReadOp);
                 }
                 0x10: Priv::rdpcr({{Rd = Pcr;}});
                 0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}});
@@ -1168,15 +1168,17 @@ decode OP default Unknown::unknown()
             0x0A: ldsh({{Rd = (int16_t)Mem.shw;}});
             0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
         }
-        0x0D: LoadStore::ldstub(
-        {{uReg0 = Mem.ub;}},
-        {{Rd.ub = uReg0;
-          Mem.ub = 0xFF;}});
+        0x0D: Swap::ldstub({{Mem.ub = 0xFF;}},
+                           {{
+                               uint8_t tmp = mem_data;
+                               Rd.ub = tmp;
+                           }}, MEM_SWAP);
         0x0E: Store::stx({{Mem.udw = Rd}});
-        0x0F: LoadStore::swap(
-            {{ uReg0 = Mem.uw}},
-            {{ Mem.uw = Rd.uw;
-               Rd.uw = uReg0;}});
+        0x0F: Swap::swap({{Mem.uw = Rd.uw}},
+                         {{
+                               uint32_t tmp = mem_data;
+                               Rd.uw = tmp;
+                         }}, MEM_SWAP);
         format LoadAlt {
             0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
             0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
@@ -1184,34 +1186,60 @@ decode OP default Unknown::unknown()
             0x13: decode EXT_ASI {
                 //ASI_LDTD_AIUP
                 0x22: TwinLoad::ldtx_aiup(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 //ASI_LDTD_AIUS
                 0x23: TwinLoad::ldtx_aius(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 //ASI_QUAD_LDD
                 0x24: TwinLoad::ldtx_quad_ldd(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 //ASI_LDTX_REAL
                 0x26: TwinLoad::ldtx_real(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
-               //ASI_LDTX_N
-               0x27: TwinLoad::ldtx_n(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
-               //ASI_LDTX_L
-               0x2C: TwinLoad::ldtx_l(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
+                //ASI_LDTX_N
+                0x27: TwinLoad::ldtx_n(
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
+                //ASI_LDTX_AIUP_L
+                0x2A: TwinLoad::ldtx_aiup_l(
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
+                //ASI_LDTX_AIUS_L
+                0x2B: TwinLoad::ldtx_aius_l(
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
+                //ASI_LDTX_L
+                0x2C: TwinLoad::ldtx_l(
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 //ASI_LDTX_REAL_L
                 0x2E: TwinLoad::ldtx_real_l(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 //ASI_LDTX_N_L
                 0x2F: TwinLoad::ldtx_n_l(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 //ASI_LDTX_P
                 0xE2: TwinLoad::ldtx_p(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 //ASI_LDTX_S
                 0xE3: TwinLoad::ldtx_s(
-                    {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
+                //ASI_LDTX_PL
+                0xEA: TwinLoad::ldtx_pl(
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
+                //ASI_LDTX_SL
+                0xEB: TwinLoad::ldtx_sl(
+                    {{RdLow.udw = (Mem.tudw).a;
+                      RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
                 default: ldtwa({{
                         uint64_t val = Mem.udw;
                         RdLow = val<31:0>;
@@ -1231,15 +1259,18 @@ decode OP default Unknown::unknown()
             0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}, {{EXT_ASI}});
             0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
         }
-        0x1D: LoadStoreAlt::ldstuba(
-                {{uReg0 = Mem.ub;}},
-                {{Rd.ub = uReg0;
-                  Mem.ub = 0xFF;}}, {{EXT_ASI}});
+        0x1D: SwapAlt::ldstuba({{Mem.ub = 0xFF;}},
+                           {{
+                               uint8_t tmp = mem_data;
+                               Rd.ub = tmp;
+                           }}, {{EXT_ASI}}, MEM_SWAP);
         0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
-        0x1F: LoadStoreAlt::swapa(
-            {{ uReg0 = Mem.uw}},
-            {{ Mem.uw = Rd.uw;
-               Rd.uw = uReg0;}}, {{EXT_ASI}});
+        0x1F: SwapAlt::swapa({{Mem.uw = Rd.uw}},
+                         {{
+                               uint32_t tmp = mem_data;
+                               Rd.uw = tmp;
+                         }}, {{EXT_ASI}}, MEM_SWAP);
+
         format Trap {
             0x20: Load::ldf({{Frds.uw = Mem.uw;}});
             0x21: decode RD {
@@ -1438,21 +1469,17 @@ decode OP default Unknown::unknown()
                         {{fault = new DataAccessException;}});
                 }
             }
-            0x3C: Cas::casa(
-                {{uReg0 = Mem.uw;}},
-                {{if(Rs2.uw == uReg0)
-                        Mem.uw = Rd.uw;
-                else
-                        storeCond = false;
-                Rd.uw = uReg0;}}, {{EXT_ASI}});
+            0x3C: CasAlt::casa({{
+                               mem_data = htog(Rs2.uw);
+                               Mem.uw = Rd.uw;}},
+                         {{
+                               uint32_t tmp = mem_data;
+                               Rd.uw = tmp;
+                         }}, {{EXT_ASI}}, MEM_SWAP_COND);
             0x3D: Nop::prefetcha({{ }});
-            0x3E: Cas::casxa(
-                {{uReg0 = Mem.udw;}},
-                {{if(Rs2 == uReg0)
-                        Mem.udw = Rd;
-                else
-                        storeCond = false;
-                Rd = uReg0;}}, {{EXT_ASI}});
+            0x3E: CasAlt::casxa({{mem_data = gtoh(Rs2);
+                                Mem.udw = Rd.udw; }},
+                         {{ Rd.udw = mem_data; }}, {{EXT_ASI}}, MEM_SWAP_COND);
         }
     }
 }
index 1d9075a570f7cf0c6d18279e51aa931d81e31ee4..7512628112307b0d8ad084eb40ae60a4c48a5bb0 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2006 The Regents of The University of Michigan
+// Copyright (c) 2006-2007 The Regents of The University of Michigan
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -52,22 +52,20 @@ def template MemDeclare {{
 }};
 
 let {{
-    def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags):
+    def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''):
         addrCalcReg = 'EA = Rs1 + Rs2;'
         addrCalcImm = 'EA = Rs1 + imm;'
         iop = InstObjParams(name, Name, 'Mem',
-                {"code": code, "fault_check": faultCode,
-                 "ea_code": addrCalcReg},
-                opt_flags)
+                {"code": code, "postacc_code" : postacc_code,
+                 "fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags)
         iop_imm = InstObjParams(name, Name + "Imm", 'MemImm',
-                {"code": code, "fault_check": faultCode,
-                 "ea_code": addrCalcImm},
-                opt_flags)
+                {"code": code, "postacc_code" : postacc_code,
+                "fault_check": faultCode, "ea_code": addrCalcImm}, opt_flags)
         header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
         decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
         decode_block = ROrImmDecode.subst(iop)
-        exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm,
-                execute, faultCode, name, name + "Imm",
+        exec_output = doDualSplitExecute(code, postacc_code, addrCalcReg,
+                addrCalcImm, execute, faultCode, name, name + "Imm",
                 Name, Name + "Imm", asi, opt_flags)
         return (header_output, decoder_output, exec_output, decode_block)
 }};
@@ -103,3 +101,13 @@ def format Store(code, *opt_flags) {{
          decode_block) = doMemFormat(code,
              StoreFuncs, '', name, Name, 0, opt_flags)
 }};
+
+def format TwinLoad(code, asi, *opt_flags) {{
+        (header_output,
+         decoder_output,
+         exec_output,
+         decode_block) = doMemFormat(code, LoadFuncs,
+            AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck,
+            name, Name, asi, opt_flags)
+}};
+
index 9795d2342ba6d482d521d354c1d278e7b3dc9267..499685a5cfeb19fbd8939abec213e51ad8d2d02a 100644 (file)
@@ -91,65 +91,6 @@ output header {{
         };
 }};
 
-output header {{
-
-        class TwinMem : public SparcMacroInst
-        {
-          protected:
-
-            // Constructor
-            // We make the assumption that all block memory operations
-            // Will take 8 instructions to execute
-            TwinMem(const char *mnem, ExtMachInst _machInst) :
-                SparcMacroInst(mnem, _machInst, No_OpClass, 2)
-            {}
-        };
-
-        class TwinMemImm : public BlockMem
-        {
-          protected:
-
-            // Constructor
-            TwinMemImm(const char *mnem, ExtMachInst _machInst) :
-                BlockMem(mnem, _machInst)
-            {}
-        };
-
-        class TwinMemMicro : public SparcMicroInst
-        {
-          protected:
-
-            // Constructor
-            TwinMemMicro(const char *mnem, ExtMachInst _machInst,
-                    OpClass __opClass, int8_t _offset) :
-                SparcMicroInst(mnem, _machInst, __opClass),
-                offset(_offset)
-            {}
-
-            std::string generateDisassembly(Addr pc,
-                const SymbolTable *symtab) const;
-
-            const int8_t offset;
-        };
-
-        class TwinMemImmMicro : public BlockMemMicro
-        {
-          protected:
-
-            // Constructor
-            TwinMemImmMicro(const char *mnem, ExtMachInst _machInst,
-                    OpClass __opClass, int8_t _offset) :
-                BlockMemMicro(mnem, _machInst, __opClass, _offset),
-                imm(sext<13>(SIMM13))
-            {}
-
-            std::string generateDisassembly(Addr pc,
-                const SymbolTable *symtab) const;
-
-            const int32_t imm;
-        };
-}};
-
 output decoder {{
         std::string BlockMemMicro::generateDisassembly(Addr pc,
                 const SymbolTable *symtab) const
@@ -208,64 +149,6 @@ output decoder {{
 
 }};
 
-output decoder {{
-        std::string TwinMemMicro::generateDisassembly(Addr pc,
-                const SymbolTable *symtab) const
-        {
-            std::stringstream response;
-            bool load = flags[IsLoad];
-            bool save = flags[IsStore];
-
-            printMnemonic(response, mnemonic);
-            if(save)
-            {
-                printReg(response, _srcRegIdx[0]);
-                ccprintf(response, ", ");
-            }
-            ccprintf(response, "[ ");
-            printReg(response, _srcRegIdx[!save ? 0 : 1]);
-            ccprintf(response, " + ");
-            printReg(response, _srcRegIdx[!save ? 1 : 2]);
-            ccprintf(response, " ]");
-            if(load)
-            {
-                ccprintf(response, ", ");
-                printReg(response, _destRegIdx[0]);
-            }
-
-            return response.str();
-        }
-
-        std::string TwinMemImmMicro::generateDisassembly(Addr pc,
-                const SymbolTable *symtab) const
-        {
-            std::stringstream response;
-            bool load = flags[IsLoad];
-            bool save = flags[IsStore];
-
-            printMnemonic(response, mnemonic);
-            if(save)
-            {
-                printReg(response, _srcRegIdx[1]);
-                ccprintf(response, ", ");
-            }
-            ccprintf(response, "[ ");
-            printReg(response, _srcRegIdx[0]);
-            if(imm >= 0)
-                ccprintf(response, " + 0x%x ]", imm);
-            else
-                ccprintf(response, " + -0x%x ]", -imm);
-            if(load)
-            {
-                ccprintf(response, ", ");
-                printReg(response, _destRegIdx[0]);
-            }
-
-            return response.str();
-        }
-
-}};
-
 def template BlockMemDeclare {{
         /**
          * Static instruction class for a block memory operation
@@ -359,39 +242,6 @@ def template BlockMemDeclare {{
         };
 }};
 
-def template TwinMemDeclare {{
-        /**
-         * Static instruction class for a block memory operation
-         */
-        class %(class_name)s : public %(base_class)s
-        {
-          public:
-            //Constructor
-            %(class_name)s(ExtMachInst machInst);
-
-          protected:
-            class %(class_name)s_0 : public %(base_class)sMicro
-            {
-              public:
-                //Constructor
-                %(class_name)s_0(ExtMachInst machInst);
-                %(BasicExecDeclare)s
-                %(InitiateAccDeclare)s
-                %(CompleteAccDeclare)s
-            };
-
-            class %(class_name)s_1 : public %(base_class)sMicro
-            {
-              public:
-                //Constructor
-                %(class_name)s_1(ExtMachInst machInst);
-                %(BasicExecDeclare)s
-                %(InitiateAccDeclare)s
-                %(CompleteAccDeclare)s
-            };
-        };
-}};
-
 // Basic instruction class constructor template.
 def template BlockMemConstructor {{
         inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
@@ -409,17 +259,6 @@ def template BlockMemConstructor {{
         }
 }};
 
-// Basic instruction class constructor template.
-def template TwinMemConstructor {{
-        inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
-            : %(base_class)s("%(mnemonic)s", machInst)
-        {
-            %(constructor)s;
-            microOps[0] = new %(class_name)s_0(machInst);
-            microOps[1] = new %(class_name)s_1(machInst);
-        }
-}};
-
 def template BlockMemMicroConstructor {{
         inline %(class_name)s::
             %(class_name)s_%(micro_pc)s::
@@ -467,47 +306,7 @@ let {{
             decoder_output += BlockMemMicroConstructor.subst(iop)
             decoder_output += BlockMemMicroConstructor.subst(iop_imm)
             exec_output += doDualSplitExecute(
-                    pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
-                    makeMicroName(name, microPc),
-                    makeMicroName(name + "Imm", microPc),
-                    makeMicroName(Name, microPc),
-                    makeMicroName(Name + "Imm", microPc),
-                    asi, opt_flags);
-            faultCode = ''
-        return (header_output, decoder_output, exec_output, decode_block)
-
-    def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
-        addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
-        addrCalcImm = 'EA = Rs1 + imm + offset;'
-        iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags)
-        iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags)
-        header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm)
-        decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm)
-        decode_block = ROrImmDecode.subst(iop)
-        matcher = re.compile(r'RdTwin')
-        exec_output = ''
-        for microPc in range(2):
-            flag_code = ''
-            pcedCode = ''
-            if (microPc == 1):
-                flag_code = "flags[IsLastMicroOp] = true;"
-                pcedCode = "RdLow = uReg0;\n"
-                pcedCode += matcher.sub("RdHigh", code)
-            else:
-                flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
-                pcedCode = matcher.sub("uReg0", code)
-            iop = InstObjParams(name, Name, 'TwinMem',
-                    {"code": pcedCode, "ea_code": addrCalcReg,
-                    "fault_check": faultCode, "micro_pc": microPc,
-                    "set_flags": flag_code}, opt_flags)
-            iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm',
-                    {"code": pcedCode, "ea_code": addrCalcImm,
-                    "fault_check": faultCode, "micro_pc": microPc,
-                    "set_flags": flag_code}, opt_flags)
-            decoder_output += BlockMemMicroConstructor.subst(iop)
-            decoder_output += BlockMemMicroConstructor.subst(iop_imm)
-            exec_output += doDualSplitExecute(
-                    pcedCode, addrCalcReg, addrCalcImm, LoadFuncs, faultCode,
+                    pcedCode, '', addrCalcReg, addrCalcImm, execute, faultCode,
                     makeMicroName(name, microPc),
                     makeMicroName(name + "Imm", microPc),
                     makeMicroName(Name, microPc),
@@ -515,7 +314,6 @@ let {{
                     asi, opt_flags);
             faultCode = ''
         return (header_output, decoder_output, exec_output, decode_block)
-
 }};
 
 def format BlockLoad(code, asi, *opt_flags) {{
@@ -541,11 +339,3 @@ def format BlockStore(code, asi, *opt_flags) {{
          decode_block) = doBlockMemFormat(code, faultCode,
              StoreFuncs, name, Name, asi, opt_flags)
 }};
-
-def format TwinLoad(code, asi, *opt_flags) {{
-    faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck
-    (header_output,
-     decoder_output,
-     exec_output,
-     decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags)
-}};
index fedece2b898b592fdf11d3f30aa1a6c3f25acfad..db45e226d4a47b1ca72e9701de09a3e3619da1c4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2006 The Regents of The University of Michigan
+// Copyright (c) 2006-2007 The Regents of The University of Michigan
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -42,4 +42,4 @@
 ##include "blockmem.isa"
 
 //Include the load/store and cas memory format
-##include "loadstore.isa"
+##include "swap.isa"
diff --git a/src/arch/sparc/isa/formats/mem/swap.isa b/src/arch/sparc/isa/formats/mem/swap.isa
new file mode 100644 (file)
index 0000000..818597a
--- /dev/null
@@ -0,0 +1,183 @@
+// Copyright (c) 2007 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Gabe Black
+//          Ali Saidi
+
+//This template provides the execute functions for a swap
+def template SwapExecute {{
+        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+                Trace::InstRecord *traceData) const
+        {
+            Fault fault = NoFault;
+            //This is to support the conditional store in cas instructions.
+            //It should be optomized out in all the others
+            bool storeCond = true;
+            Addr EA;
+            %(fp_enable_check)s;
+            %(op_decl)s;
+            uint64_t mem_data;
+
+            %(op_rd)s;
+            %(ea_code)s;
+            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
+            %(fault_check)s;
+            if(fault == NoFault)
+            {
+                %(code)s;
+            }
+            if(storeCond && fault == NoFault)
+            {
+                fault = xc->write((uint%(mem_acc_size)s_t)Mem,
+                        EA, %(asi_val)s, &mem_data);
+            }
+            if(fault == NoFault)
+            {
+                    //Handle the swapping
+                    %(postacc_code)s;
+            }
+            if(fault == NoFault)
+            {
+                    //Write the resulting state to the execution context
+                    %(op_wb)s;
+            }
+
+            return fault;
+        }
+}};
+
+
+def template SwapInitiateAcc {{
+        Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
+                Trace::InstRecord * traceData) const
+        {
+            Fault fault = NoFault;
+            Addr EA;
+            %(fp_enable_check)s;
+            uint64_t mem_data = 0;
+            %(op_decl)s;
+            %(op_rd)s;
+            %(ea_code)s;
+
+            DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
+            %(fault_check)s;
+
+            if(fault == NoFault)
+            {
+                %(code)s;
+            }
+            if(fault == NoFault)
+            {
+                fault = xc->write((uint%(mem_acc_size)s_t)Mem,
+                        EA, %(asi_val)s, &mem_data);
+            }
+            return fault;
+        }
+}};
+
+
+
+def template SwapCompleteAcc {{
+        Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
+                Trace::InstRecord * traceData) const
+        {
+            Fault fault = NoFault;
+            %(op_decl)s;
+
+            uint64_t mem_data = pkt->get<uint%(mem_acc_size)s_t>();
+
+            if(fault == NoFault)
+            {
+                    //Handle the swapping
+                    %(postacc_code)s;
+            }
+            if(fault == NoFault)
+            {
+                    //Write the resulting state to the execution context
+                    %(op_wb)s;
+            }
+
+            return fault;
+        }
+}};
+
+let {{
+    SwapFuncs = [SwapExecute, SwapInitiateAcc, SwapCompleteAcc]
+}};
+
+
+def format Swap(code, postacc_code, mem_flags, *opt_flags) {{
+    mem_flags = makeList(mem_flags)
+    flags = string.join(mem_flags, '|')
+
+    (header_output,
+     decoder_output,
+     exec_output,
+     decode_block) = doMemFormat(code, SwapFuncs, '', name, Name, flags,
+         opt_flags, postacc_code)
+}};
+
+def format SwapAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{
+    mem_flags = makeList(mem_flags)
+    mem_flags.append(asi)
+    flags = string.join(mem_flags, '|')
+    (header_output,
+     decoder_output,
+     exec_output,
+     decode_block) = doMemFormat(code, SwapFuncs, AlternateASIPrivFaultCheck,
+         name, Name, flags, opt_flags, postacc_code)
+}};
+
+
+let {{
+    def doCasFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''):
+        addrCalcReg = 'EA = Rs1;'
+        iop = InstObjParams(name, Name, 'Mem',
+                {"code": code, "postacc_code" : postacc_code,
+                 "fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags)
+        header_output = MemDeclare.subst(iop)
+        decoder_output = BasicConstructor.subst(iop)
+        decode_block = BasicDecode.subst(iop)
+        microParams = {"code": code, "postacc_code" : postacc_code,
+            "ea_code" : addrCalcReg, "fault_check" : faultCode}
+        exec_output = doSplitExecute(execute, name, Name, asi, opt_flags,
+                microParams);
+        return (header_output, decoder_output, exec_output, decode_block)
+}};
+
+
+def format CasAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{
+    mem_flags = makeList(mem_flags)
+    mem_flags.append(asi)
+    flags = string.join(mem_flags, '|')
+    (header_output,
+     decoder_output,
+     exec_output,
+     decode_block) = doCasFormat(code, SwapFuncs, AlternateASIPrivFaultCheck,
+         name, Name, flags, opt_flags, postacc_code)
+}};
+
+
index dbaabdca4ecdc3fd57cecf964f775c8d21e45fdb..1d884d6c32460f9b224e9e1d82f1a643b35bd0c1 100644 (file)
@@ -149,7 +149,7 @@ def template LoadExecute {{
             %(fault_check)s;
             if(fault == NoFault)
             {
-                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
+                fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s);
             }
             if(fault == NoFault)
             {
@@ -179,7 +179,7 @@ def template LoadInitiateAcc {{
             %(fault_check)s;
             if(fault == NoFault)
             {
-                fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
+                fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s);
             }
             return fault;
         }
@@ -246,6 +246,7 @@ def template StoreInitiateAcc {{
             Addr EA;
             %(fp_enable_check)s;
             %(op_decl)s;
+
             %(op_rd)s;
             %(ea_code)s;
             DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
@@ -290,6 +291,7 @@ def template CompleteAccDeclare {{
 let {{
     LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
     StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
+
     # The LSB can be zero, since it's really the MSB in doubles and quads
     # and we're dealing with doubles
     BlockAlignmentFaultCheck = '''
@@ -337,14 +339,14 @@ let {{
         return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
 
 
-    def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
+    def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute,
             faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
         executeCode = ''
         for (eaCode, name, Name) in (
                 (eaRegCode, nameReg, NameReg),
                 (eaImmCode, nameImm, NameImm)):
-            microParams = {"code": code, "ea_code": eaCode,
-                "fault_check": faultCode}
+            microParams = {"code": code, "postacc_code" : postacc_code,
+                "ea_code": eaCode, "fault_check": faultCode}
             executeCode += doSplitExecute(execute, name, Name,
                     asi, opt_flags, microParams)
         return executeCode
index d2ef6715496c3e0fa324e4fcf617966971dda9dc..b46ef011e3b2028ec71d78dd0965d0b66fd0b921 100644 (file)
@@ -74,6 +74,7 @@ output exec {{
 
 #include <cmath>
 #include "arch/sparc/asi.hh"
+#include "base/bigint.hh"
 #include "cpu/base.hh"
 #include "cpu/exetrace.hh"
 #include "sim/sim_exit.hh"
index 14005501001d2df89768530fc143856f7ea468fb..f624c3e2b3ad458e928aab33004f9df0736cff0f 100644 (file)
@@ -37,6 +37,7 @@ def operand_types {{
     'uw' : ('unsigned int', 32),
     'sdw' : ('signed int', 64),
     'udw' : ('unsigned int', 64),
+    'tudw' : ('twin int', 64),
     'sf' : ('float', 32),
     'df' : ('float', 64),
     'qf' : ('float', 128)
index 88fb241534b6c4bbbdd846368cb807a5125f85d3..15386adcafbec240a08190a362f65d73e91d6281 100644 (file)
@@ -32,6 +32,7 @@
 #define __ARCH_SPARC_TYPES_HH__
 
 #include <inttypes.h>
+#include "base/bigint.hh"
 
 namespace SparcISA
 {
@@ -39,6 +40,7 @@ namespace SparcISA
     typedef uint64_t ExtMachInst;
 
     typedef uint64_t IntReg;
+    typedef Twin64_t LargestRead;
     typedef uint64_t MiscReg;
     typedef double FloatReg;
     typedef uint64_t FloatRegBits;
diff --git a/src/base/bigint.hh b/src/base/bigint.hh
new file mode 100644 (file)
index 0000000..aa60eeb
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#ifndef __BASE_BIGINT_HH__
+#define __BASE_BIGINT_HH__
+// Create a couple of large int types for atomic reads
+struct m5_twin64_t {
+    uint64_t a;
+    uint64_t b;
+    inline m5_twin64_t& operator=(const uint64_t x)
+    {
+        a = x;
+        b = x;
+        return *this;
+    }
+};
+
+// This is for twin loads (two 64 bit values), not 1 128 bit value (as far as
+// endian conversion is concerned!
+typedef m5_twin64_t Twin64_t;
+
+
+#endif // __BASE_BIGINT_HH__
+
index 515cd0836bd05befbf6c2b60e4483dfa297f13a1..9ccdcdccc965f51c08a1aac35942381e2332e72b 100644 (file)
@@ -868,7 +868,7 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
     if (res) {
         // always return some result to keep misspeculated paths
         // (which will ignore faults) deterministic
-        *res = (fault == NoFault) ? req->getScResult() : 0;
+        *res = (fault == NoFault) ? req->getExtraData() : 0;
     }
 
     return fault;
index fa47b0eeee95f9e644dfeba888294e2f47c330db..6904ed936261322e0e695177d5edce7c0e7a63cd 100644 (file)
@@ -31,6 +31,7 @@
 #include "arch/locked_mem.hh"
 #include "arch/mmaped_ipr.hh"
 #include "arch/utility.hh"
+#include "base/bigint.hh"
 #include "cpu/exetrace.hh"
 #include "cpu/simple/atomic.hh"
 #include "mem/packet.hh"
@@ -151,6 +152,8 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
     data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
     data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq,
                                 Packet::Broadcast);
+    data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq,
+                                Packet::Broadcast);
 }
 
 
@@ -316,6 +319,10 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
+template
+Fault
+AtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags);
+
 template
 Fault
 AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
@@ -363,10 +370,15 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
 {
     // use the CPU's statically allocated write request and packet objects
     Request *req = data_write_req;
-    PacketPtr pkt = data_write_pkt;
+    PacketPtr pkt;
 
     req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
 
+    if (req->isSwap())
+        pkt = data_swap_pkt;
+    else
+        pkt = data_write_pkt;
+
     if (traceData) {
         traceData->setAddr(addr);
     }
@@ -381,6 +393,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
         if (req->isLocked()) {
             do_access = TheISA::handleLockedWrite(thread, req);
         }
+        if (req->isCondSwap()) {
+             assert(res);
+             req->setExtraData(*res);
+        }
+
 
         if (do_access) {
             pkt->reinitFromRequest();
@@ -401,14 +418,19 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
 #endif
         }
 
+        if (req->isSwap()) {
+            assert(res);
+            *res = pkt->get<T>();
+        }
+
         if (req->isLocked()) {
-            uint64_t scResult = req->getScResult();
+            uint64_t scResult = req->getExtraData();
             if (scResult != 0) {
                 // clear failure counter
                 thread->setStCondFailures(0);
             }
             if (res) {
-                *res = req->getScResult();
+                *res = req->getExtraData();
             }
         }
     }
index 42c7bf23a611defb8e3e74bd7a2a44ff5095a7ef..5bffb76667c4e378cde600199e979bc313b9df11 100644 (file)
@@ -118,6 +118,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     PacketPtr data_read_pkt;
     Request  *data_write_req;
     PacketPtr data_write_pkt;
+    PacketPtr data_swap_pkt;
 
     bool dcache_access;
     Tick dcache_latency;
index c4853b916bebfda1c58bfd2b29c30406e3e8bddf..b7d93c7020a0314579cc5874bf883f9368e4dd3c 100644 (file)
@@ -125,7 +125,7 @@ class BaseSimpleCPU : public BaseCPU
     MachInst inst;
 
     // Static data storage
-    TheISA::IntReg dataReg;
+    TheISA::LargestRead dataReg;
 
     StaticInstPtr curStaticInst;
     StaticInstPtr curMacroStaticInst;
index e4748c966fc8d004dce7dfab5a5a0f093b42e034..ff3606a74b56d6dfe10f7cf1a4e4818aa912d333 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "arch/locked_mem.hh"
 #include "arch/utility.hh"
+#include "base/bigint.hh"
 #include "cpu/exetrace.hh"
 #include "cpu/simple/timing.hh"
 #include "mem/packet.hh"
@@ -310,6 +311,10 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
+template
+Fault
+TimingSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags);
+
 template
 Fault
 TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
@@ -359,13 +364,20 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
         new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
                     cpu_id, /* thread ID */ 0);
 
+    if (traceData) {
+        traceData->setAddr(req->getVaddr());
+    }
+
     // translate to physical address
     Fault fault = thread->translateDataWriteReq(req);
 
     // Now do the access.
     if (fault == NoFault) {
         assert(dcache_pkt == NULL);
-        dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast);
+        if (req->isSwap())
+            dcache_pkt = new Packet(req, MemCmd::SwapReq, Packet::Broadcast);
+        else
+            dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast);
         dcache_pkt->allocate();
         dcache_pkt->set(data);
 
@@ -374,6 +386,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
         if (req->isLocked()) {
             do_access = TheISA::handleLockedWrite(thread, req);
         }
+        if (req->isCondSwap()) {
+             assert(res);
+             req->setExtraData(*res);
+        }
 
         if (do_access) {
             if (!dcachePort.sendTiming(dcache_pkt)) {
index 7b999e4b1f655388174f73849fb4975175520a34..a4df1b03ffd45a195c9d4367adad25d5873b10b0 100644 (file)
@@ -249,7 +249,7 @@ class CacheBlk
                 }
             }
 
-            req->setScResult(success ? 1 : 0);
+            req->setExtraData(success ? 1 : 0);
             clearLoadLocks();
             return success;
         } else {
index ff35a07495700210bf412b060f0aa1b1d4cc7553..dac2b93a43f63c96389674deffa1ea39b6d82eee 100644 (file)
@@ -206,7 +206,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
         // complete miss (no matching block)
         if (pkt->req->isLocked() && pkt->isWrite()) {
             // miss on store conditional... just give up now
-            pkt->req->setScResult(0);
+            pkt->req->setExtraData(0);
             pkt->flags |= SATISFIED;
         }
     }
@@ -1147,7 +1147,7 @@ Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt)
     }
 
     if (pkt->isWrite() && (pkt->req->isLocked())) {
-        pkt->req->setScResult(1);
+        pkt->req->setExtraData(1);
     }
     myCache()->access(pkt);
     return true;
index dde6c00d597d94d2118bb6ba3e173b722d310283..14d08db1b2eb37dde24b7925e9a4afa77088cce4 100644 (file)
@@ -94,7 +94,13 @@ MemCmd::commandInfo[] =
             ReadExResp, "ReadExReq" },
     /* ReadExResp */
     { SET4(IsRead, IsInvalidate, IsResponse, HasData),
-            InvalidCmd, "ReadExResp" }
+            InvalidCmd, "ReadExResp" },
+    /* SwapReq -- for Swap ldstub type operations */
+    { SET4(IsReadWrite, IsRequest, HasData, NeedsResponse),
+        SwapResp, "SwapReq" },
+    /* SwapResp -- for Swap ldstub type operations */
+    { SET3(IsReadWrite, IsResponse, HasData),
+        InvalidCmd, "SwapResp" }
 };
 
 
@@ -238,9 +244,11 @@ operator<<(std::ostream &o, const Packet &p)
     if (p.isRead())
         o << "Read ";
     if (p.isWrite())
-        o << "Read ";
+        o << "Write ";
+    if (p.isReadWrite())
+        o << "Read/Write ";
     if (p.isInvalidate())
-        o << "Read ";
+        o << "Invalidate ";
     if (p.isRequest())
         o << "Request ";
     if (p.isResponse())
index 65d2207db54be7475d779a6b95403feebf5d0a6c..16410594ae92f802a8cdaa24ad68a93b62fb1468 100644 (file)
@@ -88,6 +88,8 @@ class MemCmd
         UpgradeReq,
         ReadExReq,
         ReadExResp,
+        SwapReq,
+        SwapResp,
         NUM_MEM_CMDS
     };
 
@@ -106,6 +108,7 @@ class MemCmd
         IsHWPrefetch,
         IsUpgrade,
         HasData,
+        IsReadWrite,
         NUM_COMMAND_ATTRIBUTES
     };
 
@@ -141,6 +144,7 @@ class MemCmd
     bool needsResponse() const  { return testCmdAttrib(NeedsResponse); }
     bool isInvalidate() const   { return testCmdAttrib(IsInvalidate); }
     bool hasData() const        { return testCmdAttrib(HasData); }
+    bool isReadWrite() const    { return testCmdAttrib(IsReadWrite); }
 
     const Command responseCommand() const {
         return commandInfo[cmd].response;
@@ -300,6 +304,7 @@ class Packet
     bool needsResponse() const  { return cmd.needsResponse(); }
     bool isInvalidate() const   { return cmd.isInvalidate(); }
     bool hasData() const        { return cmd.hasData(); }
+    bool isReadWrite() const    { return cmd.isReadWrite(); }
 
     bool isCacheFill() const    { return (flags & CACHE_LINE_FILL) != 0; }
     bool isNoAllocate() const   { return (flags & NO_ALLOCATE) != 0; }
index aac0c3ae5683b3a7f6f64ef2e68646402e1095e7..882aa98d0c94e57296fb3c203e660765828fe8f6 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include "arch/isa_traits.hh"
+#include "base/bigint.hh"
 #include "mem/packet.hh"
 #include "sim/byteswap.hh"
 
 // these functions and make the users do their own byte swapping since
 // the memory system does not in fact have an endianness.
 
+template<>
+inline Twin64_t
+Packet::get()
+{
+    Twin64_t d;
+    assert(staticData || dynamicData);
+    assert(sizeof(Twin64_t) <= size);
+    d.a = TheISA::gtoh(*(uint64_t*)data);
+    d.b = TheISA::gtoh(*((uint64_t*)data + 1));
+    return d;
+}
+
+
 /** return the value of what is pointed to in the packet. */
 template <typename T>
 inline T
index eccd42bec55e9d6ce0f7c28349b4a7c9a0d47f78..381669d4de8be90970022dcc22070d8ffe016e11 100644 (file)
@@ -92,7 +92,7 @@ Addr
 PhysicalMemory::new_page()
 {
     Addr return_addr = pagePtr << LogVMPageSize;
-    return_addr += params()->addrRange.start;
+    return_addr += start();
 
     ++pagePtr;
     return return_addr;
@@ -187,7 +187,7 @@ PhysicalMemory::checkLockedAddrList(Request *req)
     }
 
     if (isLocked) {
-        req->setScResult(success ? 1 : 0);
+        req->setExtraData(success ? 1 : 0);
     }
 
     return success;
@@ -196,16 +196,14 @@ PhysicalMemory::checkLockedAddrList(Request *req)
 void
 PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
 {
-    assert(pkt->getAddr() >= params()->addrRange.start &&
-           pkt->getAddr() + pkt->getSize() <= params()->addrRange.start +
-           params()->addrRange.size());
+    assert(pkt->getAddr() >= start() &&
+           pkt->getAddr() + pkt->getSize() <= start() + size());
 
     if (pkt->isRead()) {
         if (pkt->req->isLocked()) {
             trackLoadLocked(pkt->req);
         }
-        memcpy(pkt->getPtr<uint8_t>(),
-               pmemAddr + pkt->getAddr() - params()->addrRange.start,
+        memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
                pkt->getSize());
 #if TRACING_ON
         switch (pkt->getSize()) {
@@ -233,8 +231,8 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
     }
     else if (pkt->isWrite()) {
         if (writeOK(pkt->req)) {
-            memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
-                   pkt->getPtr<uint8_t>(), pkt->getSize());
+                memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(),
+                        pkt->getSize());
 #if TRACING_ON
             switch (pkt->getSize()) {
               case sizeof(uint64_t):
@@ -259,12 +257,77 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
             }
 #endif
         }
-    }
-    else if (pkt->isInvalidate()) {
+    } else if (pkt->isInvalidate()) {
         //upgrade or invalidate
         pkt->flags |= SATISFIED;
-    }
-    else {
+    } else if (pkt->isReadWrite()) {
+        IntReg overwrite_val;
+        bool overwrite_mem;
+        uint64_t condition_val64;
+        uint32_t condition_val32;
+        uint64_t test_val64;
+        uint32_t test_val32;
+
+        assert(sizeof(IntReg) >= pkt->getSize());
+
+        overwrite_mem = true;
+        // keep a copy of our possible write value, and copy what is at the
+        // memory address into the packet
+        memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
+        memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
+               pkt->getSize());
+
+        if (pkt->req->isCondSwap()) {
+            if (pkt->getSize() == sizeof(uint64_t)) {
+                condition_val64 = htog(pkt->req->getExtraData());
+                memcpy(&test_val64, pmemAddr + pkt->getAddr() - start(), sizeof(uint64_t));
+                overwrite_mem = test_val64 == condition_val64;
+            } else if (pkt->getSize() == sizeof(uint32_t)) {
+                condition_val32 = htog((uint32_t)pkt->req->getExtraData());
+                memcpy(&test_val32, pmemAddr + pkt->getAddr() - start(), sizeof(uint32_t));
+                overwrite_mem = test_val32 == condition_val32;
+            } else
+                panic("Invalid size for conditional read/write\n");
+        }
+
+        if (overwrite_mem)
+            memcpy(pmemAddr + pkt->getAddr() - start(),
+               &overwrite_val, pkt->getSize());
+
+#if TRACING_ON
+        switch (pkt->getSize()) {
+          case sizeof(uint64_t):
+            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
+                    pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
+            DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
+                    overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
+                    condition_val64, overwrite_mem ? "happened" : "didn't happen");
+            break;
+          case sizeof(uint32_t):
+            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
+                    pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
+            DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
+                    overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
+                    condition_val32, overwrite_mem ? "happened" : "didn't happen");
+            break;
+          case sizeof(uint16_t):
+            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
+                    pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
+            DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
+                    overwrite_mem);
+            break;
+          case sizeof(uint8_t):
+            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
+                    pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
+            DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
+                    overwrite_mem);
+            break;
+          default:
+            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n",
+                    pkt->getSize(), pkt->getAddr());
+        }
+#endif
+    } else {
         panic("unimplemented");
     }
 
@@ -315,7 +378,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
 {
     snoop.clear();
     resp.clear();
-    resp.push_back(RangeSize(params()->addrRange.start,
+    resp.push_back(RangeSize(start(),
                              params()->addrRange.size()));
 }
 
index af88bcaa0fdccc8357e68509d5e69cce59810710..f7200b50208dabf694abfc8052aaecfb38154873 100644 (file)
@@ -131,7 +131,7 @@ class PhysicalMemory : public MemObject
             // no locked addrs: nothing to check, store_conditional fails
             bool isLocked = req->isLocked();
             if (isLocked) {
-                req->setScResult(0);
+                req->setExtraData(0);
             }
             return !isLocked; // only do write if not an sc
         } else {
@@ -148,6 +148,7 @@ class PhysicalMemory : public MemObject
   public:
     Addr new_page();
     uint64_t size() { return params()->addrRange.size(); }
+    uint64_t start() { return params()->addrRange.start; }
 
     struct Params
     {
index de0512e1c7d72a690cccf5c3e3df624d1db4fb45..43d8ff1d5c7f300352ac9b30c8ce58787650c01f 100644 (file)
@@ -71,6 +71,10 @@ const uint32_t EVICT_NEXT    = 0x20000;
 const uint32_t NO_ALIGN_FAULT   = 0x40000;
 /** The request was an instruction read. */
 const uint32_t INST_READ        = 0x80000;
+/** This request is for a memory swap. */
+const uint32_t MEM_SWAP         = 0x100000;
+const uint32_t MEM_SWAP_COND    = 0x200000;
+
 
 class Request
 {
@@ -104,8 +108,9 @@ class Request
     /** The virtual address of the request. */
     Addr vaddr;
 
-    /** The return value of store conditional. */
-    uint64_t scResult;
+    /** Extra data for the request, such as the return value of
+     * store conditional or the compare value for a CAS. */
+    uint64_t extraData;
 
     /** The cpu number (for statistics, typically). */
     int cpuNum;
@@ -120,7 +125,7 @@ class Request
     /** Whether or not the asid & vaddr are valid. */
     bool validAsidVaddr;
     /** Whether or not the sc result is valid. */
-    bool validScResult;
+    bool validExData;
     /** Whether or not the cpu number & thread ID are valid. */
     bool validCpuAndThreadNums;
     /** Whether or not the pc is valid. */
@@ -130,7 +135,7 @@ class Request
     /** Minimal constructor.  No fields are initialized. */
     Request()
         : validPaddr(false), validAsidVaddr(false),
-          validScResult(false), validCpuAndThreadNums(false), validPC(false)
+          validExData(false), validCpuAndThreadNums(false), validPC(false)
     {}
 
     /**
@@ -169,7 +174,7 @@ class Request
         validPaddr = true;
         validAsidVaddr = false;
         validPC = false;
-        validScResult = false;
+        validExData = false;
         mmapedIpr = false;
     }
 
@@ -187,7 +192,7 @@ class Request
         validPaddr = false;
         validAsidVaddr = true;
         validPC = true;
-        validScResult = false;
+        validExData = false;
         mmapedIpr = false;
     }
 
@@ -237,12 +242,12 @@ class Request
     void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; }
 
     /** Accessor function to check if sc result is valid. */
-    bool scResultValid() { return validScResult; }
+    bool extraDataValid() { return validExData; }
     /** Accessor function for store conditional return value.*/
-    uint64_t getScResult() { assert(validScResult); return scResult; }
+    uint64_t getExtraData() { assert(validExData); return extraData; }
     /** Accessor function for store conditional return value.*/
-    void setScResult(uint64_t _scResult)
-    { scResult = _scResult; validScResult = true; }
+    void setExtraData(uint64_t _extraData)
+    { extraData = _extraData; validExData = true; }
 
     /** Accessor function for cpu number.*/
     int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; }
@@ -259,6 +264,12 @@ class Request
 
     bool isLocked() { return (getFlags() & LOCKED) != 0; }
 
+    bool isSwap() { return (getFlags() & MEM_SWAP ||
+                            getFlags() & MEM_SWAP_COND); }
+
+    bool isCondSwap() { return (getFlags() & MEM_SWAP_COND) != 0; }
+
+
     friend class Packet;
 };