Some clean up and add initial support for elaboration system tasks

This commit is contained in:
Cary R 2021-02-01 00:20:09 -08:00
parent 8484ff71ac
commit 18392a464d
11 changed files with 183 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2021 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
@ -61,6 +61,7 @@ void PGenerate::probe_for_direct_nesting_(void)
if (! genvars.empty()) return;
if (! behaviors.empty()) return;
if (! analog_behaviors.empty()) return;
if (! elab_tasks.empty()) return;
if (generate_schemes.empty()) return;

View File

@ -1,7 +1,7 @@
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2021 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
@ -37,6 +37,7 @@ class PClass;
class PTask;
class PWire;
class Statement;
class PCallTask;
class Design;
class NetScope;
@ -133,6 +134,9 @@ class LexicalScope {
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
// The elaboration tasks in this scope
list<PCallTask*> elab_tasks;
// Enumeration sets.
std::set<enum_type_t*> enum_sets;

View File

@ -1,7 +1,7 @@
#ifndef IVL_Statement_H
#define IVL_Statement_H
/*
* Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2021 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
@ -225,6 +225,8 @@ class PCallTask : public Statement {
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
bool elaborate_elab(Design*des, NetScope*scope) const;
private:
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const;

View File

@ -4628,7 +4628,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (net->struct_type() && !member_path.empty()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Ident " << base_path
"Ident " << base_path
<< " look for struct member " << member_path
<< endl;
}
@ -4644,10 +4644,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// the member_path, check for array properties.
if (net->darray_type() && !member_path.empty()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Ident " << base_path
<< " looking for array property " << member_path
<< endl;
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
"Ident " << base_path
<< " looking for array property " << member_path
<< endl;
}
ivl_assert(*this, member_path.size() == 1);
@ -4796,10 +4796,27 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
}
if ((net->data_type() == IVL_VT_STRING) && !member_path.empty()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
"Ident " << base_path
<< " looking for string property " << member_path
<< endl;
}
ivl_assert(*this, member_path.size() == 1);
const name_component_t member_comp = member_path.front();
cerr << get_fileline() << ": sorry: String method '"
<< member_comp.name << "' currently requires ()."
<< endl;
des->errors += 1;
return 0;
}
if (net->class_type() && !member_path.empty()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Ident " << base_path
"Ident " << base_path
<< " look for class property " << member_path
<< endl;
}
@ -4814,7 +4831,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
const netenum_t*netenum = net->enumeration();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Ident " << base_path
"Ident " << base_path
<< " look for enumeration method " << member_path
<< endl;
}
@ -4837,7 +4854,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Expression as net. expr_wid=" << expr_wid
"Expression as net. expr_wid=" << expr_wid
<< ", tmp->expr_width()=" << tmp->expr_width()
<< ", tmp=" << *tmp << endl;
}
@ -4970,7 +4987,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// I cannot interpret this identifier. Error message.
cerr << get_fileline() << ": error: Unable to bind wire/reg/memory "
"`" << path_ << "' in `" << scope_path(scope) << "'" << endl;
"`" << path_ << "' in `" << scope_path(scope) << "'" << endl;
des->errors += 1;
return 0;
}

View File

@ -990,7 +990,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
cerr << wid << "] is selecting after vector." << endl;
}
}
} else {
} else if (warn_ob_select) {
cerr << get_fileline() << ": warning: L-value indexed part "
<< "select of " << reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";

View File

@ -29,6 +29,7 @@
# include <typeinfo>
# include <cstdlib>
# include <cstring>
# include <iostream>
# include <sstream>
# include <list>
@ -2570,7 +2571,6 @@ static bool lval_not_program_variable(const NetAssign_*lv)
{
while (lv) {
NetScope*sig_scope = lv->scope();
// NetScope*sig_scope = lv->sig()->scope(); // FIXME: The is had this line
if (! sig_scope->program_block()) return true;
lv = lv->more;
}
@ -4179,6 +4179,107 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
return block;
}
static bool check_parm_is_const(NetExpr*param)
{
// FIXME: Are these actually needed and are others needed?
// if (dynamic_cast<NetEConstEnum*>(param)) { cerr << "Enum" << endl; return; }
// if (dynamic_cast<NetECString*>(param)) { cerr << "String" << endl; return; }
if (dynamic_cast<NetEConstParam*>(param)) return true;
if (dynamic_cast<NetECReal*>(param)) return true;
if (dynamic_cast<NetECRealParam*>(param)) return true;
if (dynamic_cast<NetEConst*>(param)) return true;
return false;
}
/* Elaborate an elaboration task. */
bool PCallTask::elaborate_elab(Design*des, NetScope*scope) const
{
assert(scope);
assert(path_.size() == 1);
unsigned parm_count = parms_.size();
/* Catch the special case that the elaboration task has no
parameters. The "()" string will be parsed as a single
empty parameter, when we really mean no parameters at all. */
if ((parm_count== 1) && (parms_[0] == 0))
parm_count = 0;
perm_string name = peek_tail_name(path_);
if (!gn_system_verilog()) {
cerr << get_fileline() << ": error: Elaboration task '"
<< name << "' requires SystemVerilog." << endl;
des->errors += 1;
return false;
}
if (name != "$fatal" &&
name != "$error" &&
name != "$warning" &&
name != "$info") {
cerr << get_fileline() << ": error: '" << name
<< "' is not a valid elaboration task." << endl;
des->errors += 1;
return true;
}
vector<NetExpr*>eparms (parm_count);
bool const_parms = true;
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
PExpr*ex = parms_[idx];
if (ex != 0) {
eparms[idx] = elab_sys_task_arg(des, scope, name, idx, ex);
if (!check_parm_is_const(eparms[idx])) {
cerr << get_fileline() << ": error: Elaboration task "
<< name << " parameter [" << idx+1 << "] '"
<< *eparms[idx] << "' is not constant." << endl;
des->errors += 1;
const_parms = false;
}
} else {
eparms[idx] = 0;
}
}
if (!const_parms) return true;
/* Drop the $ and convert to upper case for the severity string */
string sstr = name.str()+1;
transform(sstr.begin(), sstr.end(), sstr.begin(), ::toupper);
cerr << sstr << ": " << get_fileline() << ":";
if (parm_count != 0) {
cerr << " ";
/*
cerr << *eparms[0];
for (unsigned idx = 1; idx < parm_count; idx += 1) {
cerr << ", " << *eparms[idx];
}
*/
// FIXME: Need to actually handle this.
cerr << "sorry: Elaboration tasks with arguments "
"are not currently supported.";
des->errors += 1;
}
cerr << endl;
cerr << string(sstr.size(), ' ') << " During elaboration Scope: "
<< scope->fullname() << endl;
// For a fatal mark as an error and fail elaboration.
if (name == "$fatal") {
des->errors += 1;
return false;
}
// For an error just set it as an error.
if (name == "$error") des->errors += 1;
return true;
}
/*
* Elaborate a procedural continuous assign. This really looks very
* much like other procedural assignments, at this point, but there
@ -6113,6 +6214,12 @@ bool Module::elaborate(Design*des, NetScope*scope) const
(*sp)->elaborate(des, scope);
}
// Elaborate the elaboration tasks.
for (list<PCallTask*>::const_iterator et = elab_tasks.begin()
; et != elab_tasks.end() ; ++ et ) {
result_flag &= (*et)->elaborate_elab(des, scope);
}
return result_flag;
}

12
parse.y
View File

@ -5359,6 +5359,18 @@ module_item
K_endcase
{ pform_endgenerate(true); }
/* Elaboration system tasks. */
| SYSTEM_IDENTIFIER '(' expression_list_with_nuls ')' ';'
{ pform_make_elab_task(@1, lex_strings.make($1), *$3);
delete[]$1;
delete $3;
}
| SYSTEM_IDENTIFIER ';'
{ list<PExpr*>pt;
pform_make_elab_task(@1, lex_strings.make($1), pt);
delete[]$1;
}
| modport_declaration
/* 1364-2001 and later allow specparam declarations outside specify blocks. */

View File

@ -1694,6 +1694,16 @@ void pform_endgenerate(bool end_conditional)
pform_cur_generate = parent_generate;
}
void pform_make_elab_task(const struct vlltype&li,
perm_string name,
const list<PExpr*>&params)
{
PCallTask*elab_task = new PCallTask(name, params);
FILE_NAME(elab_task, li);
lexical_scope->elab_tasks.push_back(elab_task);
}
MIN_TYP_MAX min_typ_max_flag = TYP;
unsigned min_typ_max_warn = 10;

View File

@ -313,6 +313,10 @@ extern void pform_endgenerate(bool end_conditional);
*/
extern PGenerate* pform_parent_generate(void);
extern void pform_make_elab_task(const struct vlltype&li,
perm_string name,
const std::list<PExpr*>&params);
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
std::list<pform_range_t>*unp_ranges);

View File

@ -1435,6 +1435,11 @@ void PGenerate::dump(ostream&out, unsigned indent) const
(*idx)->dump(out, indent+2);
}
for (list<PCallTask*>::const_iterator idx = elab_tasks.begin()
; idx != elab_tasks.end() ; ++ idx ) {
(*idx)->dump(out, indent+2);
}
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
for (genvar_iter_t cur = genvars.begin()
; cur != genvars.end() ; ++ cur ) {
@ -1742,6 +1747,11 @@ void Module::dump(ostream&out) const
(*idx)->dump(out, 4);
}
for (list<PCallTask*>::const_iterator idx = elab_tasks.begin()
; idx != elab_tasks.end() ; ++ idx ) {
(*idx)->dump(out, 4);
}
for (list<PSpecPath*>::const_iterator spec = specify_paths.begin()
; spec != specify_paths.end() ; ++ spec ) {

View File

@ -316,6 +316,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
vpi_printf("WARNING: %s:%d: a single %% at the end of format string "
"%s%s will be displayed as '%%'.\n",
info->filename, info->lineno, info->name, fmtb);
// fallthrough
case '%':
if (ljust != 0 || plus != 0 || ld_zero != 0 || width != -1 ||
prec != -1) {
@ -2158,7 +2159,7 @@ static PLI_INT32 sys_severity_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
vpi_printf("\n%*s Time: %" PLI_UINT64_FMT " Scope: %s\n",
vpi_printf("\n%*s Time: %" PLI_UINT64_FMT " Scope: %s\n",
(int)strlen(sstr), " ", now64,
vpi_get_str(vpiFullName, scope));