Exemplo n.º 1
0
/*
 * Icarus translated for(<assign>; <cond>; <incr_assign>) <body> into
 *
 *   begin
 *     <assign>;
 *     while (<cond>) begin
 *       <body>
 *       <incr_assign>
 *     end
 *   end
 * This routine looks for this pattern and turns it back into the
 * appropriate for loop.
 */
static unsigned is_for_loop(ivl_scope_t scope, ivl_statement_t stmt)
{
      unsigned wid;
      ivl_statement_t assign, while_lp, while_blk, body, incr_assign;

	/* We must have two block elements. */
      if (ivl_stmt_block_count(stmt) != 2) return 0;
	/* The first must be an assign. */
      assign = ivl_stmt_block_stmt(stmt, 0);
      if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
	/* The second must be a while. */
      while_lp = ivl_stmt_block_stmt(stmt, 1);
      if (ivl_statement_type(while_lp) != IVL_ST_WHILE) return 0;
	/* The while statement must be a block. */
      while_blk = ivl_stmt_sub_stmt(while_lp);
      if (ivl_statement_type(while_blk) != IVL_ST_BLOCK) return 0;
	/* It must not be a named block. */
      if (ivl_stmt_block_scope(while_blk)) return 0;
	/* It must have two elements. */
      if (ivl_stmt_block_count(while_blk) != 2) return 0;
	/* The first block element (the body) can be anything. */
      body = ivl_stmt_block_stmt(while_blk, 0);
	/* The second block element must be the increment assign. */
      incr_assign = ivl_stmt_block_stmt(while_blk, 1);
      if (ivl_statement_type(incr_assign) != IVL_ST_ASSIGN) return 0;
	/* And finally the for statements must have the same line number
	 * as the block. */
      if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(while_lp)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(while_blk)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(incr_assign))) {
	    return 0;
      }

	/* The pattern matched so generate the appropriate code. */
      fprintf(vlog_out, "%*cfor(", get_indent(), ' ');
	/* Emit the initialization statement. */
// HERE: Do we need to calculate the width? The compiler should have already
//       done this for us.
      wid = emit_stmt_lval(scope, assign);
      fprintf(vlog_out, " = ");
      emit_expr(scope, ivl_stmt_rval(assign), wid);
      fprintf(vlog_out, "; ");
	/* Emit the condition. */
      emit_expr(scope, ivl_stmt_cond_expr(while_lp), 0);
      fprintf(vlog_out, "; ");
	/* Emit in increment statement. */
// HERE: Do we need to calculate the width? The compiler should have already
//       done this for us.
      wid = emit_stmt_lval(scope, incr_assign);
      fprintf(vlog_out, " = ");
      emit_expr(scope, ivl_stmt_rval(incr_assign), wid);
      fprintf(vlog_out, ")");
      emit_stmt_file_line(stmt);
	/* Now emit the body. */
      single_indent = 1;
      emit_stmt(scope, body);

      return 1;
}
Exemplo n.º 2
0
void emit_process(ivl_scope_t scope, ivl_process_t proc)
{
      ivl_statement_t stmt;
      fprintf(vlog_out, "\n%*c", get_indent(), ' ');
      switch (ivl_process_type(proc)) {
        case IVL_PR_INITIAL:
            fprintf(vlog_out, "initial");
            break;
        case IVL_PR_ALWAYS:
            fprintf(vlog_out, "always");
            break;
        default:
            fprintf(vlog_out, "<unknown>");
            fprintf(stderr, "%s:%u: vlog95 error: Unknown process type (%d).\n",
                            ivl_process_file(proc), ivl_process_lineno(proc),
                            (int)ivl_process_type(proc));
            vlog_errors+= 1;
            break;
      }
      if (emit_file_line) {
	    fprintf(vlog_out, " /* %s:%u */",
	                      ivl_process_file(proc),
	                      ivl_process_lineno(proc));
      }
      stmt = ivl_process_stmt(proc);
      if (ivl_statement_type(stmt) == IVL_ST_NOOP) {
            fprintf(vlog_out, " begin\n%*cend\n", get_indent(), ' ');
      } else {
	    single_indent = 1;
	    emit_stmt(scope, stmt);
      }
}
Exemplo n.º 3
0
/*
 * Icarus translated wait(<expr) <stmt> into
 *   begin
 *    while (<expr> !== 1'b1) @(<expr sensitivities>);
 *    <stmt>
 *   end
 * This routine looks for this pattern and turns it back into a
 * wait statement.
 */
static unsigned is_wait(ivl_scope_t scope, ivl_statement_t stmt)
{
      ivl_statement_t while_wait, wait, wait_stmt;
      ivl_expr_t while_expr, expr;
      const char *bits;
	/* We must have two block elements. */
      if (ivl_stmt_block_count(stmt) != 2) return 0;
	/* The first must be a while. */
      while_wait = ivl_stmt_block_stmt(stmt, 0);
      if (ivl_statement_type(while_wait) != IVL_ST_WHILE) return 0;
	/* That has a wait with a NOOP statement. */
      wait = ivl_stmt_sub_stmt(while_wait);
      if (ivl_statement_type(wait) != IVL_ST_WAIT) return 0;
      wait_stmt = ivl_stmt_sub_stmt(wait);
      if (ivl_statement_type(wait_stmt) != IVL_ST_NOOP) return 0;
	/* Check that the while condition has the correct form. */
      while_expr = ivl_stmt_cond_expr(while_wait);
      if (ivl_expr_type(while_expr) != IVL_EX_BINARY) return 0;
      if (ivl_expr_opcode(while_expr) != 'N') return 0;
	/* Has a second operator that is a constant 1'b1. */
      expr = ivl_expr_oper2(while_expr);
      if (ivl_expr_type(expr) != IVL_EX_NUMBER) return 0;
      if (ivl_expr_width(expr) != 1) return 0;
      bits = ivl_expr_bits(expr);
      if (*bits != '1') return 0;
// HERE: There is no easy way to verify that the @ sensitivity list
//       matches the first expression so we don't check for that yet.
	/* And finally the two statements that represent the wait must
	 * have the same line number as the block. */
      if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(while_wait)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(wait))) {
	    return 0;
      }

	/* The pattern matched so generate the appropriate code. */
      fprintf(vlog_out, "%*cwait(", get_indent(), ' ');
      emit_expr(scope, ivl_expr_oper1(while_expr), 0);
      fprintf(vlog_out, ")");
      emit_stmt_file_line(stmt);
      single_indent = 1;
      emit_stmt(scope, ivl_stmt_block_stmt(stmt, 1));
      return 1;
}
Exemplo n.º 4
0
static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt)
{
      char *case_type;
      unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
      switch(ivl_statement_type(stmt)) {
	case IVL_ST_CASE:
	case IVL_ST_CASER:
	    case_type = "case";
	    break;
	case IVL_ST_CASEX:
	    case_type = "casex";
	    break;
	case IVL_ST_CASEZ:
	    case_type = "casez";
	    break;
	default:
	    assert(0);
      }
      fprintf(vlog_out, "%*c%s (", get_indent(), ' ', case_type);
      emit_expr(scope, ivl_stmt_cond_expr(stmt), 0);
      fprintf(vlog_out, ")");
      emit_stmt_file_line(stmt);
      fprintf(vlog_out, "\n");
      indent += indent_incr;
      default_case = count;
      for (idx = 0; idx < count; idx += 1) {
	    ivl_expr_t expr = ivl_stmt_case_expr(stmt, idx);
	      /* This is the default case so emit it last. */
	    if (expr == 0) {
		  assert(default_case == count);
		  default_case = idx;
		  continue;
	    }
	    fprintf(vlog_out, "%*c", get_indent(), ' ');
	    emit_expr(scope, expr, 0);
	    fprintf(vlog_out, ":");
	    single_indent = 1;
	    emit_stmt(scope, ivl_stmt_case_stmt(stmt, idx));
      }
      if (default_case < count) {
	    fprintf(vlog_out, "%*cdefault:", get_indent(), ' ');
	    single_indent = 1;
	    emit_stmt(scope, ivl_stmt_case_stmt(stmt, default_case));
      }
      assert(indent >= indent_incr);
      indent -= indent_incr;
      fprintf(vlog_out, "%*cendcase\n", get_indent(), ' ');
}
Exemplo n.º 5
0
static void emit_stmt_condit(ivl_scope_t scope, ivl_statement_t stmt)
{
      ivl_statement_t true_stmt = ivl_stmt_cond_true(stmt);
      ivl_statement_t false_stmt = ivl_stmt_cond_false(stmt);
      unsigned nest = 0;
      fprintf(vlog_out, "%*cif (", get_indent(), ' ');
      emit_expr(scope, ivl_stmt_cond_expr(stmt), 0);
      fprintf(vlog_out, ")");
      emit_stmt_file_line(stmt);
      if (true_stmt) {
	      /* If we have a false statement and the true statement is a
	       * condition that does not have a false clause then we need
	       * to add a begin/end pair to keep the else clause attached
	       * to this condition. */
	    if (false_stmt &&
	        (ivl_statement_type(true_stmt) == IVL_ST_CONDIT) &&
	        (! ivl_stmt_cond_false(true_stmt))) nest = 1;
	    if (nest) {
		  fprintf(vlog_out, " begin\n");
		  indent += indent_incr;
	    } else single_indent = 1;
	    emit_stmt(scope, true_stmt);
      } else {
	    fprintf(vlog_out, ";\n");
      }
      if (false_stmt) {
	    if (nest) {
		  assert(indent >= indent_incr);
		  indent -= indent_incr;
	    }
	    fprintf(vlog_out, "%*c", get_indent(), ' ');
	    if (nest) fprintf(vlog_out, "end ");
	    fprintf(vlog_out, "else");
	    single_indent = 1;
	    emit_stmt(scope, false_stmt);
      }
}
Exemplo n.º 6
0
void clsAnalysis::AnalyzeStatement(clsStatement * pStatement, clsBasicBlock * pBasicBlock, clsEvent * pEvent)
{
  ivl_statement_t                   ivl_Statement;
  vector<clsLValue *>::iterator     it_pLValue;
  vector<clsBasicBlock *>::iterator it_pBasicBlock;
  unsigned int                      iNumberOfParameters;
  unsigned int                      iNumberOfStatements;
  unsigned int                      iIndex;
  
  ivl_Statement = pStatement->m_ivl_Statement;
  it_pBasicBlock = pBasicBlock->m_pSuccessors.begin();
  
  switch (pStatement->m_Type)
  {
  default:
    _DebugPrint("/* Unrecognized statement of type %u is encountered. */\n", ivl_statement_type(ivl_Statement) );
    _Assert(0 && "Frontend Error: Unrecognized statement is encountered.");
    break;
  case CMODELGEN_STATEMENT_NOP:
    break;
  case CMODELGEN_STATEMENT_WAIT:
    if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
    {
      AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
    }
    break;
  case CMODELGEN_STATEMENT_CASE:
  case CMODELGEN_STATEMENT_CASEZ:
  case CMODELGEN_STATEMENT_CASEX:
    AnalyzeExpression(pStatement->m_pExpressions[0], pEvent);
    iNumberOfStatements = ivl_stmt_case_count(ivl_Statement);
    for(iIndex = 0; iIndex < iNumberOfStatements; ++iIndex)
    {
      AnalyzeExpression(pStatement->m_pExpressions[iIndex + 1], pEvent);
      if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
      {
        AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
      }
      if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() )
      {
        ++it_pBasicBlock;
      }
    }
    if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
    {
      AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
    }
    break;
  case CMODELGEN_STATEMENT_COND:
    AnalyzeExpression(pStatement->m_pExpressions[0], pEvent);
    if (0 != ivl_stmt_cond_true(ivl_Statement) )
    {
      if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
      {
        AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
      }
      if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() )
      {
        ++it_pBasicBlock;
      }
    }
    if (0 != ivl_stmt_cond_false(ivl_Statement) )
    {
      if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
      {
        AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
      }
      if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() )
      {
        ++it_pBasicBlock;
      }
    }
    if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
    {
      AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
    }
    break;
  case CMODELGEN_STATEMENT_REPEAT:
  case CMODELGEN_STATEMENT_WHILE:
    AnalyzeExpression(pStatement->m_pExpressions[0], pEvent);
    if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
    {
      AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
    }
    if (it_pBasicBlock != pBasicBlock->m_pSuccessors.end() && *it_pBasicBlock != NULL)
    {
      AnalyzeBasicBlock(*it_pBasicBlock, pEvent);
    }
    break;
  case CMODELGEN_STATEMENT_NB_ASSIGN:
    iIndex = 0;
    for (it_pLValue  = pStatement->m_pLValues.begin();
         it_pLValue != pStatement->m_pLValues.end();
         ++it_pLValue)
    {
      AnalyzeNBLValue(*it_pLValue, pEvent);
      ++iIndex;
    }
    AnalyzeExpression(pStatement->m_pExpressions[0], pEvent);
    break;
  case CMODELGEN_STATEMENT_ASSIGN:
    iIndex = 0;
    for (it_pLValue  = pStatement->m_pLValues.begin();
         it_pLValue != pStatement->m_pLValues.end();
         ++it_pLValue)
    {
      AnalyzeLValue(*it_pLValue, pEvent);
      ++iIndex;
    }
    AnalyzeExpression(pStatement->m_pExpressions[0], pEvent);
    break;
  case CMODELGEN_STATEMENT_STASK:
    iNumberOfParameters = ivl_stmt_parm_count(ivl_Statement);
    for(iIndex = 0; iIndex < iNumberOfParameters; ++iIndex)
    {
      AnalyzeExpression(pStatement->m_pExpressions[iIndex], pEvent);
    }
    break;
  case CMODELGEN_STATEMENT_UTASK:
    break;
  case CMODELGEN_STATEMENT_DISABLE:
    break;
  case CMODELGEN_STATEMENT_ALLOC:
    break;
  case CMODELGEN_STATEMENT_FREE:
    break;
  }
}
static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
{
      ivl_expr_t exp = ivl_stmt_cond_expr(net);
      struct vector_info cond = draw_eval_expr(exp, 0);
      unsigned count = ivl_stmt_case_count(net);

      unsigned local_base = local_count;

      unsigned idx, default_case;

      local_count += count + 1;

	/* First draw the branch table.  All the non-default cases
	   generate a branch out of here, to the code that implements
	   the case. The default will fall through all the tests. */
      default_case = count;

      for (idx = 0 ;  idx < count ;  idx += 1) {
	    ivl_expr_t cex = ivl_stmt_case_expr(net, idx);
	    struct vector_info cvec;

	    if (cex == 0) {
		  default_case = idx;
		  continue;
	    }

	      /* Is the guard expression something I can pass to a
		 %cmpi/u instruction? If so, use that instead. */

	    if ((ivl_statement_type(net) == IVL_ST_CASE)
		&& (ivl_expr_type(cex) == IVL_EX_NUMBER)
		&& (! number_is_unknown(cex))
		&& number_is_immediate(cex, 16)) {

		  unsigned long imm = get_number_immediate(cex);

		  fprintf(vvp_out, "    %%cmpi/u %u, %lu, %u;\n",
			  cond.base, imm, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 6;\n",
			  thread_count, local_base+idx);

		  continue;
	    }

	      /* Oh well, do this case the hard way. */

	    cvec = draw_eval_expr_wid(cex, cond.wid, 0);
	    assert(cvec.wid == cond.wid);

	    switch (ivl_statement_type(net)) {

		case IVL_ST_CASE:
		  fprintf(vvp_out, "    %%cmp/u %u, %u, %u;\n",
			  cond.base, cvec.base, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 6;\n",
			  thread_count, local_base+idx);
		  break;

		case IVL_ST_CASEX:
		  fprintf(vvp_out, "    %%cmp/x %u, %u, %u;\n",
			  cond.base, cvec.base, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 4;\n",
			  thread_count, local_base+idx);
		  break;

		case IVL_ST_CASEZ:
		  fprintf(vvp_out, "    %%cmp/z %u, %u, %u;\n",
			  cond.base, cvec.base, cond.wid);
		  fprintf(vvp_out, "    %%jmp/1 T_%d.%d, 4;\n",
			  thread_count, local_base+idx);
		  break;

		default:
		  assert(0);
	    }
	    
	      /* Done with the case expression */
	    clr_vector(cvec);
      }

	/* Done with the condition expression */
      clr_vector(cond);

	/* Emit code for the default case. */
      if (default_case < count) {
	    ivl_statement_t cst = ivl_stmt_case_stmt(net, default_case);
	    show_statement(cst, sscope);
      }

	/* Jump to the out of the case. */
      fprintf(vvp_out, "    %%jmp T_%d.%d;\n", thread_count,
	      local_base+count);

      for (idx = 0 ;  idx < count ;  idx += 1) {
	    ivl_statement_t cst = ivl_stmt_case_stmt(net, idx);

	    if (idx == default_case)
		  continue;

	    fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx);
	    clear_expression_lookaside();
	    show_statement(cst, sscope);

	    fprintf(vvp_out, "    %%jmp T_%d.%d;\n", thread_count,
		    local_base+count);

      }


	/* The out of the case. */
      fprintf(vvp_out, "T_%d.%d ;\n",  thread_count, local_base+count);
      clear_expression_lookaside();

      return 0;
}
/*
 * This function draws a statement as vvp assembly. It basically
 * switches on the statement type and draws code based on the type and
 * further specifics.
 */
static int show_statement(ivl_statement_t net, ivl_scope_t sscope)
{
      const ivl_statement_type_t code = ivl_statement_type(net);
      int rc = 0;

      switch (code) {

	  case IVL_ST_ASSIGN:
	    rc += show_stmt_assign(net);
	    break;

	  case IVL_ST_ASSIGN_NB:
	    rc += show_stmt_assign_nb(net);
	    break;

	  case IVL_ST_BLOCK:
	    if (ivl_stmt_block_scope(net))
		  rc += show_stmt_block_named(net, sscope);
	    else
		  rc += show_stmt_block(net, sscope);
	    break;

	  case IVL_ST_CASE:
	  case IVL_ST_CASEX:
	  case IVL_ST_CASEZ:
	    rc += show_stmt_case(net, sscope);
	    break;

	  case IVL_ST_CASER:
	    rc += show_stmt_case_r(net, sscope);
	    break;

	  case IVL_ST_CASSIGN:
	    rc += show_stmt_cassign(net);
	    break;

	  case IVL_ST_CONDIT:
	    rc += show_stmt_condit(net, sscope);
	    break;

	  case IVL_ST_DEASSIGN:
	    rc += show_stmt_deassign(net);
	    break;

	  case IVL_ST_DELAY:
	    rc += show_stmt_delay(net, sscope);
	    break;

	  case IVL_ST_DELAYX:
	    rc += show_stmt_delayx(net, sscope);
	    break;

	  case IVL_ST_DISABLE:
	    rc += show_stmt_disable(net, sscope);
	    break;

	  case IVL_ST_FORCE:
	    rc += show_stmt_force(net);
	    break;

	  case IVL_ST_FOREVER:
	    rc += show_stmt_forever(net, sscope);
	    break;

	  case IVL_ST_FORK:
	    rc += show_stmt_fork(net, sscope);
	    break;

	  case IVL_ST_NOOP:
	    rc += show_stmt_noop(net);
	    break;

	  case IVL_ST_RELEASE:
	    rc += show_stmt_release(net);
	    break;

	  case IVL_ST_REPEAT:
	    rc += show_stmt_repeat(net, sscope);
	    break;

	  case IVL_ST_STASK:
	    rc += show_system_task_call(net);
	    break;

	  case IVL_ST_TRIGGER:
	    rc += show_stmt_trigger(net);
	    break;

	  case IVL_ST_UTASK:
	    rc += show_stmt_utask(net);
	    break;

	  case IVL_ST_WAIT:
	    rc += show_stmt_wait(net, sscope);
	    break;

	  case IVL_ST_WHILE:
	    rc += show_stmt_while(net, sscope);
	    break;

	  default:
	    fprintf(stderr, "vvp.tgt: Unable to draw statement type %u\n",
		    code);
	    rc += 1;
	    break;
      }

      return rc;
}
Exemplo n.º 9
0
static void show_statement(ivl_statement_t net, unsigned ind)
{
      const ivl_statement_type_t code = ivl_statement_type(net);

      switch (code) {
	  case IVL_ST_ASSIGN:
	    fprintf(out, "%*s", ind, "");
	    show_assign_lvals(net);
	    fprintf(out, " = ");
	    show_expression(ivl_stmt_rval(net));
	    fprintf(out, ";\n");
	    break;

	  case IVL_ST_BLOCK: {
		unsigned cnt = ivl_stmt_block_count(net);
		unsigned idx;
		fprintf(out, "%*sbegin\n", ind, "");
		for (idx = 0 ;  idx < cnt ;  idx += 1) {
		      ivl_statement_t cur = ivl_stmt_block_stmt(net, idx);
		      show_statement(cur, ind+4);
		}
		fprintf(out, "%*send\n", ind, "");
		break;
	  }

	  case IVL_ST_CONDIT: {
		ivl_statement_t t = ivl_stmt_cond_true(net);
		ivl_statement_t f = ivl_stmt_cond_false(net);

		fprintf(out, "%*sif (", ind, "");
		show_expression(ivl_stmt_cond_expr(net));
		fprintf(out, ")\n");

		if (t)
		      show_statement(t, ind+4);
		else
		      fprintf(out, "%*s;\n", ind+4, "");

		if (f) {
		      fprintf(out, "%*selse\n", ind, "");
		      show_statement(f, ind+4);
		}

		break;
	  }

	  case IVL_ST_DELAY:
	    fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
	    show_statement(ivl_stmt_sub_stmt(net), ind+2);
	    break;

	  case IVL_ST_NOOP:
	    fprintf(out, "%*s/* noop */;\n", ind, "");
	    break;

	  case IVL_ST_STASK:
	    if (ivl_stmt_parm_count(net) == 0) {
		  fprintf(out, "%*s%s;\n", ind, "", ivl_stmt_name(net));

	    } else {
		  unsigned idx;
		  fprintf(out, "%*s%s(", ind, "", ivl_stmt_name(net));
		  show_expression(ivl_stmt_parm(net, 0));
		  for (idx = 1 ;  idx < ivl_stmt_parm_count(net) ; idx += 1) {
			fprintf(out, ", ");
			show_expression(ivl_stmt_parm(net, idx));
		  }
		  fprintf(out, ");\n");
	    }
	    break;

	  case IVL_ST_WAIT:
	    fprintf(out, "%*s@(...)\n", ind, "");
	    show_statement(ivl_stmt_sub_stmt(net), ind+2);
	    break;

	  case IVL_ST_WHILE:
	    fprintf(out, "%*swhile (<?>)\n", ind, "");
	    show_statement(ivl_stmt_sub_stmt(net), ind+2);
	    break;

	  default:
	    fprintf(out, "%*sunknown statement type (%d)\n", ind, "", code);
      }
}
Exemplo n.º 10
0
/*
 * Icarus encodes a user task call with arguments as:
 *   begin
 *     <input 1> = <arg>
 *     ...
 *     <input n> = <arg>
 *     <task_call>
 *     <arg> = <output 1>
 *     ...
 *     <arg> = <output n>
 *   end
 * This routine looks for that pattern and translates it into the
 * appropriate task call. It returns true (1) if it successfully
 * translated the block to a task call, otherwise it returns false
 * (0) to indicate the block needs to be emitted.
 */
static unsigned is_utask_call_with_args(ivl_scope_t scope,
                                        ivl_statement_t stmt)
{
      unsigned idx, ports, task_idx = 0;
      unsigned count = ivl_stmt_block_count(stmt);
      unsigned lineno = ivl_stmt_lineno(stmt);
      ivl_scope_t task_scope = 0;
      port_expr_t port_exprs;
	/* Check to see if the block is of the basic form first.  */
      for (idx = 0; idx < count; idx += 1) {
	    ivl_statement_t tmp = ivl_stmt_block_stmt(stmt, idx);
	    if (ivl_statement_type(tmp) == IVL_ST_ASSIGN) continue;
	    if (ivl_statement_type(tmp) == IVL_ST_UTASK && !task_scope) {
		  task_idx = idx;
		  task_scope = ivl_stmt_call(tmp);
		  assert(ivl_scope_type(task_scope) == IVL_SCT_TASK);
		  continue;
	    }
	    return 0;
      }
	/* If there is no task call or it takes no argument then return. */
      if (!task_scope) return 0;
      ports = ivl_scope_ports(task_scope);
      if (ports == 0) return 0;

	/* Allocate space to save the port information and initialize it. */
      port_exprs = (port_expr_t) malloc(sizeof(struct port_expr_s)*ports);
      for (idx = 0; idx < ports; idx += 1) {
	    port_exprs[idx].type = IVL_SIP_NONE;
	    port_exprs[idx].expr.rval = 0;
      }
	/* Check that the input arguments are correct. */
      for (idx = 0; idx < task_idx; idx += 1) {
	    ivl_statement_t assign = ivl_stmt_block_stmt(stmt, idx);
	    unsigned port = utask_in_port_idx(task_scope, assign);
	    if ((port == ports) || (lineno != ivl_stmt_lineno(assign))) {
		  free(port_exprs);
		  return 0;
	    }
	    port_exprs[port].type = IVL_SIP_INPUT;
	    port_exprs[port].expr.rval = ivl_stmt_rval(assign);
      }
	/* Check that the output arguments are correct. */
      for (idx = task_idx + 1; idx < count; idx += 1) {
	    ivl_statement_t assign = ivl_stmt_block_stmt(stmt, idx);
	    unsigned port = utask_out_port_idx(task_scope, assign);
	    if ((port == ports) || (lineno != ivl_stmt_lineno(assign))) {
		  free(port_exprs);
		  return 0;
	    }
	    if (port_exprs[port].type == IVL_SIP_INPUT) {
		  port_exprs[port].type = IVL_SIP_INOUT;
// HERE: We probably should verify that the current R-value matches the
//       new L-value.
	    } else {
		  port_exprs[port].type = IVL_SIP_OUTPUT;
	    }
	    port_exprs[port].expr.lval = assign;
      }
	/* Check that the task call has the correct line number. */
      if (lineno != ivl_stmt_lineno(ivl_stmt_block_stmt(stmt, task_idx))) {
	    free(port_exprs);
	    return 0;
      }

	/* Verify that all the ports were defined. */
      for (idx = 0; idx < ports; idx += 1) {
	    if (port_exprs[idx].type == IVL_SIP_NONE) {
		  free(port_exprs);
		  return 0;
	    }
      }

	/* Now that we have the arguments figured out, print the task call. */
      fprintf(vlog_out, "%*c", get_indent(), ' ');
      emit_scope_path(scope, task_scope);
      fprintf(vlog_out, "(");
      emit_port(scope, port_exprs[0]);
      for (idx = 1; idx < ports; idx += 1) {
	    fprintf(vlog_out, ", ");
	    emit_port(scope, port_exprs[idx]);
      }
      free(port_exprs);
      fprintf(vlog_out, ");");
      emit_stmt_file_line(stmt);
      fprintf(vlog_out, "\n");
      return 1;
}
Exemplo n.º 11
0
/*
 * Icarus translated <var> = repeat(<count>) <event> <value> into
 *   begin
 *    <tmp> = <value>;
 *    repeat(<count>) <event>;
 *    <var> = <tmp>;
 *   end
 * This routine looks for this pattern and turns it back into the
 * appropriate blocking assignment.
 */
static unsigned is_repeat_event_assign(ivl_scope_t scope, ivl_statement_t stmt)
{
      unsigned wid;
      ivl_statement_t assign, event, event_assign, repeat;
      ivl_lval_t lval;
      ivl_expr_t rval;
      ivl_signal_t lsig, rsig;

	/* We must have three block elements. */
      if (ivl_stmt_block_count(stmt) != 3) return 0;
	/* The first must be an assign. */
      assign = ivl_stmt_block_stmt(stmt, 0);
      if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
	/* The second must be a repeat with an event or an event. */
      repeat = ivl_stmt_block_stmt(stmt, 1);
      if (ivl_statement_type(repeat) != IVL_ST_REPEAT) return 0;
	/* The repeat must have an event statement. */
      event = ivl_stmt_sub_stmt(repeat);
      if (ivl_statement_type(event) != IVL_ST_WAIT) return 0;
	/* The third must be an assign. */
      event_assign = ivl_stmt_block_stmt(stmt, 2);
      if (ivl_statement_type(event_assign) != IVL_ST_ASSIGN) return 0;
	/* The L-value must be a single signal. */
      if (ivl_stmt_lvals(assign) != 1) return 0;
      lval = ivl_stmt_lval(assign, 0);
	/* It must not have an array select. */
      if (ivl_lval_idx(lval)) return 0;
	/* It must not have a non-zero base. */
      if (ivl_lval_part_off(lval)) return 0;
      lsig = ivl_lval_sig(lval);
	/* It must not be part of the signal. */
      if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return 0;
	/* The R-value must be a single signal. */
      rval = ivl_stmt_rval(event_assign);
      if (ivl_expr_type(rval) != IVL_EX_SIGNAL) return 0;
	/* It must not be an array word. */
      if (ivl_expr_oper1(rval)) return 0;
      rsig = ivl_expr_signal(rval);
	/* The two signals must be the same. */
      if (lsig != rsig) return 0;
	/* And finally the four statements must have the same line number
	 * as the block. */
      if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(repeat)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(event)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(event_assign))) {
	    return 0;
      }

	/* The pattern matched so generate the appropriate code. */
      fprintf(vlog_out, "%*c", get_indent(), ' ');
      wid = emit_stmt_lval(scope, event_assign);
      fprintf(vlog_out, " =");
      if (repeat) {
	    fprintf(vlog_out, " repeat (");
	    emit_expr(scope, ivl_stmt_cond_expr(repeat), 0);
	    fprintf(vlog_out, ")");
      }
      fprintf(vlog_out, " @(");
      emit_event(scope, event);
      fprintf(vlog_out, ") ");
      emit_expr(scope, ivl_stmt_rval(assign), wid);
      fprintf(vlog_out, ";");
      emit_stmt_file_line(stmt);
      fprintf(vlog_out, "\n");

      return 1;
}
Exemplo n.º 12
0
/*
 * Icarus translated <var> = <delay or event> <value> into
 *   begin
 *    <tmp> = <value>;
 *    <delay or event> <var> = <tmp>;
 *   end
 * This routine looks for this pattern and turns it back into the
 * appropriate blocking assignment.
 */
static unsigned is_delayed_or_event_assign(ivl_scope_t scope,
                                           ivl_statement_t stmt)
{
      unsigned wid;
      ivl_statement_t assign, delay, delayed_assign;
      ivl_statement_type_t delay_type;
      ivl_lval_t lval;
      ivl_expr_t rval;
      ivl_signal_t lsig, rsig;

	/* We must have two block elements. */
      if (ivl_stmt_block_count(stmt) != 2) return 0;
	/* The first must be an assign. */
      assign = ivl_stmt_block_stmt(stmt, 0);
      if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
	/* The second must be a delayx. */
      delay = ivl_stmt_block_stmt(stmt, 1);
      delay_type = ivl_statement_type(delay);
      if ((delay_type != IVL_ST_DELAYX) &&
          (delay_type != IVL_ST_WAIT)) return 0;
	/* The statement for the delayx must be an assign. */
      delayed_assign = ivl_stmt_sub_stmt(delay);
      if (ivl_statement_type(delayed_assign) != IVL_ST_ASSIGN) return 0;
	/* The L-value must be a single signal. */
      if (ivl_stmt_lvals(assign) != 1) return 0;
      lval = ivl_stmt_lval(assign, 0);
	/* It must not have an array select. */
      if (ivl_lval_idx(lval)) return 0;
	/* It must not have a non-zero base. */
      if (ivl_lval_part_off(lval)) return 0;
      lsig = ivl_lval_sig(lval);
	/* It must not be part of the signal. */
      if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return 0;
	/* The R-value must be a single signal. */
      rval = ivl_stmt_rval(delayed_assign);
      if (ivl_expr_type(rval) != IVL_EX_SIGNAL) return 0;
	/* It must not be an array word. */
      if (ivl_expr_oper1(rval)) return 0;
      rsig = ivl_expr_signal(rval);
	/* The two signals must be the same. */
      if (lsig != rsig) return 0;
	/* And finally the three statements must have the same line number
	 * as the block. */
      if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(delay)) ||
          (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(delayed_assign))) {
	    return 0;
      }

	/* The pattern matched so generate the appropriate code. */
      fprintf(vlog_out, "%*c", get_indent(), ' ');
      wid = emit_stmt_lval(scope, delayed_assign);
      fprintf(vlog_out, " = ");
      if (delay_type == IVL_ST_DELAYX) {
	    fprintf(vlog_out, "#(");
	    emit_scaled_delayx(scope, ivl_stmt_delay_expr(delay), 1);
      } else {
	    fprintf(vlog_out, "@(");
	    emit_event(scope, delay);
      }
      fprintf(vlog_out, ") ");
      emit_expr(scope, ivl_stmt_rval(assign), wid);
      fprintf(vlog_out, ";");
      emit_stmt_file_line(stmt);
      fprintf(vlog_out, "\n");

      return 1;
}
Exemplo n.º 13
0
void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
{
      switch(ivl_statement_type(stmt)) {
	case IVL_ST_NOOP:
	      /* If this is a statement termination then just finish the
	       * statement, otherwise print an empty begin/end pair. */
	    if (single_indent) {
		  single_indent = 0;
		  fprintf(vlog_out, ";\n");
	    } else {
		  fprintf(vlog_out, "%*cbegin\n", get_indent(), ' ');
		  fprintf(vlog_out, "%*cend\n", get_indent(), ' ');
	    }
	    break;
	case IVL_ST_ALLOC:
	      /* This statement is only used with an automatic task so we
	       * can safely skip it. The automatic task definition will
	       * generate an appropriate error message.*/
	    break;
	case IVL_ST_ASSIGN:
	    emit_stmt_assign(scope, stmt);
	    break;
	case IVL_ST_ASSIGN_NB:
	    emit_stmt_assign_nb(scope, stmt);
	    break;
	case IVL_ST_BLOCK:
	    if (ivl_stmt_block_scope(stmt)) {
		  emit_stmt_block_named(scope, stmt);
	    } else {
		  if (is_delayed_or_event_assign(scope, stmt)) break;
		  if (is_for_loop(scope, stmt)) break;
		  if (is_repeat_event_assign(scope, stmt)) break;
		  if (is_wait(scope, stmt)) break;
		  if (is_utask_call_with_args(scope, stmt)) break;
		  emit_stmt_block(scope, stmt);
	    }
	    break;
	case IVL_ST_CASE:
	case IVL_ST_CASER:
	case IVL_ST_CASEX:
	case IVL_ST_CASEZ:
	    emit_stmt_case(scope, stmt);
	    break;
	case IVL_ST_CASSIGN:
	    emit_stmt_cassign(scope, stmt);
	    break;
	case IVL_ST_CONDIT:
	    emit_stmt_condit(scope, stmt);
	    break;
	case IVL_ST_DEASSIGN:
	    emit_stmt_deassign(scope, stmt);
	    break;
	case IVL_ST_DELAY:
	    emit_stmt_delay(scope, stmt);
	    break;
	case IVL_ST_DELAYX:
	    emit_stmt_delayx(scope, stmt);
	    break;
	case IVL_ST_DISABLE:
	    emit_stmt_disable(scope, stmt);
	    break;
	case IVL_ST_FORCE:
	    emit_stmt_force(scope, stmt);
	    break;
	case IVL_ST_FOREVER:
	    emit_stmt_forever(scope, stmt);
	    break;
	case IVL_ST_FORK:
	    if (ivl_stmt_block_scope(stmt)) {
		  emit_stmt_fork_named(scope, stmt);
	    } else {
		  emit_stmt_fork(scope, stmt);
	    }
	    break;
	case IVL_ST_FREE:
	      /* This statement is only used with an automatic task so we
	       * can safely skip it. The automatic task definition will
	       * generate an appropriate error message.*/
	    break;
	case IVL_ST_RELEASE:
	    emit_stmt_release(scope, stmt);
	    break;
	case IVL_ST_REPEAT:
	    emit_stmt_repeat(scope, stmt);
	    break;
	case IVL_ST_STASK:
	    emit_stmt_stask(scope, stmt);
	    break;
	case IVL_ST_TRIGGER:
	    emit_stmt_trigger(scope, stmt);
	    break;
	case IVL_ST_UTASK:
	    emit_stmt_utask(scope, stmt);
	    break;
	case IVL_ST_WAIT:
	    emit_stmt_wait(scope, stmt);
	    break;
	case IVL_ST_WHILE:
	    emit_stmt_while(scope, stmt);
	    break;
	default:
	    fprintf(vlog_out, "%*c<unknown>;\n", get_indent(), ' ');
	    fprintf(stderr, "%s:%u: vlog95 error: Unknown statement "
	                    "type (%d).\n",
	                    ivl_stmt_file(stmt),
	                    ivl_stmt_lineno(stmt),
	                    (int)ivl_statement_type(stmt));
	    vlog_errors += 1;
	    break;
      }
}