/*
 * Copyright 2019 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "gtest/gtest.h"
#include "isl/isl.h"

void
PrintTo(const enum isl_aux_op &op, ::std::ostream* os) {
   *os << (const char *[]) {
    [ISL_AUX_OP_ASSERT         ] = "ISL_AUX_OP_ASSERT",
    [ISL_AUX_OP_NONE           ] = "ISL_AUX_OP_NONE",
    [ISL_AUX_OP_FAST_CLEAR     ] = "ISL_AUX_OP_FAST_CLEAR",
    [ISL_AUX_OP_FULL_RESOLVE   ] = "ISL_AUX_OP_FULL_RESOLVE",
    [ISL_AUX_OP_PARTIAL_RESOLVE] = "ISL_AUX_OP_PARTIAL_RESOLVE",
    [ISL_AUX_OP_AMBIGUATE      ] = "ISL_AUX_OP_AMBIGUATE",
   }[op];
}

#define E(state, usage, fc, op) \
   EXPECT_EQ(ISL_AUX_OP_ ## op, \
             isl_aux_prepare_access(ISL_AUX_STATE_ ## state, \
                                    ISL_AUX_USAGE_ ## usage, fc))

TEST(PrepareAccess, CompressedFalseFastClearFalsePartialResolveFalse) {
   E(CLEAR, NONE, false, FULL_RESOLVE);
   E(CLEAR, NONE, true, ASSERT);
   E(PARTIAL_CLEAR, NONE, false, FULL_RESOLVE);
   E(PARTIAL_CLEAR, NONE, true, ASSERT);
   E(COMPRESSED_CLEAR, NONE, false, FULL_RESOLVE);
   E(COMPRESSED_CLEAR, NONE, true, ASSERT);
   E(COMPRESSED_NO_CLEAR, NONE, false, FULL_RESOLVE);
   E(COMPRESSED_NO_CLEAR, NONE, true, ASSERT);
   E(RESOLVED, NONE, false, NONE);
   E(RESOLVED, NONE, true, ASSERT);
   E(PASS_THROUGH, NONE, false, NONE);
   E(PASS_THROUGH, NONE, true, ASSERT);
   E(AUX_INVALID, NONE, false, NONE);
   E(AUX_INVALID, NONE, true, ASSERT);
}

TEST(PrepareAccess, CompressedFalseFastClearTruePartialResolveFalse) {
   E(CLEAR, CCS_D, false, FULL_RESOLVE);
   E(CLEAR, CCS_D, true, NONE);
   E(PARTIAL_CLEAR, CCS_D, false, FULL_RESOLVE);
   E(PARTIAL_CLEAR, CCS_D, true, NONE);
   E(COMPRESSED_CLEAR, CCS_D, false, FULL_RESOLVE);
   E(COMPRESSED_CLEAR, CCS_D, true, FULL_RESOLVE);
   E(COMPRESSED_NO_CLEAR, CCS_D, false, FULL_RESOLVE);
   E(COMPRESSED_NO_CLEAR, CCS_D, true, FULL_RESOLVE);
   E(RESOLVED, CCS_D, false, NONE);
   E(RESOLVED, CCS_D, true, NONE);
   E(PASS_THROUGH, CCS_D, false, NONE);
   E(PASS_THROUGH, CCS_D, true, NONE);
   E(AUX_INVALID, CCS_D, false, AMBIGUATE);
   E(AUX_INVALID, CCS_D, true, AMBIGUATE);
}

TEST(PrepareAccess, CompressedTrueFastClearFalsePartialResolveFalse) {
   E(CLEAR, MC, false, ASSERT);
   E(CLEAR, MC, true, ASSERT);
   E(PARTIAL_CLEAR, MC, false, ASSERT);
   E(PARTIAL_CLEAR, MC, true, ASSERT);
   E(COMPRESSED_CLEAR, MC, false, ASSERT);
   E(COMPRESSED_CLEAR, MC, true, ASSERT);
   E(COMPRESSED_NO_CLEAR, MC, false, NONE);
   E(COMPRESSED_NO_CLEAR, MC, true, ASSERT);
   E(RESOLVED, MC, false, NONE);
   E(RESOLVED, MC, true, ASSERT);
   E(PASS_THROUGH, MC, false, NONE);
   E(PASS_THROUGH, MC, true, ASSERT);
   E(AUX_INVALID, MC, false, AMBIGUATE);
   E(AUX_INVALID, MC, true, ASSERT);
}

TEST(PrepareAccess, CompressedTrueFastClearTruePartialResolveFalse) {
   E(CLEAR, HIZ, false, FULL_RESOLVE);
   E(CLEAR, HIZ, true, NONE);
   E(PARTIAL_CLEAR, HIZ, false, FULL_RESOLVE);
   E(PARTIAL_CLEAR, HIZ, true, NONE);
   E(COMPRESSED_CLEAR, HIZ, false, FULL_RESOLVE);
   E(COMPRESSED_CLEAR, HIZ, true, NONE);
   E(COMPRESSED_NO_CLEAR, HIZ, false, NONE);
   E(COMPRESSED_NO_CLEAR, HIZ, true, NONE);
   E(RESOLVED, HIZ, false, NONE);
   E(RESOLVED, HIZ, true, NONE);
   E(PASS_THROUGH, HIZ, false, NONE);
   E(PASS_THROUGH, HIZ, true, NONE);
   E(AUX_INVALID, HIZ, false, AMBIGUATE);
   E(AUX_INVALID, HIZ, true, AMBIGUATE);
}

TEST(PrepareAccess, CompressedTrueFastClearTruePartialResolveTrue) {
   E(CLEAR, MCS, false, PARTIAL_RESOLVE);
   E(CLEAR, MCS, true, NONE);
   E(PARTIAL_CLEAR, MCS, false, PARTIAL_RESOLVE);
   E(PARTIAL_CLEAR, MCS, true, NONE);
   E(COMPRESSED_CLEAR, MCS, false, PARTIAL_RESOLVE);
   E(COMPRESSED_CLEAR, MCS, true, NONE);
   E(COMPRESSED_NO_CLEAR, MCS, false, NONE);
   E(COMPRESSED_NO_CLEAR, MCS, true, NONE);
   E(RESOLVED, MCS, false, NONE);
   E(RESOLVED, MCS, true, NONE);
   E(PASS_THROUGH, MCS, false, NONE);
   E(PASS_THROUGH, MCS, true, NONE);
   E(AUX_INVALID, MCS, false, AMBIGUATE);
   E(AUX_INVALID, MCS, true, AMBIGUATE);
}

void
PrintTo(const enum isl_aux_state &state, ::std::ostream* os) {
   *os << (const char *[]) {
    [ISL_AUX_STATE_ASSERT             ] = "ISL_AUX_STATE_ASSERT",
    [ISL_AUX_STATE_CLEAR              ] = "ISL_AUX_STATE_CLEAR",
    [ISL_AUX_STATE_PARTIAL_CLEAR      ] = "ISL_AUX_STATE_PARTIAL_CLEAR",
    [ISL_AUX_STATE_COMPRESSED_CLEAR   ] = "ISL_AUX_STATE_COMPRESSED_CLEAR",
    [ISL_AUX_STATE_COMPRESSED_NO_CLEAR] = "ISL_AUX_STATE_COMPRESSED_NO_CLEAR",
    [ISL_AUX_STATE_RESOLVED           ] = "ISL_AUX_STATE_RESOLVED",
    [ISL_AUX_STATE_PASS_THROUGH       ] = "ISL_AUX_STATE_PASS_THROUGH",
    [ISL_AUX_STATE_AUX_INVALID        ] = "ISL_AUX_STATE_AUX_INVALID"
   }[state];
}

#undef E
#define E(state1, usage, op, state2) \
   EXPECT_EQ(ISL_AUX_STATE_ ## state2, \
             isl_aux_state_transition_aux_op(ISL_AUX_STATE_ ## state1, \
                                             ISL_AUX_USAGE_ ## usage, \
                                             ISL_AUX_OP_ ## op))

/* The usages used in each test of this suite represent all combinations of
 * ::fast_clear and ::full_resolves_ambiguate.
 */
TEST(StateTransitionAuxOp, None) {
   E(CLEAR, NONE, NONE, ASSERT);
   E(PARTIAL_CLEAR, NONE, NONE, ASSERT);
   E(COMPRESSED_CLEAR, NONE, NONE, ASSERT);
   E(COMPRESSED_NO_CLEAR, NONE, NONE, ASSERT);
   E(RESOLVED, NONE, NONE, RESOLVED);
   E(PASS_THROUGH, NONE, NONE, PASS_THROUGH);
   E(AUX_INVALID, NONE, NONE, AUX_INVALID);

   E(CLEAR, MC, NONE, ASSERT);
   E(PARTIAL_CLEAR, MC, NONE, ASSERT);
   E(COMPRESSED_CLEAR, MC, NONE, ASSERT);
   E(COMPRESSED_NO_CLEAR, MC, NONE, COMPRESSED_NO_CLEAR);
   E(RESOLVED, MC, NONE, RESOLVED);
   E(PASS_THROUGH, MC, NONE, PASS_THROUGH);
   E(AUX_INVALID, MC, NONE, AUX_INVALID);

   E(CLEAR, HIZ, NONE, CLEAR);
   E(PARTIAL_CLEAR, HIZ, NONE, PARTIAL_CLEAR);
   E(COMPRESSED_CLEAR, HIZ, NONE, COMPRESSED_CLEAR);
   E(COMPRESSED_NO_CLEAR, HIZ, NONE, COMPRESSED_NO_CLEAR);
   E(RESOLVED, HIZ, NONE, RESOLVED);
   E(PASS_THROUGH, HIZ, NONE, PASS_THROUGH);
   E(AUX_INVALID, HIZ, NONE, AUX_INVALID);

   E(CLEAR, CCS_E, NONE, CLEAR);
   E(PARTIAL_CLEAR, CCS_E, NONE, PARTIAL_CLEAR);
   E(COMPRESSED_CLEAR, CCS_E, NONE, COMPRESSED_CLEAR);
   E(COMPRESSED_NO_CLEAR, CCS_E, NONE, COMPRESSED_NO_CLEAR);
   E(RESOLVED, CCS_E, NONE, RESOLVED);
   E(PASS_THROUGH, CCS_E, NONE, PASS_THROUGH);
   E(AUX_INVALID, CCS_E, NONE, AUX_INVALID);
}

TEST(StateTransitionAuxOp, FastClear) {
   E(CLEAR, NONE, FAST_CLEAR, ASSERT);
   E(PARTIAL_CLEAR, NONE, FAST_CLEAR, ASSERT);
   E(COMPRESSED_CLEAR, NONE, FAST_CLEAR, ASSERT);
   E(COMPRESSED_NO_CLEAR, NONE, FAST_CLEAR, ASSERT);
   E(RESOLVED, NONE, FAST_CLEAR, ASSERT);
   E(PASS_THROUGH, NONE, FAST_CLEAR, ASSERT);
   E(AUX_INVALID, NONE, FAST_CLEAR, ASSERT);

   E(CLEAR, MC, FAST_CLEAR, ASSERT);
   E(PARTIAL_CLEAR, MC, FAST_CLEAR, ASSERT);
   E(COMPRESSED_CLEAR, MC, FAST_CLEAR, ASSERT);
   E(COMPRESSED_NO_CLEAR, MC, FAST_CLEAR, ASSERT);
   E(RESOLVED, MC, FAST_CLEAR, ASSERT);
   E(PASS_THROUGH, MC, FAST_CLEAR, ASSERT);
   E(AUX_INVALID, MC, FAST_CLEAR, ASSERT);

   E(CLEAR, HIZ, FAST_CLEAR, CLEAR);
   E(PARTIAL_CLEAR, HIZ, FAST_CLEAR, CLEAR);
   E(COMPRESSED_CLEAR, HIZ, FAST_CLEAR, CLEAR);
   E(COMPRESSED_NO_CLEAR, HIZ, FAST_CLEAR, CLEAR);
   E(RESOLVED, HIZ, FAST_CLEAR, CLEAR);
   E(PASS_THROUGH, HIZ, FAST_CLEAR, CLEAR);
   E(AUX_INVALID, HIZ, FAST_CLEAR, CLEAR);

   E(CLEAR, CCS_E, FAST_CLEAR, CLEAR);
   E(PARTIAL_CLEAR, CCS_E, FAST_CLEAR, CLEAR);
   E(COMPRESSED_CLEAR, CCS_E, FAST_CLEAR, CLEAR);
   E(COMPRESSED_NO_CLEAR, CCS_E, FAST_CLEAR, CLEAR);
   E(RESOLVED, CCS_E, FAST_CLEAR, CLEAR);
   E(PASS_THROUGH, CCS_E, FAST_CLEAR, CLEAR);
   E(AUX_INVALID, CCS_E, FAST_CLEAR, CLEAR);
}

TEST(StateTransitionAuxOp, PartialResolve) {
   E(CLEAR, NONE, PARTIAL_RESOLVE, ASSERT);
   E(PARTIAL_CLEAR, NONE, PARTIAL_RESOLVE, ASSERT);
   E(COMPRESSED_CLEAR, NONE, PARTIAL_RESOLVE, ASSERT);
   E(COMPRESSED_NO_CLEAR, NONE, PARTIAL_RESOLVE, ASSERT);
   E(RESOLVED, NONE, PARTIAL_RESOLVE, ASSERT);
   E(PASS_THROUGH, NONE, PARTIAL_RESOLVE, ASSERT);
   E(AUX_INVALID, NONE, PARTIAL_RESOLVE, ASSERT);

   E(CLEAR, MC, PARTIAL_RESOLVE, ASSERT);
   E(PARTIAL_CLEAR, MC, PARTIAL_RESOLVE, ASSERT);
   E(COMPRESSED_CLEAR, MC, PARTIAL_RESOLVE, ASSERT);
   E(COMPRESSED_NO_CLEAR, MC, PARTIAL_RESOLVE, ASSERT);
   E(RESOLVED, MC, PARTIAL_RESOLVE, ASSERT);
   E(PASS_THROUGH, MC, PARTIAL_RESOLVE, ASSERT);
   E(AUX_INVALID, MC, PARTIAL_RESOLVE, ASSERT);

   E(CLEAR, HIZ, PARTIAL_RESOLVE, ASSERT);
   E(PARTIAL_CLEAR, HIZ, PARTIAL_RESOLVE, ASSERT);
   E(COMPRESSED_CLEAR, HIZ, PARTIAL_RESOLVE, ASSERT);
   E(COMPRESSED_NO_CLEAR, HIZ, PARTIAL_RESOLVE, ASSERT);
   E(RESOLVED, HIZ, PARTIAL_RESOLVE, ASSERT);
   E(PASS_THROUGH, HIZ, PARTIAL_RESOLVE, ASSERT);
   E(AUX_INVALID, HIZ, PARTIAL_RESOLVE, ASSERT);

   E(CLEAR, CCS_E, PARTIAL_RESOLVE, COMPRESSED_NO_CLEAR);
   E(PARTIAL_CLEAR, CCS_E, PARTIAL_RESOLVE, COMPRESSED_NO_CLEAR);
   E(COMPRESSED_CLEAR, CCS_E, PARTIAL_RESOLVE, COMPRESSED_NO_CLEAR);
   E(COMPRESSED_NO_CLEAR, CCS_E, PARTIAL_RESOLVE, COMPRESSED_NO_CLEAR);
   E(RESOLVED, CCS_E, PARTIAL_RESOLVE, RESOLVED);
   E(PASS_THROUGH, CCS_E, PARTIAL_RESOLVE, PASS_THROUGH);
   E(AUX_INVALID, CCS_E, PARTIAL_RESOLVE, ASSERT);
}

TEST(StateTransitionAuxOp, FullResolve) {
   E(CLEAR, NONE, FULL_RESOLVE, ASSERT);
   E(PARTIAL_CLEAR, NONE, FULL_RESOLVE, ASSERT);
   E(COMPRESSED_CLEAR, NONE, FULL_RESOLVE, ASSERT);
   E(COMPRESSED_NO_CLEAR, NONE, FULL_RESOLVE, ASSERT);
   E(RESOLVED, NONE, FULL_RESOLVE, ASSERT);
   E(PASS_THROUGH, NONE, FULL_RESOLVE, ASSERT);
   E(AUX_INVALID, NONE, FULL_RESOLVE, ASSERT);

   E(CLEAR, MC, FULL_RESOLVE, ASSERT);
   E(PARTIAL_CLEAR, MC, FULL_RESOLVE, ASSERT);
   E(COMPRESSED_CLEAR, MC, FULL_RESOLVE, ASSERT);
   E(COMPRESSED_NO_CLEAR, MC, FULL_RESOLVE, PASS_THROUGH);
   E(RESOLVED, MC, FULL_RESOLVE, PASS_THROUGH);
   E(PASS_THROUGH, MC, FULL_RESOLVE, PASS_THROUGH);
   E(AUX_INVALID, MC, FULL_RESOLVE, ASSERT);

   E(CLEAR, HIZ, FULL_RESOLVE, RESOLVED);
   E(PARTIAL_CLEAR, HIZ, FULL_RESOLVE, RESOLVED);
   E(COMPRESSED_CLEAR, HIZ, FULL_RESOLVE, RESOLVED);
   E(COMPRESSED_NO_CLEAR, HIZ, FULL_RESOLVE, RESOLVED);
   E(RESOLVED, HIZ, FULL_RESOLVE, RESOLVED);
   E(PASS_THROUGH, HIZ, FULL_RESOLVE, PASS_THROUGH);
   E(AUX_INVALID, HIZ, FULL_RESOLVE, ASSERT);

   E(CLEAR, CCS_E, FULL_RESOLVE, PASS_THROUGH);
   E(PARTIAL_CLEAR, CCS_E, FULL_RESOLVE, PASS_THROUGH);
   E(COMPRESSED_CLEAR, CCS_E, FULL_RESOLVE, PASS_THROUGH);
   E(COMPRESSED_NO_CLEAR, CCS_E, FULL_RESOLVE, PASS_THROUGH);
   E(RESOLVED, CCS_E, FULL_RESOLVE, PASS_THROUGH);
   E(PASS_THROUGH, CCS_E, FULL_RESOLVE, PASS_THROUGH);
   E(AUX_INVALID, CCS_E, FULL_RESOLVE, ASSERT);
}

TEST(StateTransitionAuxOp, Ambiguate) {
   E(CLEAR, NONE, AMBIGUATE, ASSERT);
   E(PARTIAL_CLEAR, NONE, AMBIGUATE, ASSERT);
   E(COMPRESSED_CLEAR, NONE, AMBIGUATE, ASSERT);
   E(COMPRESSED_NO_CLEAR, NONE, AMBIGUATE, ASSERT);
   E(RESOLVED, NONE, AMBIGUATE, ASSERT);
   E(PASS_THROUGH, NONE, AMBIGUATE, ASSERT);
   E(AUX_INVALID, NONE, AMBIGUATE, ASSERT);

   E(CLEAR, MC, AMBIGUATE, ASSERT);
   E(PARTIAL_CLEAR, MC, AMBIGUATE, ASSERT);
   E(COMPRESSED_CLEAR, MC, AMBIGUATE, ASSERT);
   E(COMPRESSED_NO_CLEAR, MC, AMBIGUATE, PASS_THROUGH);
   E(RESOLVED, MC, AMBIGUATE, PASS_THROUGH);
   E(PASS_THROUGH, MC, AMBIGUATE, PASS_THROUGH);
   E(AUX_INVALID, MC, AMBIGUATE, PASS_THROUGH);

   E(CLEAR, HIZ, AMBIGUATE, PASS_THROUGH);
   E(PARTIAL_CLEAR, HIZ, AMBIGUATE, PASS_THROUGH);
   E(COMPRESSED_CLEAR, HIZ, AMBIGUATE, PASS_THROUGH);
   E(COMPRESSED_NO_CLEAR, HIZ, AMBIGUATE, PASS_THROUGH);
   E(RESOLVED, HIZ, AMBIGUATE, PASS_THROUGH);
   E(PASS_THROUGH, HIZ, AMBIGUATE, PASS_THROUGH);
   E(AUX_INVALID, HIZ, AMBIGUATE, PASS_THROUGH);

   E(CLEAR, CCS_E, AMBIGUATE, PASS_THROUGH);
   E(PARTIAL_CLEAR, CCS_E, AMBIGUATE, PASS_THROUGH);
   E(COMPRESSED_CLEAR, CCS_E, AMBIGUATE, PASS_THROUGH);
   E(COMPRESSED_NO_CLEAR, CCS_E, AMBIGUATE, PASS_THROUGH);
   E(RESOLVED, CCS_E, AMBIGUATE, PASS_THROUGH);
   E(PASS_THROUGH, CCS_E, AMBIGUATE, PASS_THROUGH);
   E(AUX_INVALID, CCS_E, AMBIGUATE, PASS_THROUGH);
}

#undef E
#define E(state1, usage, full_surface, state2) \
   EXPECT_EQ(ISL_AUX_STATE_ ## state2, \
             isl_aux_state_transition_write(ISL_AUX_STATE_ ## state1, \
                                            ISL_AUX_USAGE_ ## usage, \
                                            full_surface))

TEST(StateTransitionWrite, WritesOnlyTouchMain) {
   E(CLEAR, NONE, false, ASSERT);
   E(CLEAR, NONE, true, AUX_INVALID);
   E(PARTIAL_CLEAR, NONE, false, ASSERT);
   E(PARTIAL_CLEAR, NONE, true, AUX_INVALID);
   E(COMPRESSED_CLEAR, NONE, false, ASSERT);
   E(COMPRESSED_CLEAR, NONE, true, AUX_INVALID);
   E(COMPRESSED_NO_CLEAR, NONE, false, ASSERT);
   E(COMPRESSED_NO_CLEAR, NONE, true, AUX_INVALID);
   E(RESOLVED, NONE, false, AUX_INVALID);
   E(RESOLVED, NONE, true, AUX_INVALID);
   E(PASS_THROUGH, NONE, false, PASS_THROUGH);
   E(PASS_THROUGH, NONE, true, PASS_THROUGH);
   E(AUX_INVALID, NONE, false, AUX_INVALID);
   E(AUX_INVALID, NONE, true, AUX_INVALID);
}

TEST(StateTransitionWrite, WritesCompress) {
   E(CLEAR, MCS, false, COMPRESSED_CLEAR);
   E(CLEAR, MCS, true, COMPRESSED_NO_CLEAR);
   E(PARTIAL_CLEAR, MCS, false, COMPRESSED_CLEAR);
   E(PARTIAL_CLEAR, MCS, true, COMPRESSED_NO_CLEAR);
   E(COMPRESSED_CLEAR, MCS, false, COMPRESSED_CLEAR);
   E(COMPRESSED_CLEAR, MCS, true, COMPRESSED_NO_CLEAR);
   E(COMPRESSED_NO_CLEAR, MCS, false, COMPRESSED_NO_CLEAR);
   E(COMPRESSED_NO_CLEAR, MCS, true, COMPRESSED_NO_CLEAR);
   E(RESOLVED, MCS, false, COMPRESSED_NO_CLEAR);
   E(RESOLVED, MCS, true, COMPRESSED_NO_CLEAR);
   E(PASS_THROUGH, MCS, false, COMPRESSED_NO_CLEAR);
   E(PASS_THROUGH, MCS, true, COMPRESSED_NO_CLEAR);
   E(AUX_INVALID, MCS, false, ASSERT);
   E(AUX_INVALID, MCS, true, ASSERT);

   E(CLEAR, STC_CCS, false, ASSERT);
   E(CLEAR, STC_CCS, true, ASSERT);
   E(PARTIAL_CLEAR, STC_CCS, false, ASSERT);
   E(PARTIAL_CLEAR, STC_CCS, true, ASSERT);
   E(COMPRESSED_CLEAR, STC_CCS, false, ASSERT);
   E(COMPRESSED_CLEAR, STC_CCS, true, ASSERT);
   E(COMPRESSED_NO_CLEAR, STC_CCS, false, COMPRESSED_NO_CLEAR);
   E(COMPRESSED_NO_CLEAR, STC_CCS, true, COMPRESSED_NO_CLEAR);
   E(RESOLVED, STC_CCS, false, COMPRESSED_NO_CLEAR);
   E(RESOLVED, STC_CCS, true, COMPRESSED_NO_CLEAR);
   E(PASS_THROUGH, STC_CCS, false, COMPRESSED_NO_CLEAR);
   E(PASS_THROUGH, STC_CCS, true, COMPRESSED_NO_CLEAR);
   E(AUX_INVALID, STC_CCS, false, ASSERT);
   E(AUX_INVALID, STC_CCS, true, ASSERT);
}

TEST(StateTransitionWrite, WritesCompressClear) {
   E(CLEAR, FCV_CCS_E, false, COMPRESSED_CLEAR);
   E(CLEAR, FCV_CCS_E, true, COMPRESSED_CLEAR);
   E(PARTIAL_CLEAR, FCV_CCS_E, false, COMPRESSED_CLEAR);
   E(PARTIAL_CLEAR, FCV_CCS_E, true, COMPRESSED_CLEAR);
   E(COMPRESSED_CLEAR, FCV_CCS_E, false, COMPRESSED_CLEAR);
   E(COMPRESSED_CLEAR, FCV_CCS_E, true, COMPRESSED_CLEAR);
   E(COMPRESSED_NO_CLEAR, FCV_CCS_E, false, COMPRESSED_CLEAR);
   E(COMPRESSED_NO_CLEAR, FCV_CCS_E, true, COMPRESSED_CLEAR);
   E(RESOLVED, FCV_CCS_E, false, COMPRESSED_CLEAR);
   E(RESOLVED, FCV_CCS_E, true, COMPRESSED_CLEAR);
   E(PASS_THROUGH, FCV_CCS_E, false, COMPRESSED_CLEAR);
   E(PASS_THROUGH, FCV_CCS_E, true, COMPRESSED_CLEAR);
   E(AUX_INVALID, FCV_CCS_E, false, ASSERT);
   E(AUX_INVALID, FCV_CCS_E, true, ASSERT);
}

TEST(StateTransitionWrite, WritesResolveAmbiguate) {
   E(CLEAR, CCS_D, false, PARTIAL_CLEAR);
   E(CLEAR, CCS_D, true, PASS_THROUGH);
   E(PARTIAL_CLEAR, CCS_D, false, PARTIAL_CLEAR);
   E(PARTIAL_CLEAR, CCS_D, true, PASS_THROUGH);
   E(COMPRESSED_CLEAR, CCS_D, false, ASSERT);
   E(COMPRESSED_CLEAR, CCS_D, true, ASSERT);
   E(COMPRESSED_NO_CLEAR, CCS_D, false, ASSERT);
   E(COMPRESSED_NO_CLEAR, CCS_D, true, ASSERT);
   E(RESOLVED, CCS_D, false, RESOLVED);
   E(RESOLVED, CCS_D, true, PASS_THROUGH);
   E(PASS_THROUGH, CCS_D, false, PASS_THROUGH);
   E(PASS_THROUGH, CCS_D, true, PASS_THROUGH);
   E(AUX_INVALID, CCS_D, false, ASSERT);
   E(AUX_INVALID, CCS_D, true, ASSERT);

   E(CLEAR, MC, false, ASSERT);
   E(CLEAR, MC, true, ASSERT);
   E(PARTIAL_CLEAR, MC, false, ASSERT);
   E(PARTIAL_CLEAR, MC, true, ASSERT);
   E(COMPRESSED_CLEAR, MC, false, ASSERT);
   E(COMPRESSED_CLEAR, MC, true, ASSERT);
   E(COMPRESSED_NO_CLEAR, MC, false, COMPRESSED_NO_CLEAR);
   E(COMPRESSED_NO_CLEAR, MC, true, PASS_THROUGH);
   E(RESOLVED, MC, false, RESOLVED);
   E(RESOLVED, MC, true, PASS_THROUGH);
   E(PASS_THROUGH, MC, false, PASS_THROUGH);
   E(PASS_THROUGH, MC, true, PASS_THROUGH);
   E(AUX_INVALID, MC, false, ASSERT);
   E(AUX_INVALID, MC, true, ASSERT);
}

#undef E
