Parse and elaborate unique and priority case statements
The unique, unique0, and priority keywords can decorate case statements to tell the run time (or synthesis) to do extra tests (or make extra assumptions). These tests are not implemented in the vvp run time, but now the decorations make it to the code generators.
This commit is contained in:
parent
70da8db6b5
commit
befc91340c
|
|
@ -206,8 +206,8 @@ const pform_name_t& PCallTask::path() const
|
|||
return path_;
|
||||
}
|
||||
|
||||
PCase::PCase(NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
|
||||
: type_(t), expr_(ex), items_(l)
|
||||
PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
|
||||
: quality_(q), type_(t), expr_(ex), items_(l)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ class PCase : public Statement {
|
|||
Statement*stat;
|
||||
};
|
||||
|
||||
PCase(NetCase::TYPE, PExpr*ex, svector<Item*>*);
|
||||
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, svector<Item*>*);
|
||||
~PCase();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
|
@ -263,6 +263,7 @@ class PCase : public Statement {
|
|||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_case_quality_t quality_;
|
||||
NetCase::TYPE type_;
|
||||
PExpr*expr_;
|
||||
|
||||
|
|
|
|||
|
|
@ -1150,15 +1150,29 @@ void NetBlock::dump(ostream&o, unsigned ind) const
|
|||
|
||||
void NetCase::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
switch (quality_) {
|
||||
case IVL_CASE_QUALITY_BASIC:
|
||||
break;
|
||||
case IVL_CASE_QUALITY_UNIQUE:
|
||||
o << "unique ";
|
||||
break;
|
||||
case IVL_CASE_QUALITY_UNIQUE0:
|
||||
o << "unique0 ";
|
||||
break;
|
||||
case IVL_CASE_QUALITY_PRIORITY:
|
||||
o << "priority ";
|
||||
break;
|
||||
}
|
||||
switch (type_) {
|
||||
case EQ:
|
||||
o << setw(ind) << "" << "case (" << *expr_ << ")" << endl;
|
||||
o << "case (" << *expr_ << ")" << endl;
|
||||
break;
|
||||
case EQX:
|
||||
o << setw(ind) << "" << "casex (" << *expr_ << ")" << endl;
|
||||
o << "casex (" << *expr_ << ")" << endl;
|
||||
break;
|
||||
case EQZ:
|
||||
o << setw(ind) << "" << "casez (" << *expr_ << ")" << endl;
|
||||
o << "casez (" << *expr_ << ")" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3127,7 +3127,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
|||
icount += cur->expr.size();
|
||||
}
|
||||
|
||||
NetCase*res = new NetCase(type_, expr, icount);
|
||||
NetCase*res = new NetCase(quality_, type_, expr, icount);
|
||||
res->set_line(*this);
|
||||
|
||||
/* Iterate over all the case items (guard/statement pairs)
|
||||
|
|
|
|||
10
ivl_target.h
10
ivl_target.h
|
|
@ -434,6 +434,14 @@ typedef enum ivl_statement_type_e {
|
|||
IVL_ST_WHILE = 23
|
||||
} ivl_statement_type_t;
|
||||
|
||||
/* Case statements can be tagged as unique/unique0/priority. */
|
||||
typedef enum ivl_case_quality_t {
|
||||
IVL_CASE_QUALITY_BASIC = 0, /* no quality flags */
|
||||
IVL_CASE_QUALITY_UNIQUE = 1,
|
||||
IVL_CASE_QUALITY_UNIQUE0 = 2,
|
||||
IVL_CASE_QUALITY_PRIORITY = 3
|
||||
} ivl_case_quality_t;
|
||||
|
||||
/* SystemVerilog allows a system function to be called as a task. */
|
||||
typedef enum ivl_sfunc_as_task_e {
|
||||
IVL_SFUNC_AS_TASK_ERROR = 0,
|
||||
|
|
@ -2222,6 +2230,8 @@ extern ivl_scope_t ivl_stmt_call(ivl_statement_t net);
|
|||
extern unsigned ivl_stmt_case_count(ivl_statement_t net);
|
||||
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
|
||||
extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i);
|
||||
/* IVL+ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
|
||||
extern ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net);
|
||||
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
|
||||
extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i);
|
||||
/* IVL_ST_CONDIT IVL_ST_CASE IVL_ST_REPEAT IVL_ST_WHILE */
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const
|
|||
return cur->next_;
|
||||
}
|
||||
|
||||
NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt)
|
||||
: type_(c), expr_(ex), items_(cnt)
|
||||
NetCase::NetCase(ivl_case_quality_t q, NetCase::TYPE c, NetExpr*ex, unsigned cnt)
|
||||
: quality_(q), type_(c), expr_(ex), items_(cnt)
|
||||
{
|
||||
ivl_assert(*this, expr_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3050,6 +3050,9 @@ class NetBlock : public NetProc {
|
|||
* way the comparisons are performed. Also, it is likely that the
|
||||
* target may be able to optimize differently.
|
||||
*
|
||||
* Case statements can have unique, unique0, or priority attached to
|
||||
* them. If not otherwise adorned, it is QBASIC.
|
||||
*
|
||||
* Case can be one of three types:
|
||||
* EQ -- All bits must exactly match
|
||||
* EQZ -- z bits are don't care
|
||||
|
|
@ -3059,13 +3062,15 @@ class NetCase : public NetProc {
|
|||
|
||||
public:
|
||||
enum TYPE { EQ, EQX, EQZ };
|
||||
NetCase(TYPE c, NetExpr*ex, unsigned cnt);
|
||||
|
||||
NetCase(ivl_case_quality_t q, TYPE c, NetExpr*ex, unsigned cnt);
|
||||
~NetCase();
|
||||
|
||||
void set_case(unsigned idx, NetExpr*ex, NetProc*st);
|
||||
|
||||
void prune();
|
||||
|
||||
inline ivl_case_quality_t case_quality() const { return quality_; }
|
||||
TYPE type() const;
|
||||
const NetExpr*expr() const { return expr_; }
|
||||
inline unsigned nitems() const { return items_.size(); }
|
||||
|
|
@ -3097,6 +3102,7 @@ class NetCase : public NetProc {
|
|||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
ivl_case_quality_t quality_;
|
||||
TYPE type_;
|
||||
|
||||
struct Item {
|
||||
|
|
|
|||
53
parse.y
53
parse.y
|
|
@ -408,6 +408,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
|
||||
svector<PEEvent*>*event_expr;
|
||||
|
||||
ivl_case_quality_t case_quality;
|
||||
NetNet::Type nettype;
|
||||
PGBuiltin::Type gatetype;
|
||||
NetNet::PortType porttype;
|
||||
|
|
@ -677,6 +678,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
|
||||
%type <lifetime> lifetime lifetime_opt
|
||||
|
||||
%type <case_quality> unique_priority
|
||||
|
||||
%token K_TAND
|
||||
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
||||
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
|
||||
|
|
@ -6618,27 +6621,28 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
|
||||
| jump_statement { $$ = $1; }
|
||||
|
||||
| K_case '(' expression ')' case_items K_endcase
|
||||
{ PCase*tmp = new PCase(NetCase::EQ, $3, $5);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_casex '(' expression ')' case_items K_endcase
|
||||
{ PCase*tmp = new PCase(NetCase::EQX, $3, $5);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_casez '(' expression ')' case_items K_endcase
|
||||
{ PCase*tmp = new PCase(NetCase::EQZ, $3, $5);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_case '(' expression ')' error K_endcase
|
||||
{ yyerrok; }
|
||||
| K_casex '(' expression ')' error K_endcase
|
||||
{ yyerrok; }
|
||||
| K_casez '(' expression ')' error K_endcase
|
||||
{ yyerrok; }
|
||||
| unique_priority K_case '(' expression ')' case_items K_endcase
|
||||
{ PCase*tmp = new PCase($1, NetCase::EQ, $4, $6);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| unique_priority K_casex '(' expression ')' case_items K_endcase
|
||||
{ PCase*tmp = new PCase($1, NetCase::EQX, $4, $6);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| unique_priority K_casez '(' expression ')' case_items K_endcase
|
||||
{ PCase*tmp = new PCase($1, NetCase::EQZ, $4, $6);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| unique_priority K_case '(' expression ')' error K_endcase
|
||||
{ yyerrok; }
|
||||
| unique_priority K_casex '(' expression ')' error K_endcase
|
||||
{ yyerrok; }
|
||||
| unique_priority K_casez '(' expression ')' error K_endcase
|
||||
{ yyerrok; }
|
||||
|
||||
| K_if '(' expression ')' statement_or_null %prec less_than_K_else
|
||||
{ PCondit*tmp = new PCondit($3, $5, 0);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
|
@ -7293,6 +7297,13 @@ udp_primitive
|
|||
}
|
||||
;
|
||||
|
||||
unique_priority
|
||||
: { $$ = IVL_CASE_QUALITY_BASIC; }
|
||||
| K_unique { $$ = IVL_CASE_QUALITY_UNIQUE; }
|
||||
| K_unique0 { $$ = IVL_CASE_QUALITY_UNIQUE0; }
|
||||
| K_priority { $$ = IVL_CASE_QUALITY_PRIORITY; }
|
||||
;
|
||||
|
||||
/* Many keywords can be optional in the syntax, although their
|
||||
presence is significant. This is a fairly common pattern so
|
||||
collect those rules here. */
|
||||
|
|
|
|||
|
|
@ -840,6 +840,19 @@ void PCallTask::dump(ostream&out, unsigned ind) const
|
|||
void PCase::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "";
|
||||
switch (quality_) {
|
||||
case IVL_CASE_QUALITY_BASIC:
|
||||
break;
|
||||
case IVL_CASE_QUALITY_UNIQUE:
|
||||
out << "unique ";
|
||||
break;
|
||||
case IVL_CASE_QUALITY_UNIQUE0:
|
||||
out << "unique0 ";
|
||||
break;
|
||||
case IVL_CASE_QUALITY_PRIORITY:
|
||||
out << "priority ";
|
||||
break;
|
||||
}
|
||||
switch (type_) {
|
||||
case NetCase::EQ:
|
||||
out << "case";
|
||||
|
|
|
|||
16
t-dll-api.cc
16
t-dll-api.cc
|
|
@ -2728,6 +2728,22 @@ extern "C" ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned idx)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASE:
|
||||
case IVL_ST_CASER:
|
||||
case IVL_ST_CASEX:
|
||||
case IVL_ST_CASEZ:
|
||||
return net->u_.case_.quality;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return IVL_CASE_QUALITY_BASIC;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
|
|
|
|||
|
|
@ -497,6 +497,7 @@ void dll_target::proc_case(const NetCase*net)
|
|||
}
|
||||
assert(stmt_cur_->type_ != IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->u_.case_.quality = net->case_quality();
|
||||
assert(expr_ == 0);
|
||||
assert(net->expr());
|
||||
net->expr()->expr_scan(this);
|
||||
|
|
|
|||
1
t-dll.h
1
t-dll.h
|
|
@ -810,6 +810,7 @@ struct ivl_statement_s {
|
|||
} block_;
|
||||
|
||||
struct { /* IVL_ST_CASE, IVL_ST_CASEX, IVL_ST_CASEZ */
|
||||
ivl_case_quality_t quality;
|
||||
ivl_expr_t cond;
|
||||
unsigned ncase;
|
||||
ivl_expr_t*case_ex;
|
||||
|
|
|
|||
|
|
@ -375,8 +375,24 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
|||
case IVL_ST_CASEZ:
|
||||
case IVL_ST_CASER:
|
||||
case IVL_ST_CASE: {
|
||||
ivl_case_quality_t qual = ivl_stmt_case_quality(net);
|
||||
unsigned cnt = ivl_stmt_case_count(net);
|
||||
fprintf(out, "%*scase (...) <%u cases>\n", ind, "", cnt);
|
||||
const char*qual_txt = "";
|
||||
switch (qual) {
|
||||
case IVL_CASE_QUALITY_BASIC:
|
||||
qual_txt = "basic";
|
||||
break;
|
||||
case IVL_CASE_QUALITY_UNIQUE:
|
||||
qual_txt = "unique";
|
||||
break;
|
||||
case IVL_CASE_QUALITY_UNIQUE0:
|
||||
qual_txt = "unique0";
|
||||
break;
|
||||
case IVL_CASE_QUALITY_PRIORITY:
|
||||
qual_txt = "priority";
|
||||
break;
|
||||
}
|
||||
fprintf(out, "%*scase (...) <%u cases, %s>\n", ind, "", cnt, qual_txt);
|
||||
show_expression(ivl_stmt_cond_expr(net), ind+4);
|
||||
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
|
|
|
|||
|
|
@ -644,6 +644,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
|
|||
static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
||||
{
|
||||
int rc = 0;
|
||||
ivl_case_quality_t qual = ivl_stmt_case_quality(net);
|
||||
ivl_expr_t expr = ivl_stmt_cond_expr(net);
|
||||
unsigned count = ivl_stmt_case_count(net);
|
||||
|
||||
|
|
@ -651,6 +652,12 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
|||
|
||||
unsigned idx, default_case;
|
||||
|
||||
if (qual != IVL_CASE_QUALITY_BASIC) {
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: "
|
||||
"Case unique/unique0/priority qualities are ignored.\n",
|
||||
ivl_stmt_file(net), ivl_stmt_lineno(net));
|
||||
}
|
||||
|
||||
show_stmt_file_line(net, "Case statement.");
|
||||
|
||||
local_count += count + 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue