Exemple #1
0
void ctrl_exception_done(void* desc, void* cpu, integer_t val)
{
  int proc_no = SIM_get_proc_no((conf_object_t*) cpu);
  conf_object_t* cpu_obj = (conf_object_t*) cpu;
  uinteger_t trap_level = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tl")); 
  uinteger_t pc = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "pc"));
  uinteger_t npc = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "npc"));
  uinteger_t tpc = 0;
  uinteger_t tnpc = 0;
  //get the return PC,NPC pair based on the trap level
  ASSERT(1 <= trap_level && trap_level <= 5);
  if(trap_level == 1){
    tpc =  SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tpc1"));
    tnpc = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tnpc1"));
  }
  if(trap_level == 2){
    tpc =  SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tpc2"));
    tnpc = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tnpc2"));
  }
  if(trap_level == 3){
    tpc =  SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tpc3"));
    tnpc = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tnpc3"));
  }
  if(trap_level == 4){
    tpc =  SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tpc4"));
    tnpc = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tnpc4"));
  }
  if(trap_level == 5){
    tpc =  SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tpc5"));
    tnpc = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "tnpc5"));
  }
  
  if (!XACT_MEMORY) return;
  TransactionInterfaceManager *xact_mgr = XACT_MGR;

  int smt_thread_num = proc_no % RubyConfig::numberofSMTThreads();
  // The simulated processor number
  int sim_proc_no = proc_no / RubyConfig::numberofSMTThreads();

  if (proc_no != SIMICS_current_processor_number()){
    WARN_EXPR(proc_no);
    WARN_EXPR(SIMICS_current_processor_number());
    WARN_MSG("Callback for a different processor");
  }  

  g_system_ptr->getProfiler()->profileExceptionDone(xact_mgr->getTransactionLevel(smt_thread_num) > 0, sim_proc_no, smt_thread_num, val, trap_level, pc, npc, tpc, tnpc);

  if((val >= 0x80 && val <= 0x9f) || (val >= 0xc0 && val <= 0xdf)){
    //xact_mgr->clearLoggedException(smt_thread_num);
  }

  if ((val == 0x122) && xact_mgr->shouldTrap(smt_thread_num)){
    // use software handler
    if (xact_mgr->shouldUseHardwareAbort(smt_thread_num)){
        xact_mgr->hardwareAbort(smt_thread_num);
    } else {          
      xact_mgr->trapToHandler(smt_thread_num);
    }  
  }
}
/* Calculate whether an assertion is a standard GObject type check.
 * .e.g. NSPACE_IS_OBJ(x).
 *
 * This is complicated by the fact that type checking is done by macros, which
 * expand to something like:
 * (((__extension__ ({
 *    GTypeInstance *__inst = (GTypeInstance *)((x));
 *    GType __t = ((nspace_obj_get_type()));
 *    gboolean __r;
 *    if (!__inst)
 *        __r = (0);
 *    else if (__inst->g_class && __inst->g_class->g_type == __t)
 *        __r = (!(0));
 *    else
 *        __r = g_type_check_instance_is_a(__inst, __t);
 *    __r;
 * }))))
 *
 * Insert the ValueDecls of the variables being checked into the provided
 * unordered_set, and return the number of such insertions (this will be 0 if no
 * variables are type checked). The returned number may be an over-estimate
 * of the number of elements in the set, as it doesn’t account for
 * duplicates. */
static unsigned int
_assertion_is_gobject_type_check (Expr& assertion_expr,
                                  const ASTContext& context,
                                  std::unordered_set<const ValueDecl*>& ret)
{
	DEBUG_EXPR (__func__ << ": ", assertion_expr);

	switch ((int) assertion_expr.getStmtClass ()) {
	case Expr::StmtExprClass: {
		/* Parse all the way through the statement expression, checking
		 * if the first statement is an assignment to the __inst
		 * variable, as in the macro expansion given above.
		 *
		 * This is a particularly shoddy way of checking for a GObject
		 * type check (we should really check for a
		 * g_type_check_instance_is_a() call) but this will do for
		 * now. */
		StmtExpr& stmt_expr = cast<StmtExpr> (assertion_expr);
		CompoundStmt* compound_stmt = stmt_expr.getSubStmt ();
		const Stmt* first_stmt = *(compound_stmt->body_begin ());

		if (first_stmt->getStmtClass () != Expr::DeclStmtClass)
			return 0;

		const DeclStmt& decl_stmt = cast<DeclStmt> (*first_stmt);
		const VarDecl* decl =
			dyn_cast<VarDecl> (decl_stmt.getSingleDecl ());

		if (decl == NULL)
			return 0;

		if (decl->getNameAsString () != "__inst")
			return 0;

		const Expr* init =
			decl->getAnyInitializer ()->IgnoreParenCasts ();
		const DeclRefExpr* decl_expr = dyn_cast<DeclRefExpr> (init);
		if (decl_expr != NULL) {
			ret.insert (decl_expr->getDecl ());
			return 1;
		}

		return 0;
	}
	case Expr::IntegerLiteralClass:
	case Expr::BinaryOperatorClass:
	case Expr::UnaryOperatorClass:
	case Expr::ConditionalOperatorClass:
	case Expr::CallExprClass:
	case Expr::ImplicitCastExprClass: {
		/* These can’t be type checks. */
		return 0;
	}
	case Stmt::StmtClass::NoStmtClass:
	default:
		WARN_EXPR (__func__ << "() can’t handle expressions of type " <<
		           assertion_expr.getStmtClassName (), assertion_expr);
		return 0;
	}
}
Exemple #3
0
void Tester::checkForDeadlock()
{
  int size = m_last_progress_vector.size();
  Time current_time = g_eventQueue_ptr->getTime();
  for (int processor=0; processor<size; processor++) {
    if ((current_time - m_last_progress_vector[processor]) > g_DEADLOCK_THRESHOLD) {
      WARN_EXPR(current_time);
      WARN_EXPR(m_last_progress_vector[processor]);
      WARN_EXPR(current_time - m_last_progress_vector[processor]);
      WARN_EXPR(processor);
      Sequencer* seq_ptr = g_system_ptr->getChip(processor/RubyConfig::numberOfProcsPerChip())->getSequencer(processor%RubyConfig::numberOfProcsPerChip());
      assert(seq_ptr != NULL);
      WARN_EXPR(*seq_ptr);
#ifdef USE_TOPAZ
      cerr<<"******TOPAZ POST DEADLOCK STATS************"<<endl;
      g_system_ptr->getNetwork()->printStats(cerr);
#endif
		
      ERROR_MSG("Deadlock detected.");
    }
  }
}
void RequestGenerator::wakeup()
{
  DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);

  if (m_status == RequestGeneratorStatus_Thinking) {
    m_status = RequestGeneratorStatus_Test_Pending;
    m_last_transition = g_eventQueue_ptr->getTime();
    initiateTest();  // Test
  } else if (m_status == RequestGeneratorStatus_Holding) {
    m_status = RequestGeneratorStatus_Release_Pending;
    m_last_transition = g_eventQueue_ptr->getTime();
    initiateRelease();  // Release
  } else if (m_status == RequestGeneratorStatus_Before_Swap) {
    m_status = RequestGeneratorStatus_Swap_Pending;
    m_last_transition = g_eventQueue_ptr->getTime();
    initiateSwap();
  } else {
    WARN_EXPR(m_status);
    ERROR_MSG("Invalid status");
  }
}
Exemple #5
0
void Check::performCallback(NodeID proc, SubBlock& data)
{
    Address address = data.getAddress();
    //  assert(getAddress() == address);  // This isn't exactly right since we now have multi-byte checks
    assert(getAddress().getLineAddress() == address.getLineAddress());

    DEBUG_MSG(TESTER_COMP, MedPrio, "Callback");
    DEBUG_EXPR(TESTER_COMP, MedPrio, *this);

    if (m_status == TesterStatus_Action_Pending) {
        DEBUG_MSG(TESTER_COMP, MedPrio, "Action callback");
        // Perform store
        data.setByte(0, m_value+m_store_count); // We store one byte at a time
        m_store_count++;

        if (m_store_count == CHECK_SIZE) {
            m_status = TesterStatus_Ready;
        } else {
            m_status = TesterStatus_Idle;
        }
    } else if (m_status == TesterStatus_Check_Pending) {
        DEBUG_MSG(TESTER_COMP, MedPrio, "Check callback");
        // Perform load/check
        for(int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
            if (uint8(m_value+byte_number) != data.getByte(byte_number) && (DATA_BLOCK == true)) {
                WARN_EXPR(proc);
                WARN_EXPR(address);
                WARN_EXPR(data);
                WARN_EXPR(byte_number);
                WARN_EXPR((int)m_value+byte_number);
                WARN_EXPR((int)data.getByte(byte_number));
                WARN_EXPR(*this);
                WARN_EXPR(g_eventQueue_ptr->getTime());
                ERROR_MSG("Action/check failure");
            }
        }
        DEBUG_MSG(TESTER_COMP, HighPrio, "Action/check success:");
        DEBUG_EXPR(TESTER_COMP, HighPrio, *this);
        DEBUG_EXPR(TESTER_COMP, MedPrio, data);

        m_status = TesterStatus_Idle;
        pickValue();

    } else {
        WARN_EXPR(*this);
        WARN_EXPR(proc);
        WARN_EXPR(data);
        WARN_EXPR(m_status);
        WARN_EXPR(g_eventQueue_ptr->getTime());
        ERROR_MSG("Unexpected TesterStatus");
    }

    DEBUG_EXPR(TESTER_COMP, MedPrio, proc);
    DEBUG_EXPR(TESTER_COMP, MedPrio, data);
    DEBUG_EXPR(TESTER_COMP, MedPrio, getAddress().getLineAddress());
    DEBUG_MSG(TESTER_COMP, MedPrio, "Callback done");
    DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
}
/* Calculate whether an assertion is a standard non-NULL check.
 * e.g. (x != NULL), (x), (x != NULL && …) or (x && …).
 *
 * Insert the ValueDecls of the variables being checked into the provided
 * unordered_set, and return the number of such insertions (this will be 0 if no
 * variables are non-NULL checked). The returned number may be an over-estimate
 * of the number of elements in the set, as it doesn’t account for
 * duplicates. */
static unsigned int
_assertion_is_explicit_nonnull_check (Expr& assertion_expr,
                                      const ASTContext& context,
                                      std::unordered_set<const ValueDecl*>& ret)
{
	DEBUG_EXPR (__func__ << ": ", assertion_expr);

	switch ((int) assertion_expr.getStmtClass ()) {
	case Expr::BinaryOperatorClass: {
		BinaryOperator& bin_expr =
			cast<BinaryOperator> (assertion_expr);
		BinaryOperatorKind opcode = bin_expr.getOpcode ();

		if (opcode == BinaryOperatorKind::BO_LAnd) {
			/* LHS && RHS */
			unsigned int lhs_count =
				AssertionExtracter::assertion_is_nonnull_check (*(bin_expr.getLHS ()), context, ret);
			unsigned int rhs_count =
				AssertionExtracter::assertion_is_nonnull_check (*(bin_expr.getRHS ()), context, ret);

			return lhs_count + rhs_count;
		} else if (opcode == BinaryOperatorKind::BO_LOr) {
			/* LHS || RHS */
			std::unordered_set<const ValueDecl*> lhs_vars, rhs_vars;

			unsigned int lhs_count =
				AssertionExtracter::assertion_is_nonnull_check (*(bin_expr.getLHS ()), context, lhs_vars);
			unsigned int rhs_count =
				AssertionExtracter::assertion_is_nonnull_check (*(bin_expr.getRHS ()), context, rhs_vars);

			std::set_intersection (lhs_vars.begin (),
			                       lhs_vars.end (),
			                       rhs_vars.begin (),
			                       rhs_vars.end (),
			                       std::inserter (ret, ret.end ()));

			return lhs_count + rhs_count;
		} else if (opcode == BinaryOperatorKind::BO_NE) {
			/* LHS != RHS */
			Expr* rhs = bin_expr.getRHS ();
			Expr::NullPointerConstantKind k =
				rhs->isNullPointerConstant (const_cast<ASTContext&> (context),
				                            Expr::NullPointerConstantValueDependence::NPC_ValueDependentIsNotNull);
			if (k != Expr::NullPointerConstantKind::NPCK_NotNull &&
			    bin_expr.getLHS ()->IgnoreParenCasts ()->getStmtClass () == Expr::DeclRefExprClass) {
				DEBUG ("Found non-NULL check.");
				ret.insert (cast<DeclRefExpr> (bin_expr.getLHS ()->IgnoreParenCasts ())->getDecl ());
				return 1;
			}

			/* Either not a comparison to NULL, or the expr being
			 * compared is not a DeclRefExpr. */
			return 0;
		}

		return 0;
	}
	case Expr::UnaryOperatorClass: {
		/* A unary operator. For the moment, assume this isn't a
		 * non-null check.
		 *
		 * FIXME: In the future, define a proper program transformation
		 * to check for non-null checks, since we could have expressions
		 * like:
		 *     !(my_var == NULL)
		 * or (more weirdly):
		 *     ~(my_var == NULL)
		 */
		return 0;
	}
	case Expr::ConditionalOperatorClass: {
		/* A conditional operator. For the moment, assume this isn’t a
		 * non-null check.
		 *
		 * FIXME: In the future, define a proper program transformation
		 * to check for non-null checks, since we could have expressions
		 * like:
		 *     (x == NULL) ? TRUE : FALSE
		 */
		return 0;
	}
	case Expr::CStyleCastExprClass:
	case Expr::ImplicitCastExprClass: {
		/* A (explicit or implicit) cast. This can either be:
		 *     (void*)0
		 * or
		 *     (bool)my_var */
		CastExpr& cast_expr = cast<CastExpr> (assertion_expr);
		Expr* sub_expr = cast_expr.getSubExpr ()->IgnoreParenCasts ();

		if (sub_expr->getStmtClass () == Expr::DeclRefExprClass) {
			DEBUG ("Found non-NULL check.");
			ret.insert (cast<DeclRefExpr> (sub_expr)->getDecl ());
			return 1;
		}

		/* Not a cast to NULL, or the expr being casted is not a
		 * DeclRefExpr. */
		return 0;
	}
	case Expr::DeclRefExprClass: {
		/* A variable reference, which will implicitly become a non-NULL
		 * check. */
		DEBUG ("Found non-NULL check.");
		DeclRefExpr& decl_ref_expr = cast<DeclRefExpr> (assertion_expr);
		ret.insert (decl_ref_expr.getDecl ());
		return 1;
	}
	case Expr::StmtExprClass:
		/* FIXME: Statement expressions can be nonnull checks, but
		 * detecting them requires a formal program transformation which
		 * has not been implemented yet. */
	case Expr::CallExprClass:
		/* Function calls can’t be nonnull checks. */
	case Expr::IntegerLiteralClass: {
		/* Integer literals can’t be nonnull checks. */
		return 0;
	}
	case Stmt::StmtClass::NoStmtClass:
	default:
		WARN_EXPR (__func__ << "() can’t handle expressions of type " <<
		           assertion_expr.getStmtClassName (), assertion_expr);
		return 0;
	}
}
/* Does the given statement look like:
 *  • g_return_if_fail(…)
 *  • g_return_val_if_fail(…)
 *  • g_assert(…)
 *  • g_assert_*(…)
 *  • assert(…)
 * This is complicated by the fact that if the gmessages.h header isn’t
 * available, they’ll present as CallExpr function calls with those names; if it
 * is available, they’ll be expanded as macros and turn into DoStmts with misc.
 * rubbish beneath.
 *
 * If the statement changes program state at all, return NULL. Otherwise, return
 * the condition which holds for the assertion to be bypassed (i.e. for the
 * assertion to succeed). This function is built recursively, building a boolean
 * expression for the condition based on avoiding branches which call
 * abort()-like functions.
 *
 * This function is based on a transformation of the AST to an augmented boolean
 * expression, using rules documented in each switch case. In this
 * documentation, calc(S) refers to the transformation function. The augmented
 * boolean expressions can be either NULL, or a normal boolean expression
 * (TRUE, FALSE, ∧, ∨, ¬). NULL is used iff the statement potentially changes
 * program state, and poisons any boolean expression:
 *     B ∧ NULL ≡ NULL
 *     B ∨ NULL ≡ NULL
 *     ¬NULL ≡ NULL
 */
Expr*
AssertionExtracter::is_assertion_stmt (Stmt& stmt, const ASTContext& context)
{
	DEBUG ("Checking " << stmt.getStmtClassName () << " for assertions.");

	/* Slow path: walk through the AST, aborting on statements which
	 * potentially mutate program state, and otherwise trying to find a base
	 * function call such as:
	 *  • g_return_if_fail_warning()
	 *  • g_assertion_message()
	 *  • g_assertion_message_*()
	 */
	switch ((int) stmt.getStmtClass ()) {
	case Stmt::StmtClass::CallExprClass: {
		/* Handle a direct function call.
		 * Transformations:
		 *     [g_return_if_fail|assert|…](C) ↦ C
		 *     [g_return_if_fail_warning|__assert_fail|…](C) ↦ FALSE
		 *     other_funcs(…) ↦ NULL */
		CallExpr& call_expr = cast<CallExpr> (stmt);
		FunctionDecl* func = call_expr.getDirectCallee ();
		if (func == NULL)
			return NULL;

		std::string func_name = func->getNameAsString ();
		DEBUG ("CallExpr to function " << func_name);

		if (_is_assertion_name (func_name)) {
			/* Assertion path where the compiler hasn't seen the
			 * definition of the assertion macro, so still thinks
			 * it's a function.
			 *
			 * Extract the assertion condition as the first function
			 * parameter.
			 *
			 * TODO: May need to fix up the condition for macros
			 * like g_assert_null(). */
			return call_expr.getArg (0);
		} else if (_is_assertion_fail_func_name (func_name)) {
			/* Assertion path where the assertion macro has been
			 * expanded and we're on the assertion failure branch.
			 *
			 * In this case, the assertion condition has been
			 * grabbed from an if statement already, so negate it
			 * (to avoid the failure condition) and return. */
			return new (context)
				IntegerLiteral (context, context.MakeIntValue (0, context.getLogicalOperationType ()),
				                context.getLogicalOperationType (),
				                SourceLocation ());
		}

		/* Not an assertion path. */
		return NULL;
	}
	case Stmt::StmtClass::DoStmtClass: {
		/* Handle a do { … } while (0) block (commonly used to allow
		 * macros to optionally be suffixed by a semicolon).
		 * Transformations:
		 *     do { S } while (0) ↦ calc(S)
		 *     do { S } while (C) ↦ NULL
		 * Note the second condition is overly-conservative. No
		 * solutions for the halting problem here. */
		DoStmt& do_stmt = cast<DoStmt> (stmt);
		Stmt* body = do_stmt.getBody ();
		Stmt* cond = do_stmt.getCond ();
		Expr* expr = dyn_cast<Expr> (cond);
		llvm::APSInt bool_expr;

		if (body != NULL &&
		    expr != NULL &&
		    expr->isIntegerConstantExpr (bool_expr, context) &&
		    !bool_expr.getBoolValue ()) {
			return is_assertion_stmt (*body, context);
		}

		return NULL;
	}
	case Stmt::StmtClass::IfStmtClass: {
		/* Handle an if(…) { … } else { … } block.
		 * Transformations:
		 *     if (C) { S1 } else { S2 } ↦
		 *       (C ∧ calc(S1)) ∨ (¬C ∧ calc(S2))
		 *     if (C) { S } ↦ (C ∧ calc(S)) ∨ ¬C
		 * i.e.
		 *     if (C) { S } ≡ if (C) { S } else {}
		 * where {} is an empty compound statement, below. */
		IfStmt& if_stmt = cast<IfStmt> (stmt);
		assert (if_stmt.getThen () != NULL);

		Expr* neg_cond = _negation_expr (if_stmt.getCond (), context);

		Expr* then_assertion =
			is_assertion_stmt (*(if_stmt.getThen ()), context);
		if (then_assertion == NULL)
			return NULL;

		then_assertion =
			_conjunction_expr (if_stmt.getCond (), then_assertion,
			                   context);

		if (if_stmt.getElse () == NULL)
			return _disjunction_expr (then_assertion, neg_cond,
			                          context);

		Expr* else_assertion =
			is_assertion_stmt (*(if_stmt.getElse ()), context);
		if (else_assertion == NULL)
			return NULL;

		else_assertion =
			_conjunction_expr (neg_cond, else_assertion, context);

		return _disjunction_expr (then_assertion, else_assertion,
		                          context);
	}
	case Stmt::StmtClass::ConditionalOperatorClass: {
		/* Handle a ternary operator.
		 * Transformations:
		 *     C ? S1 : S2 ↦
		 *       (C ∧ calc(S1)) ∨ (¬C ∧ calc(S2)) */
		ConditionalOperator& op_expr = cast<ConditionalOperator> (stmt);
		assert (op_expr.getTrueExpr () != NULL);
		assert (op_expr.getFalseExpr () != NULL);

		Expr* neg_cond = _negation_expr (op_expr.getCond (), context);

		Expr* then_assertion =
			is_assertion_stmt (*(op_expr.getTrueExpr ()), context);
		if (then_assertion == NULL)
			return NULL;

		then_assertion =
			_conjunction_expr (op_expr.getCond (), then_assertion,
			                   context);

		Expr* else_assertion =
			is_assertion_stmt (*(op_expr.getFalseExpr ()),
			                   context);
		if (else_assertion == NULL)
			return NULL;

		else_assertion =
			_conjunction_expr (neg_cond, else_assertion, context);

		return _disjunction_expr (then_assertion, else_assertion,
		                          context);
	}
	case Stmt::StmtClass::SwitchStmtClass: {
		/* Handle a switch statement.
		 * Transformations:
		 *     switch (C) { L1: S1; L2: S2; …; Lz: Sz } ↦ NULL
		 * FIXME: This should get a proper transformation sometime. */
		return NULL;
	}
	case Stmt::StmtClass::AttributedStmtClass: {
		/* Handle an attributed statement, e.g. G_LIKELY(…).
		 * Transformations:
		 *     att S ↦ calc(S) */
		AttributedStmt& attr_stmt = cast<AttributedStmt> (stmt);

		Stmt* sub_stmt = attr_stmt.getSubStmt ();
		if (sub_stmt == NULL)
			return NULL;

		return is_assertion_stmt (*sub_stmt, context);
	}
	case Stmt::StmtClass::CompoundStmtClass: {
		/* Handle a compound statement, e.g. { stmt1; stmt2; }.
		 * Transformations:
		 *     S1; S2; …; Sz ↦ calc(S1) ∧ calc(S2) ∧ … ∧ calc(Sz)
		 *     {} ↦ TRUE
		 *
		 * This is implemented by starting with a base TRUE case in the
		 * compound_condition, then taking the conjunction with the next
		 * statement’s assertion condition for each statement in the
		 * compound.
		 *
		 * If the compound is empty, the compound_condition will be
		 * TRUE. Otherwise, it will be (TRUE ∧ …), which will be
		 * simplified later. */
		CompoundStmt& compound_stmt = cast<CompoundStmt> (stmt);
		Expr* compound_condition =
			new (context)
				IntegerLiteral (context,
				                context.MakeIntValue (1, context.getLogicalOperationType ()),
				                context.getLogicalOperationType (),
				                SourceLocation ());

		for (CompoundStmt::const_body_iterator it =
		     compound_stmt.body_begin (),
		     ie = compound_stmt.body_end (); it != ie; ++it) {
			Stmt* body_stmt = *it;
			Expr* body_assertion =
				is_assertion_stmt (*body_stmt, context);

			if (body_assertion == NULL) {
				/* Reached a program state mutation. */
				return NULL;
			}

			/* Update the compound condition. */
			compound_condition =
				_conjunction_expr (compound_condition,
				                   body_assertion, context);

			DEBUG_EXPR ("Compound condition: ", *compound_condition);
		}

		return compound_condition;
	}
	case Stmt::StmtClass::GotoStmtClass:
		/* Handle a goto statement.
		 * Transformations:
		 *     goto L ↦ FALSE */
	case Stmt::StmtClass::ReturnStmtClass: {
		/* Handle a return statement.
		 * Transformations:
		 *     return ↦ FALSE */
		return new (context)
			IntegerLiteral (context,
			                context.MakeIntValue (0, context.getLogicalOperationType ()),
			                context.getLogicalOperationType (),
			                SourceLocation ());
	}
	case Stmt::StmtClass::NullStmtClass:
		/* Handle a null statement.
		 * Transformations:
		 *     ; ↦ TRUE */
	case Stmt::StmtClass::DeclRefExprClass:
		/* Handle a variable reference expression. These don’t modify
		 * program state.
		 * Transformations:
		 *     E ↦ TRUE */
	case Stmt::StmtClass::DeclStmtClass: {
		/* Handle a variable declaration statement. These don’t modify
		 * program state; they only introduce new state, so can’t affect
		 * subsequent assertions. (FIXME: For the moment, we ignore the
		 * possibility of the rvalue modifying program state.)
		 * Transformations:
		 *     T S1 ↦ TRUE
		 *     T S1 = S2 ↦ TRUE */
		return new (context)
			IntegerLiteral (context,
			                context.MakeIntValue (1, context.getLogicalOperationType ()),
			                context.getLogicalOperationType (),
			                SourceLocation ());
	}
	case Stmt::StmtClass::IntegerLiteralClass: {
		/* Handle an integer literal. This doesn’t modify program state,
		 * and evaluates directly to a boolean.
		 * Transformations:
		 *     0 ↦ FALSE
		 *     I ↦ TRUE */
		return dyn_cast<Expr> (&stmt);
	}
	case Stmt::StmtClass::ParenExprClass: {
		/* Handle a parenthesised expression.
		 * Transformations:
		 *     ( S ) ↦ calc(S) */
		ParenExpr& paren_expr = cast<ParenExpr> (stmt);

		Stmt* sub_expr = paren_expr.getSubExpr ();
		if (sub_expr == NULL)
			return NULL;

		return is_assertion_stmt (*sub_expr, context);
	}
	case Stmt::StmtClass::LabelStmtClass: {
		/* Handle a label statement.
		 * Transformations:
		 *     label: S ↦ calc(S) */
		LabelStmt& label_stmt = cast<LabelStmt> (stmt);

		Stmt* sub_stmt = label_stmt.getSubStmt ();
		if (sub_stmt == NULL)
			return NULL;

		return is_assertion_stmt (*sub_stmt, context);
	}
	case Stmt::StmtClass::ImplicitCastExprClass:
	case Stmt::StmtClass::CStyleCastExprClass: {
		/* Handle an explicit or implicit cast.
		 * Transformations:
		 *     (T) S ↦ calc(S) */
		CastExpr& cast_expr = cast<CastExpr> (stmt);

		Stmt* sub_expr = cast_expr.getSubExpr ();
		if (sub_expr == NULL)
			return NULL;

		return is_assertion_stmt (*sub_expr, context);
	}
	case Stmt::StmtClass::GCCAsmStmtClass:
	case Stmt::StmtClass::MSAsmStmtClass:
		/* Inline assembly. There is no way we are parsing this, so
		 * conservatively assume it modifies program state.
		 * Transformations:
		 *     A ↦ NULL */
	case Stmt::StmtClass::BinaryOperatorClass:
		/* Handle a binary operator statement. Since this is being
		 * processed at the top level, it’s most likely an assignment,
		 * so conservatively assume it modifies program state.
		 * Transformations:
		 *     S1 op S2 ↦ NULL */
	case Stmt::StmtClass::UnaryOperatorClass:
		/* Handle a unary operator statement. Since this is being
		 * processed at the top level, it’s not very interesting re.
		 * assertions, even though it probably won’t modify program
		 * state (unless it’s a pre- or post-increment or -decrement
		 * operator). Be conservative and assume it does, though.
		 * Transformations:
		 *     op S ↦ NULL */
	case Stmt::StmtClass::CompoundAssignOperatorClass:
		/* Handle a compound assignment operator, e.g. x += 5. This
		 * definitely modifies program state, so ignore it.
		 * Transformations:
		 *     S1 op S2 ↦ NULL */
	case Stmt::StmtClass::ForStmtClass:
		/* Handle a for statement. We assume these *always* change
		 * program state.
		 * Transformations:
		 *     for (…) { … } ↦ NULL */
	case Stmt::StmtClass::WhileStmtClass: {
		/* Handle a while(…) { … } block. Because we don't want to solve
		 * the halting problem, just assume all while statements cannot
		 * be assertion statements.
		 * Transformations:
		 *     while (C) { S } ↦ NULL
		 */
		return NULL;
	}
	case Stmt::StmtClass::NoStmtClass:
	default:
		WARN_EXPR (__func__ << "() can’t handle statements of type " <<
		           stmt.getStmtClassName (), stmt);
		return NULL;
	}
}
Exemple #8
0
// This code will check for cases if the given cache block is exclusive in 
// one node and shared in another-- a coherence violation
//
// To use, the SLICC specification must call sequencer.checkCoherence(address)
// when the controller changes to a state with new permissions.  Do this
// in setState.  The SLICC spec must also define methods "isBlockShared"
// and "isBlockExclusive" that are specific to that protocol
//
void System::checkGlobalCoherenceInvariant(const Address& addr  )  {
  
  NodeID exclusive = -1;
  bool sharedDetected = false;
  NodeID lastShared = -1;

  for (int i = 0; i < m_chip_vector.size(); i++) {

    if (m_chip_vector[i]->isBlockExclusive(addr)) {
      if (exclusive != -1) {
        // coherence violation
        WARN_EXPR(exclusive);
        WARN_EXPR(m_chip_vector[i]->getID());
        WARN_EXPR(addr);
        WARN_EXPR(g_eventQueue_ptr->getTime());
        ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips");
      }
      else if (sharedDetected) {
        WARN_EXPR(lastShared);
        WARN_EXPR(m_chip_vector[i]->getID());
        WARN_EXPR(addr);
        WARN_EXPR(g_eventQueue_ptr->getTime());
        ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
      }
      else {
        exclusive = m_chip_vector[i]->getID();
      }
    }
    else if (m_chip_vector[i]->isBlockShared(addr)) {
      sharedDetected = true;
      lastShared = m_chip_vector[i]->getID();

      if (exclusive != -1) {
        WARN_EXPR(lastShared);
        WARN_EXPR(exclusive);
        WARN_EXPR(addr);
        WARN_EXPR(g_eventQueue_ptr->getTime());
        ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
      }
    }
  }
}
void RequestGenerator::performCallback(NodeID proc, SubBlock& data)
{
  Address address = data.getAddress();
  assert(proc == m_node);
  assert(address == m_address);  

  DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
  DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
  DEBUG_EXPR(TESTER_COMP, LowPrio, address);
  DEBUG_EXPR(TESTER_COMP, LowPrio, data);

  if (m_status == RequestGeneratorStatus_Test_Pending) { 
    //    m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
    if (data.readByte() == LockStatus_Locked) {
      // Locked - keep spinning
      m_status = RequestGeneratorStatus_Thinking;
      m_last_transition = g_eventQueue_ptr->getTime();
      g_eventQueue_ptr->scheduleEvent(this, waitTime());
    } else {
      // Unlocked - try the swap
      m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
      m_status = RequestGeneratorStatus_Before_Swap;
      m_last_transition = g_eventQueue_ptr->getTime();
      g_eventQueue_ptr->scheduleEvent(this, waitTime());
    }
  } else if (m_status == RequestGeneratorStatus_Swap_Pending) {
    m_driver.recordSwapLatency(g_eventQueue_ptr->getTime() - m_last_transition);
    if (data.readByte() == LockStatus_Locked) {
      // We failed to aquire the lock
      m_status = RequestGeneratorStatus_Thinking;
      m_last_transition = g_eventQueue_ptr->getTime();
      g_eventQueue_ptr->scheduleEvent(this, waitTime());
    } else {
      // We acquired the lock
      data.writeByte(LockStatus_Locked);
      m_status = RequestGeneratorStatus_Holding;
      m_last_transition = g_eventQueue_ptr->getTime();
      DEBUG_MSG(TESTER_COMP, HighPrio, "Acquired");
      DEBUG_EXPR(TESTER_COMP, HighPrio, proc);
      DEBUG_EXPR(TESTER_COMP, HighPrio, g_eventQueue_ptr->getTime());
      g_eventQueue_ptr->scheduleEvent(this, holdTime());
    }
  } else if (m_status == RequestGeneratorStatus_Release_Pending) {
    m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
    // We're releasing the lock
    data.writeByte(LockStatus_Unlocked);

    m_counter++;
    if (m_counter < g_param_ptr->TESTER_LENGTH()) {
      m_status = RequestGeneratorStatus_Thinking;
      m_last_transition = g_eventQueue_ptr->getTime();
      pickAddress();
      g_eventQueue_ptr->scheduleEvent(this, thinkTime());
    } else {
      m_driver.reportDone();
      m_status = RequestGeneratorStatus_Done;
      m_last_transition = g_eventQueue_ptr->getTime();
    } 
  } else {
    WARN_EXPR(m_status);
    ERROR_MSG("Invalid status");
  }
}