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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* 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 (! genvars.empty()) return;
|
||||||
if (! behaviors.empty()) return;
|
if (! behaviors.empty()) return;
|
||||||
if (! analog_behaviors.empty()) return;
|
if (! analog_behaviors.empty()) return;
|
||||||
|
if (! elab_tasks.empty()) return;
|
||||||
|
|
||||||
if (generate_schemes.empty()) return;
|
if (generate_schemes.empty()) return;
|
||||||
|
|
||||||
|
|
|
||||||
6
PScope.h
6
PScope.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_PScope_H
|
#ifndef IVL_PScope_H
|
||||||
#define 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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -37,6 +37,7 @@ class PClass;
|
||||||
class PTask;
|
class PTask;
|
||||||
class PWire;
|
class PWire;
|
||||||
class Statement;
|
class Statement;
|
||||||
|
class PCallTask;
|
||||||
|
|
||||||
class Design;
|
class Design;
|
||||||
class NetScope;
|
class NetScope;
|
||||||
|
|
@ -133,6 +134,9 @@ class LexicalScope {
|
||||||
list<PProcess*> behaviors;
|
list<PProcess*> behaviors;
|
||||||
list<AProcess*> analog_behaviors;
|
list<AProcess*> analog_behaviors;
|
||||||
|
|
||||||
|
// The elaboration tasks in this scope
|
||||||
|
list<PCallTask*> elab_tasks;
|
||||||
|
|
||||||
// Enumeration sets.
|
// Enumeration sets.
|
||||||
std::set<enum_type_t*> enum_sets;
|
std::set<enum_type_t*> enum_sets;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_Statement_H
|
#ifndef IVL_Statement_H
|
||||||
#define 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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* 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 void dump(ostream&out, unsigned ind) const;
|
||||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
|
bool elaborate_elab(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||||
|
|
|
||||||
27
elab_expr.cc
27
elab_expr.cc
|
|
@ -4628,7 +4628,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
if (net->struct_type() && !member_path.empty()) {
|
if (net->struct_type() && !member_path.empty()) {
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||||
<< "Ident " << base_path
|
"Ident " << base_path
|
||||||
<< " look for struct member " << member_path
|
<< " look for struct member " << member_path
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
@ -4645,7 +4645,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
if (net->darray_type() && !member_path.empty()) {
|
if (net->darray_type() && !member_path.empty()) {
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||||
<< "Ident " << base_path
|
"Ident " << base_path
|
||||||
<< " looking for array property " << member_path
|
<< " looking for array property " << member_path
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
@ -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 (net->class_type() && !member_path.empty()) {
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||||
<< "Ident " << base_path
|
"Ident " << base_path
|
||||||
<< " look for class property " << member_path
|
<< " look for class property " << member_path
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
@ -4814,7 +4831,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
const netenum_t*netenum = net->enumeration();
|
const netenum_t*netenum = net->enumeration();
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||||
<< "Ident " << base_path
|
"Ident " << base_path
|
||||||
<< " look for enumeration method " << member_path
|
<< " look for enumeration method " << member_path
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
@ -4837,7 +4854,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
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->expr_width()=" << tmp->expr_width()
|
||||||
<< ", tmp=" << *tmp << endl;
|
<< ", tmp=" << *tmp << endl;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -990,7 +990,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||||
cerr << wid << "] is selecting after vector." << endl;
|
cerr << wid << "] is selecting after vector." << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (warn_ob_select) {
|
||||||
cerr << get_fileline() << ": warning: L-value indexed part "
|
cerr << get_fileline() << ": warning: L-value indexed part "
|
||||||
<< "select of " << reg->name();
|
<< "select of " << reg->name();
|
||||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||||
|
|
|
||||||
109
elaborate.cc
109
elaborate.cc
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
|
# include <cstring>
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
# include <sstream>
|
# include <sstream>
|
||||||
# include <list>
|
# include <list>
|
||||||
|
|
@ -2570,7 +2571,6 @@ static bool lval_not_program_variable(const NetAssign_*lv)
|
||||||
{
|
{
|
||||||
while (lv) {
|
while (lv) {
|
||||||
NetScope*sig_scope = lv->scope();
|
NetScope*sig_scope = lv->scope();
|
||||||
// NetScope*sig_scope = lv->sig()->scope(); // FIXME: The is had this line
|
|
||||||
if (! sig_scope->program_block()) return true;
|
if (! sig_scope->program_block()) return true;
|
||||||
lv = lv->more;
|
lv = lv->more;
|
||||||
}
|
}
|
||||||
|
|
@ -4179,6 +4179,107 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||||
return block;
|
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
|
* Elaborate a procedural continuous assign. This really looks very
|
||||||
* much like other procedural assignments, at this point, but there
|
* 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);
|
(*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;
|
return result_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
parse.y
12
parse.y
|
|
@ -5359,6 +5359,18 @@ module_item
|
||||||
K_endcase
|
K_endcase
|
||||||
{ pform_endgenerate(true); }
|
{ 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
|
| modport_declaration
|
||||||
|
|
||||||
/* 1364-2001 and later allow specparam declarations outside specify blocks. */
|
/* 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;
|
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;
|
MIN_TYP_MAX min_typ_max_flag = TYP;
|
||||||
unsigned min_typ_max_warn = 10;
|
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 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,
|
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
|
||||||
std::list<pform_range_t>*unp_ranges);
|
std::list<pform_range_t>*unp_ranges);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1435,6 +1435,11 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
||||||
(*idx)->dump(out, indent+2);
|
(*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;
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
|
||||||
for (genvar_iter_t cur = genvars.begin()
|
for (genvar_iter_t cur = genvars.begin()
|
||||||
; cur != genvars.end() ; ++ cur ) {
|
; cur != genvars.end() ; ++ cur ) {
|
||||||
|
|
@ -1742,6 +1747,11 @@ void Module::dump(ostream&out) const
|
||||||
(*idx)->dump(out, 4);
|
(*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()
|
for (list<PSpecPath*>::const_iterator spec = specify_paths.begin()
|
||||||
; spec != specify_paths.end() ; ++ spec ) {
|
; 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 "
|
vpi_printf("WARNING: %s:%d: a single %% at the end of format string "
|
||||||
"%s%s will be displayed as '%%'.\n",
|
"%s%s will be displayed as '%%'.\n",
|
||||||
info->filename, info->lineno, info->name, fmtb);
|
info->filename, info->lineno, info->name, fmtb);
|
||||||
|
// fallthrough
|
||||||
case '%':
|
case '%':
|
||||||
if (ljust != 0 || plus != 0 || ld_zero != 0 || width != -1 ||
|
if (ljust != 0 || plus != 0 || ld_zero != 0 || width != -1 ||
|
||||||
prec != -1) {
|
prec != -1) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue