Add support for SV do/while
This commit is contained in:
parent
8412d0d55f
commit
d8f945be23
17
Statement.cc
17
Statement.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2008,2010,2012-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -247,6 +247,17 @@ PDisable::~PDisable()
|
|||
{
|
||||
}
|
||||
|
||||
PDoWhile::PDoWhile(PExpr*ex, Statement*st)
|
||||
: cond_(ex), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
PDoWhile::~PDoWhile()
|
||||
{
|
||||
delete cond_;
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
|
||||
: expr_(ee), statement_(0)
|
||||
{
|
||||
|
|
@ -360,8 +371,8 @@ PTrigger::~PTrigger()
|
|||
{
|
||||
}
|
||||
|
||||
PWhile::PWhile(PExpr*e1, Statement*st)
|
||||
: cond_(e1), statement_(st)
|
||||
PWhile::PWhile(PExpr*ex, Statement*st)
|
||||
: cond_(ex), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
18
Statement.h
18
Statement.h
|
|
@ -336,6 +336,22 @@ class PDisable : public Statement {
|
|||
pform_name_t scope_;
|
||||
};
|
||||
|
||||
class PDoWhile : public Statement {
|
||||
|
||||
public:
|
||||
PDoWhile(PExpr*ex, Statement*st);
|
||||
~PDoWhile();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
PExpr*cond_;
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The event statement represents the event delay in behavioral
|
||||
* code. It comes from such things as:
|
||||
|
|
@ -499,7 +515,7 @@ class PTrigger : public Statement {
|
|||
class PWhile : public Statement {
|
||||
|
||||
public:
|
||||
PWhile(PExpr*e1, Statement*st);
|
||||
PWhile(PExpr*ex, Statement*st);
|
||||
~PWhile();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -1030,6 +1030,13 @@ void NetDisable::dump(ostream&o, unsigned ind) const
|
|||
<< "/* " << get_fileline() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetDoWhile::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "do" << endl;
|
||||
proc_->dump(o, ind+3);
|
||||
o << setw(ind) << "" << "while (" << *cond_ << ");" << endl;
|
||||
}
|
||||
|
||||
void NetEvProbe::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
|
|
|
|||
|
|
@ -1795,6 +1795,17 @@ void PDelayStatement::elaborate_scope(Design*des, NetScope*scope) const
|
|||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
* statement.
|
||||
*/
|
||||
void PDoWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -755,6 +755,12 @@ void PDelayStatement::elaborate_sig(Design*des, NetScope*scope) const
|
|||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PDoWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
|
|
|
|||
12
elaborate.cc
12
elaborate.cc
|
|
@ -3718,6 +3718,18 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* The do/while loop is fairly directly represented in the netlist.
|
||||
*/
|
||||
NetProc* PDoWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
|
||||
tmp->set_line(*this);
|
||||
NetDoWhile*loop = new NetDoWhile(tmp, statement_->elaborate(des, scope));
|
||||
loop->set_line(*this);
|
||||
return loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* An event statement is an event delay of some sort, attached to a
|
||||
* statement. Some Verilog examples are:
|
||||
|
|
|
|||
23
emit.cc
23
emit.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -261,6 +261,17 @@ bool NetDisable::emit_proc(struct target_t*tgt) const
|
|||
return tgt->proc_disable(this);
|
||||
}
|
||||
|
||||
bool NetDoWhile::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_do_while(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetDoWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
bool NetForce::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_force(this);
|
||||
|
|
@ -318,6 +329,11 @@ bool NetWhile::emit_proc(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
void NetWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
void NetBlock::emit_recurse(struct target_t*tgt) const
|
||||
{
|
||||
if (last_ == 0)
|
||||
|
|
@ -459,11 +475,6 @@ bool NetScope::emit_defs(struct target_t*tgt) const
|
|||
return flag;
|
||||
}
|
||||
|
||||
void NetWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
{
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
int Design::emit(struct target_t*tgt) const
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
|
|||
|
|
@ -402,6 +402,7 @@ typedef enum ivl_statement_type_e {
|
|||
IVL_ST_DELAY = 11,
|
||||
IVL_ST_DELAYX = 12,
|
||||
IVL_ST_DISABLE = 13,
|
||||
IVL_ST_DO_WHILE = 30,
|
||||
IVL_ST_FORCE = 14,
|
||||
IVL_ST_FOREVER = 15,
|
||||
IVL_ST_FORK = 16,
|
||||
|
|
|
|||
|
|
@ -562,6 +562,49 @@ bool NetDisable::evaluate_function(const LineInfo&,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetDoWhile::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,LocalVar>&context_map) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": NetDoWhile::evaluate_function: "
|
||||
<< "Start loop" << endl;
|
||||
}
|
||||
|
||||
while (!disable) {
|
||||
// Evaluate the statement.
|
||||
flag = proc_->evaluate_function(loc, context_map);
|
||||
if (! flag)
|
||||
break;
|
||||
|
||||
// Evaluate the condition expression to try and get the
|
||||
// condition for the loop.
|
||||
NetExpr*cond = cond_->evaluate_function(loc, context_map);
|
||||
if (cond == 0) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
NetEConst*cond_const = dynamic_cast<NetEConst*> (cond);
|
||||
ivl_assert(loc, cond_const);
|
||||
|
||||
long val = cond_const->value().as_long();
|
||||
delete cond;
|
||||
|
||||
// If the condition is false, then the loop is done.
|
||||
if (val == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": NetDoWhile::evaluate_function: "
|
||||
<< "Done loop, flag=" << (flag?"true":"false") << endl;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetForever::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,LocalVar>&context_map) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -374,6 +374,15 @@ NexusSet* NetCondit::nex_input(bool rem_out)
|
|||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetDoWhile::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = proc_->nex_input(rem_out);
|
||||
NexusSet*tmp = cond_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetForce::nex_input(bool)
|
||||
{
|
||||
cerr << get_fileline() << ": internal warning: NetForce::nex_input()"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -117,6 +117,12 @@ void NetCondit::nex_output(NexusSet&out)
|
|||
else_->nex_output(out);
|
||||
}
|
||||
|
||||
void NetDoWhile::nex_output(NexusSet&out)
|
||||
{
|
||||
if (proc_ != 0)
|
||||
proc_->nex_output(out);
|
||||
}
|
||||
|
||||
void NetEvWait::nex_output(NexusSet&out)
|
||||
{
|
||||
assert(statement_);
|
||||
|
|
|
|||
|
|
@ -2810,6 +2810,14 @@ DelayType NetCondit::delay_type() const
|
|||
return combine_delays(if_type, el_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* A do/while will execute the body at least once.
|
||||
*/
|
||||
DelayType NetDoWhile::delay_type() const
|
||||
{
|
||||
return proc_->delay_type();
|
||||
}
|
||||
|
||||
DelayType NetEvWait::delay_type() const
|
||||
{
|
||||
return DEFINITE_DELAY;
|
||||
|
|
|
|||
28
netlist.h
28
netlist.h
|
|
@ -2913,6 +2913,34 @@ class NetDisable : public NetProc {
|
|||
NetDisable& operator= (const NetDisable&);
|
||||
};
|
||||
|
||||
/*
|
||||
* The do/while statement is a condition that is tested at the end of
|
||||
* each iteration, and a statement (a NetProc) that is executed once and
|
||||
* then again as long as the condition is true.
|
||||
*/
|
||||
class NetDoWhile : public NetProc {
|
||||
|
||||
public:
|
||||
NetDoWhile(NetExpr*c, NetProc*p)
|
||||
: cond_(c), proc_(p) { }
|
||||
|
||||
const NetExpr*expr() const { return cond_; }
|
||||
|
||||
void emit_proc_recurse(struct target_t*) const;
|
||||
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
virtual DelayType delay_type() const;
|
||||
virtual bool evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,LocalVar>&ctx) const;
|
||||
|
||||
private:
|
||||
NetExpr* cond_;
|
||||
NetProc*proc_;
|
||||
};
|
||||
|
||||
/*
|
||||
* A NetEvent is an object that represents an event object, that is
|
||||
* objects declared like so in Verilog:
|
||||
|
|
|
|||
11
parse.y
11
parse.y
|
|
@ -1289,6 +1289,12 @@ loop_statement /* IEEE1800-2005: A.6.8 */
|
|||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_do statement_or_null K_while '(' expression ')' ';'
|
||||
{ PDoWhile*tmp = new PDoWhile($5, $2);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_foreach '(' IDENTIFIER '[' loop_variables ']' ')' statement_or_null
|
||||
{ yyerror(@1, "sorry: foreach loops not supported");
|
||||
delete[]$3;
|
||||
|
|
@ -1321,6 +1327,11 @@ loop_statement /* IEEE1800-2005: A.6.8 */
|
|||
yyerror(@1, "error: Error in while loop condition.");
|
||||
}
|
||||
|
||||
| K_do statement_or_null K_while '(' error ')' ';'
|
||||
{ $$ = 0;
|
||||
yyerror(@1, "error: Error in do/while loop condition.");
|
||||
}
|
||||
|
||||
| K_foreach '(' IDENTIFIER '[' error ']' ')' statement_or_null
|
||||
{ $$ = 0;
|
||||
yyerror(@4, "error: Errors in foreach loop variables list.");
|
||||
|
|
|
|||
|
|
@ -840,6 +840,13 @@ void PDisable::dump(ostream&out, unsigned ind) const
|
|||
<< get_fileline() << " */" << endl;
|
||||
}
|
||||
|
||||
void PDoWhile::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "do" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
out << setw(ind) << "" << "while (" << *cond_ << ");" << endl;
|
||||
}
|
||||
|
||||
void PEventStatement::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
if (expr_.count() == 0) {
|
||||
|
|
|
|||
|
|
@ -2557,6 +2557,7 @@ extern "C" ivl_expr_t ivl_stmt_cond_expr(ivl_statement_t net)
|
|||
case IVL_ST_CASEZ:
|
||||
return net->u_.case_.cond;
|
||||
|
||||
case IVL_ST_DO_WHILE:
|
||||
case IVL_ST_REPEAT:
|
||||
case IVL_ST_WHILE:
|
||||
return net->u_.while_.cond_;
|
||||
|
|
@ -2819,6 +2820,7 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
|||
return net->u_.forever_.stmt_;
|
||||
case IVL_ST_WAIT:
|
||||
return net->u_.wait_.stmt_;
|
||||
case IVL_ST_DO_WHILE:
|
||||
case IVL_ST_REPEAT:
|
||||
case IVL_ST_WHILE:
|
||||
return net->u_.while_.stmt_;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -618,6 +618,31 @@ bool dll_target::proc_disable(const NetDisable*net)
|
|||
return true;
|
||||
}
|
||||
|
||||
void dll_target::proc_do_while(const NetDoWhile*net)
|
||||
{
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
FILE_NAME(stmt_cur_, net);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_DO_WHILE;
|
||||
stmt_cur_->u_.while_.stmt_ = (struct ivl_statement_s*)
|
||||
calloc(1, sizeof(struct ivl_statement_s));
|
||||
|
||||
assert(expr_ == 0);
|
||||
net->expr()->expr_scan(this);
|
||||
stmt_cur_->u_.while_.cond_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
/* Now generate the statement of the do/while loop. We know it is
|
||||
a single statement, and we know that the
|
||||
emit_proc_recurse() will call emit_proc() for it. */
|
||||
|
||||
ivl_statement_t save_cur_ = stmt_cur_;
|
||||
stmt_cur_ = save_cur_->u_.while_.stmt_;
|
||||
net->emit_proc_recurse(this);
|
||||
stmt_cur_ = save_cur_;
|
||||
}
|
||||
|
||||
bool dll_target::proc_force(const NetForce*net)
|
||||
{
|
||||
|
||||
|
|
|
|||
1
t-dll.h
1
t-dll.h
|
|
@ -118,6 +118,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
bool proc_deassign(const NetDeassign*);
|
||||
bool proc_delay(const NetPDelay*);
|
||||
bool proc_disable(const NetDisable*);
|
||||
void proc_do_while(const NetDoWhile*);
|
||||
bool proc_force(const NetForce*);
|
||||
void proc_forever(const NetForever*);
|
||||
void proc_free(const NetFree*);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 1998-2013 Stephen Williams <steve@icarus.com>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -364,6 +364,13 @@ bool target_t::proc_disable(const NetDisable*obj)
|
|||
return false;
|
||||
}
|
||||
|
||||
void target_t::proc_do_while(const NetDoWhile*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled do/while:" << endl;
|
||||
net->dump(cerr, 6);
|
||||
}
|
||||
|
||||
bool target_t::proc_force(const NetForce*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
|
|||
3
target.h
3
target.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __target_H
|
||||
#define __target_H
|
||||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -130,6 +130,7 @@ struct target_t {
|
|||
virtual bool proc_deassign(const NetDeassign*);
|
||||
virtual bool proc_delay(const NetPDelay*);
|
||||
virtual bool proc_disable(const NetDisable*);
|
||||
virtual void proc_do_while(const NetDoWhile*);
|
||||
virtual bool proc_force(const NetForce*);
|
||||
virtual void proc_forever(const NetForever*);
|
||||
virtual void proc_free(const NetFree*);
|
||||
|
|
|
|||
|
|
@ -388,6 +388,13 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
|||
show_stmt_disable(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_ST_DO_WHILE:
|
||||
fprintf(out, "%*sdo\n", ind, "");
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
fprintf(out, "%*swhile\n", ind, "");
|
||||
show_expression(ivl_stmt_cond_expr(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_ST_FORCE:
|
||||
show_stmt_force(net, ind);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1269,6 +1269,13 @@ void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
case IVL_ST_DISABLE:
|
||||
emit_stmt_disable(scope, stmt);
|
||||
break;
|
||||
case IVL_ST_DO_WHILE:
|
||||
fprintf(stderr, "%s:%u: vlog95 sorry: do/while is not "
|
||||
"currently translated.\n",
|
||||
ivl_stmt_file(stmt),
|
||||
ivl_stmt_lineno(stmt));
|
||||
vlog_errors += 1;
|
||||
break;
|
||||
case IVL_ST_FORCE:
|
||||
emit_stmt_force(scope, stmt);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1334,6 +1334,71 @@ static int show_stmt_disable(ivl_statement_t net, ivl_scope_t sscope)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static struct vector_info reduction_or(struct vector_info cvec)
|
||||
{
|
||||
struct vector_info result;
|
||||
|
||||
switch (cvec.base) {
|
||||
case 0:
|
||||
result.base = 0;
|
||||
result.wid = 1;
|
||||
break;
|
||||
case 1:
|
||||
result.base = 1;
|
||||
result.wid = 1;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
result.base = 0;
|
||||
result.wid = 1;
|
||||
break;
|
||||
default:
|
||||
clr_vector(cvec);
|
||||
result.base = allocate_vector(1);
|
||||
result.wid = 1;
|
||||
assert(result.base);
|
||||
fprintf(vvp_out, " %%or/r %u, %u, %u;\n", result.base,
|
||||
cvec.base, cvec.wid);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int show_stmt_do_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
{
|
||||
int rc = 0;
|
||||
struct vector_info cvec;
|
||||
|
||||
unsigned top_label = local_count++;
|
||||
|
||||
show_stmt_file_line(net, "Do/While statement.");
|
||||
|
||||
/* Start the loop. The top of the loop starts a basic block
|
||||
because it can be entered from above or from the bottom of
|
||||
the loop. */
|
||||
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, top_label);
|
||||
clear_expression_lookaside();
|
||||
|
||||
/* Draw the body of the loop. */
|
||||
rc += show_statement(ivl_stmt_sub_stmt(net), sscope);
|
||||
|
||||
/* Draw the evaluation of the condition expression, and test
|
||||
the result. If the expression evaluates to true, then
|
||||
branch to the top label. */
|
||||
cvec = draw_eval_expr(ivl_stmt_cond_expr(net), STUFF_OK_XZ|STUFF_OK_47);
|
||||
if (cvec.wid > 1)
|
||||
cvec = reduction_or(cvec);
|
||||
|
||||
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %u;\n",
|
||||
thread_count, top_label, cvec.base);
|
||||
if (cvec.base >= 8)
|
||||
clr_vector(cvec);
|
||||
|
||||
clear_expression_lookaside();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int show_stmt_force(ivl_statement_t net)
|
||||
{
|
||||
ivl_expr_t rval;
|
||||
|
|
@ -1645,37 +1710,6 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
|
|||
return show_statement(ivl_stmt_sub_stmt(net), sscope);
|
||||
}
|
||||
|
||||
static struct vector_info reduction_or(struct vector_info cvec)
|
||||
{
|
||||
struct vector_info result;
|
||||
|
||||
switch (cvec.base) {
|
||||
case 0:
|
||||
result.base = 0;
|
||||
result.wid = 1;
|
||||
break;
|
||||
case 1:
|
||||
result.base = 1;
|
||||
result.wid = 1;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
result.base = 0;
|
||||
result.wid = 1;
|
||||
break;
|
||||
default:
|
||||
clr_vector(cvec);
|
||||
result.base = allocate_vector(1);
|
||||
result.wid = 1;
|
||||
assert(result.base);
|
||||
fprintf(vvp_out, " %%or/r %u, %u, %u;\n", result.base,
|
||||
cvec.base, cvec.wid);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -2184,6 +2218,10 @@ static int show_statement(ivl_statement_t net, ivl_scope_t sscope)
|
|||
rc += show_stmt_disable(net, sscope);
|
||||
break;
|
||||
|
||||
case IVL_ST_DO_WHILE:
|
||||
rc += show_stmt_do_while(net, sscope);
|
||||
break;
|
||||
|
||||
case IVL_ST_FORCE:
|
||||
rc += show_stmt_force(net);
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue