Some clean up and add initial support for elaboration system tasks
This commit is contained in:
parent
8484ff71ac
commit
18392a464d
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
6
PScope.h
6
PScope.h
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
35
elab_expr.cc
35
elab_expr.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 << "[]";
|
||||
|
|
|
|||
109
elaborate.cc
109
elaborate.cc
|
|
@ -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
12
parse.y
|
|
@ -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. */
|
||||
|
|
|
|||
10
pform.cc
10
pform.cc
|
|
@ -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*>¶ms)
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
|||
4
pform.h
4
pform.h
|
|
@ -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*>¶ms);
|
||||
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
|
||||
std::list<pform_range_t>*unp_ranges);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue