Merge branch 'x-ms1'
This commit is contained in:
commit
3657b15428
|
|
@ -110,9 +110,10 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
|||
netenum.o netstruct.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \
|
||||
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
|
||||
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
|
||||
pform_disciplines.o pform_dump.o pform_struct_type.o pform_types.o \
|
||||
pform_disciplines.o pform_dump.o pform_pclass.o pform_struct_type.o \
|
||||
pform_types.o \
|
||||
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
|
||||
Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
|
||||
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
|
||||
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
||||
Statement.o AStatement.o $M $(FF) $(TT)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ list<Module::named_expr_t> Module::user_defparms;
|
|||
|
||||
/* n is a permallocated string. */
|
||||
Module::Module(perm_string n)
|
||||
: PScope(n)
|
||||
: PScopeExtra(n)
|
||||
{
|
||||
library_flag = false;
|
||||
is_cell = false;
|
||||
|
|
|
|||
6
Module.h
6
Module.h
|
|
@ -49,7 +49,7 @@ class NetScope;
|
|||
* therefore the handle for grasping the described circuit.
|
||||
*/
|
||||
|
||||
class Module : public PScope, public LineInfo {
|
||||
class Module : public PScopeExtra, public LineInfo {
|
||||
|
||||
/* The module ports are in general a vector of port_t
|
||||
objects. Each port has a name and an ordered list of
|
||||
|
|
@ -112,10 +112,6 @@ class Module : public PScope, public LineInfo {
|
|||
bool time_from_timescale;
|
||||
bool timescale_warn_done;
|
||||
|
||||
/* Task definitions within this module */
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*> funcs;
|
||||
|
||||
/* The module has a list of generate schemes that appear in
|
||||
the module definition. These are used at elaboration time. */
|
||||
list<PGenerate*> generate_schemes;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2012 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "PClass.h"
|
||||
|
||||
PClass::PClass(perm_string name, LexicalScope*parent)
|
||||
: PScopeExtra(name, parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PClass::~PClass()
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef __PClass_H
|
||||
#define __PClass_H
|
||||
/*
|
||||
* Copyright (c) 2012 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "PScope.h"
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
|
||||
/*
|
||||
* SystemVerilog supports class declarations with their own lexical
|
||||
* scope, etc. The parser arranges for these to be created and
|
||||
* collected.
|
||||
*/
|
||||
|
||||
class PClass : public PScopeExtra, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PClass (perm_string name, LexicalScope*parent);
|
||||
~PClass();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
4
PExpr.h
4
PExpr.h
|
|
@ -509,6 +509,10 @@ class PEUnary : public PExpr {
|
|||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
public:
|
||||
inline char get_op() const { return op_; }
|
||||
inline PExpr*get_expr() const { return expr_; }
|
||||
|
||||
private:
|
||||
NetExpr* elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const;
|
||||
|
||||
|
|
|
|||
15
PScope.cc
15
PScope.cc
|
|
@ -41,3 +41,18 @@ PWire* LexicalScope::wires_find(perm_string name)
|
|||
else
|
||||
return (*cur).second;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||
: PScope(n, parent)
|
||||
{
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n)
|
||||
: PScope(n)
|
||||
{
|
||||
}
|
||||
|
||||
PScopeExtra::~PScopeExtra()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
19
PScope.h
19
PScope.h
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PFunction;
|
||||
class AProcess;
|
||||
class PProcess;
|
||||
class PTask;
|
||||
class PWire;
|
||||
|
||||
class Design;
|
||||
|
|
@ -150,4 +152,21 @@ class PScope : public LexicalScope {
|
|||
perm_string name_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Some scopes can carry definitions. These include Modules and PClass
|
||||
* scopes. These derive from PScopeExtra so that they hold the maps of
|
||||
* extra definitions.
|
||||
*/
|
||||
class PScopeExtra : public PScope {
|
||||
|
||||
public:
|
||||
PScopeExtra(perm_string, LexicalScope*parent);
|
||||
PScopeExtra(perm_string);
|
||||
~PScopeExtra();
|
||||
|
||||
/* Task definitions within this module */
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*> funcs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
8
PTask.h
8
PTask.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999-2008,2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008,2010,2012 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
|
||||
|
|
@ -41,12 +41,14 @@ enum PTaskFuncEnum {
|
|||
PTF_REALTIME,
|
||||
PTF_TIME,
|
||||
PTF_ATOM2,
|
||||
PTF_ATOM2_S
|
||||
PTF_ATOM2_S,
|
||||
PTF_STRING,
|
||||
PTF_VOID
|
||||
};
|
||||
|
||||
struct PTaskFuncArg {
|
||||
PTaskFuncEnum type;
|
||||
vector<PExpr*>*range;
|
||||
std::list<index_component_t>*range;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -276,9 +276,8 @@ PForever::~PForever()
|
|||
}
|
||||
|
||||
PForStatement::PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
|
||||
PExpr*n2, PExpr*e2, Statement*st)
|
||||
: name1_(n1), expr1_(e1), cond_(cond), name2_(n2), expr2_(e2),
|
||||
statement_(st)
|
||||
Statement*step, Statement*st)
|
||||
: name1_(n1), expr1_(e1), cond_(cond), step_(step), statement_(st)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
17
Statement.h
17
Statement.h
|
|
@ -196,18 +196,6 @@ class PCallTask : public Statement {
|
|||
|
||||
const pform_name_t& path() const;
|
||||
|
||||
unsigned nparms() const { return parms_.size(); }
|
||||
|
||||
PExpr*&parm(unsigned idx)
|
||||
{ assert(idx < parms_.size());
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
PExpr* parm(unsigned idx) const
|
||||
{ assert(idx < parms_.size());
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
|
|
@ -403,7 +391,7 @@ class PForStatement : public Statement {
|
|||
|
||||
public:
|
||||
PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
|
||||
PExpr*n2, PExpr*e2, Statement*st);
|
||||
Statement*step, Statement*body);
|
||||
~PForStatement();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
|
@ -417,8 +405,7 @@ class PForStatement : public Statement {
|
|||
|
||||
PExpr*cond_;
|
||||
|
||||
PExpr* name2_;
|
||||
PExpr* expr2_;
|
||||
Statement*step_;
|
||||
|
||||
Statement*statement_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -221,6 +221,9 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
|||
case NetNet::PINOUT:
|
||||
o << " inout";
|
||||
break;
|
||||
case NetNet::PREF:
|
||||
o <<" ref";
|
||||
break;
|
||||
}
|
||||
|
||||
if (ivl_discipline_t dis = get_discipline())
|
||||
|
|
|
|||
|
|
@ -702,6 +702,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
|||
case NetNet::PINPUT:
|
||||
case NetNet::POUTPUT:
|
||||
case NetNet::PINOUT:
|
||||
case NetNet::PREF:
|
||||
break;
|
||||
|
||||
/* If the name matches, but the signal is not a port,
|
||||
|
|
@ -769,6 +770,9 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
|||
sig = tmp;
|
||||
break;
|
||||
|
||||
case NetNet::PREF:
|
||||
// For the purposes of module ports, treat ref ports
|
||||
// just like inout ports.
|
||||
case NetNet::PINOUT:
|
||||
ps = new NetTran(scope, scope->local_symbol(), sig->vector_width(),
|
||||
swid, lidx);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2012 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
|
||||
|
|
@ -133,9 +133,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
enum_type_t*enum_type)
|
||||
{
|
||||
bool rc_flag;
|
||||
assert(enum_type->range->size() == 2);
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, enum_type->range->front(), -1);
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, enum_type->range->back(), -1);
|
||||
assert(enum_type->range->size() == 1);
|
||||
index_component_t index = enum_type->range->front();
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, index.msb, -1);
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index.lsb, -1);
|
||||
|
||||
long msb = 0;
|
||||
rc_flag = eval_as_long(msb, msb_ex);
|
||||
|
|
|
|||
50
elab_sig.cc
50
elab_sig.cc
|
|
@ -85,6 +85,14 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
|||
PWire*cur = (*wt).second;
|
||||
NetNet*sig = cur->elaborate_sig(des, scope);
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PREF)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": sorry: "
|
||||
<< "Reference ports not supported yet." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. */
|
||||
|
|
@ -468,15 +476,12 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
case PTF_REG:
|
||||
case PTF_REG_S:
|
||||
if (return_type_.range) {
|
||||
ivl_assert(*this, return_type_.range->size() == 2);
|
||||
ivl_assert(*this, return_type_.range->size() == 1);
|
||||
index_component_t index = return_type_.range->front();
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
return_type_.range->at(0), -1,
|
||||
true);
|
||||
NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
return_type_.range->at(1), -1,
|
||||
true);
|
||||
NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
|
||||
assert(le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
|
|
@ -542,17 +547,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
case PTF_ATOM2:
|
||||
case PTF_ATOM2_S:
|
||||
ivl_assert(*this, return_type_.range != 0);
|
||||
long use_wid;
|
||||
{
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1,
|
||||
true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1], -1,
|
||||
true);
|
||||
assert(le);
|
||||
ivl_assert(*this, return_type_.range->size() == 1);
|
||||
index_component_t index = return_type_.range->front();
|
||||
NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
|
||||
ivl_assert(*this, me);
|
||||
NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
|
||||
ivl_assert(*this, le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
|
|
@ -580,6 +582,15 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ret_sig->data_type(IVL_VT_BOOL);
|
||||
break;
|
||||
|
||||
case PTF_STRING:
|
||||
cerr << get_fileline() << ": sorry: String functions are not supported yet" << endl;
|
||||
break;
|
||||
|
||||
case PTF_VOID:
|
||||
// Void functions have no return value, so there is no
|
||||
// signal to create here.
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ports_) {
|
||||
cerr << get_fileline() << ": internal error: I don't know "
|
||||
|
|
@ -797,9 +808,10 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
|
|||
long use_msb = 0;
|
||||
long use_lsb = 0;
|
||||
if (curp->range.get() && ! curp->range->empty()) {
|
||||
ivl_assert(*curp, curp->range->size() == 2);
|
||||
PExpr*msb_pex = curp->range->front();
|
||||
PExpr*lsb_pex = curp->range->back();
|
||||
ivl_assert(*curp, curp->range->size() == 1);
|
||||
index_component_t index = curp->range->front();
|
||||
PExpr*msb_pex = index.msb;
|
||||
PExpr*lsb_pex = index.lsb;
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, msb_pex, -2, true);
|
||||
ivl_assert(*curp, tmp);
|
||||
|
|
|
|||
88
elaborate.cc
88
elaborate.cc
|
|
@ -1069,6 +1069,10 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, 0);
|
||||
break;
|
||||
|
||||
case NetNet::PREF:
|
||||
ivl_assert(*this, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
|
|
@ -1506,6 +1510,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
} else {
|
||||
|
||||
/* Port type must be OUTPUT here. */
|
||||
ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT);
|
||||
|
||||
/* Output from module. Elaborate the port
|
||||
expression as the l-value of a continuous
|
||||
|
|
@ -1640,6 +1645,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
/* This may not be correct! */
|
||||
as_signed = prts[0]->get_signed() && sig->get_signed();
|
||||
break;
|
||||
case NetNet::PREF:
|
||||
ivl_assert(*this, 0);
|
||||
break;
|
||||
default:
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
|
|
@ -1786,6 +1794,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
}
|
||||
break;
|
||||
|
||||
case NetNet::PREF:
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Reference ports not supported yet." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
|
||||
case NetNet::PIMPLICIT:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unexpected IMPLICIT port" << endl;
|
||||
|
|
@ -2811,12 +2825,12 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
unsigned parm_count = nparms();
|
||||
unsigned parm_count = parms_.size();
|
||||
|
||||
/* Catch the special case that the system task has no
|
||||
parameters. The "()" string will be parsed as a single
|
||||
empty parameter, when we really mean no parameters at all. */
|
||||
if ((nparms() == 1) && (parm(0) == 0))
|
||||
if ((parm_count== 1) && (parms_[0] == 0))
|
||||
parm_count = 0;
|
||||
|
||||
svector<NetExpr*>eparms (parm_count);
|
||||
|
|
@ -2824,7 +2838,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
|||
perm_string name = peek_tail_name(path_);
|
||||
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
PExpr*ex = parm(idx);
|
||||
PExpr*ex = parms_[idx];
|
||||
if (ex != 0) {
|
||||
eparms[idx] = elab_sys_task_arg(des, scope, name, idx, ex);
|
||||
} else {
|
||||
|
|
@ -2916,9 +2930,20 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
}
|
||||
assert(def);
|
||||
|
||||
if (nparms() != def->port_count()) {
|
||||
|
||||
unsigned parm_count = parms_.size();
|
||||
|
||||
// Handle special case that the definition has no arguments
|
||||
// but the parser found a simgle nul argument. This is an
|
||||
// argument of the parser allowing for the possibility of
|
||||
// default values for argumets: The parser cannot tell the
|
||||
// difference between "func()" and "func(<default>)".
|
||||
if (def->port_count() == 0 && parm_count == 1 && parms_[0] == 0)
|
||||
parm_count = 0;
|
||||
|
||||
if (parm_count != def->port_count()) {
|
||||
cerr << get_fileline() << ": error: Port count mismatch in call to ``"
|
||||
<< path_ << "''. Got " << nparms()
|
||||
<< path_ << "''. Got " << parm_count
|
||||
<< " ports, expecting " << def->port_count() << " ports." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
|
@ -2928,7 +2953,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
|
||||
/* Handle non-automatic tasks with no parameters specially. There is
|
||||
no need to make a sequential block to hold the generated code. */
|
||||
if ((nparms() == 0) && !task->is_auto()) {
|
||||
if ((parm_count == 0) && !task->is_auto()) {
|
||||
cur = new NetUTask(task);
|
||||
cur->set_line(*this);
|
||||
return cur;
|
||||
|
|
@ -2960,7 +2985,23 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
expression the r-value. We know by definition that the port
|
||||
is a reg type, so this elaboration is pretty obvious. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
|
||||
if (parms_[idx] == 0 && !gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Missing argument " << (idx+1)
|
||||
<< " of call to task." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parms_[idx] == 0) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Implicit arguments (arg " << (idx+1)
|
||||
<< ") not supported." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
NetNet*port = def->port(idx);
|
||||
assert(port->port_type() != NetNet::NOT_A_PORT);
|
||||
|
|
@ -2971,7 +3012,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
unsigned wid = count_lval_width(lv);
|
||||
ivl_variable_type_t lv_type = lv->expr_type();
|
||||
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_[idx]);
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_ [idx]);
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< evt->event()->name() << "' can not be a user "
|
||||
|
|
@ -3001,7 +3042,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
expression that can be a target to a procedural
|
||||
assignment, including a memory word. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
|
||||
NetNet*port = def->port(idx);
|
||||
|
||||
|
|
@ -3780,8 +3821,6 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
const PEIdent*id1 = dynamic_cast<const PEIdent*>(name1_);
|
||||
assert(id1);
|
||||
const PEIdent*id2 = dynamic_cast<const PEIdent*>(name2_);
|
||||
assert(id2);
|
||||
|
||||
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
|
||||
top->set_line(*this);
|
||||
|
|
@ -3826,32 +3865,15 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
body->append(tmp);
|
||||
|
||||
|
||||
/* Elaborate the increment assignment statement at the end of
|
||||
the for loop. This is also a very specific assignment
|
||||
statement. Put this into the "body" block. */
|
||||
sig = des->find_signal(scope, id2->path());
|
||||
if (sig == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to find variable "
|
||||
<< id2->path() << " in for-loop increment expression." << endl;
|
||||
des->errors += 1;
|
||||
return body;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
lv = new NetAssign_(sig);
|
||||
|
||||
/* Make the r-value of the increment assignment, and size it
|
||||
properly. Then use it to build the assignment statement. */
|
||||
etmp = elaborate_rval_expr(des, scope, lv->expr_type(), lv->lwidth(),
|
||||
expr2_);
|
||||
|
||||
/* Now elaborate the for_step statement. I really should do
|
||||
some error checking here to make sure the step statement
|
||||
really does step the variable. */
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: FOR increment assign: "
|
||||
cerr << get_fileline() << ": debug: Elaborate for_step statement "
|
||||
<< sig->name() << " = " << *etmp << endl;
|
||||
}
|
||||
|
||||
NetAssign*step = new NetAssign(lv, etmp);
|
||||
step->set_line(*this);
|
||||
NetProc*step = step_->elaborate(des, scope);
|
||||
|
||||
body->append(step);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
*/
|
||||
extern YYLTYPE yylloc;
|
||||
|
||||
static char* strdupnew(char const *str)
|
||||
char* strdupnew(char const *str)
|
||||
{
|
||||
return str ? strcpy(new char [strlen(str)+1], str) : 0;
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ TU [munpf]
|
|||
">>>=" { return K_RSS_EQ; }
|
||||
"++" { return K_INCR; }
|
||||
"--" {return K_DECR; }
|
||||
|
||||
"'{" { return K_LP; }
|
||||
|
||||
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
|
||||
and ")", but since I know that this is really ( * ), replace it
|
||||
|
|
|
|||
|
|
@ -561,7 +561,7 @@ class NetNet : public NetObj {
|
|||
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
||||
UNRESOLVED_WIRE };
|
||||
|
||||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
||||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
|
||||
|
||||
struct range_t {
|
||||
inline range_t() : msb(0), lsb(0) { }
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
# include "config.h"
|
||||
|
||||
# include "parse_misc.h"
|
||||
# include <cstdarg>
|
||||
# include <cstdio>
|
||||
# include <iostream>
|
||||
|
||||
extern const char*vl_file;
|
||||
|
|
@ -42,10 +44,16 @@ void VLerror(const char*msg)
|
|||
cerr << yylloc.text << ":" << yylloc.first_line << ": " << msg << endl;
|
||||
}
|
||||
|
||||
void VLerror(const YYLTYPE&loc, const char*msg)
|
||||
void VLerror(const YYLTYPE&loc, const char*msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
|
||||
fprintf(stderr, "%s:%d: ", loc.text, loc.first_line);
|
||||
vfprintf(stderr, msg, ap);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
error_count += 1;
|
||||
cerr << loc << ": " << msg << endl;
|
||||
based_size = 0; /* Clear the base information if we have an error. */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ extern YYLTYPE yylloc;
|
|||
*/
|
||||
extern int VLlex();
|
||||
extern void VLerror(const char*msg);
|
||||
extern void VLerror(const YYLTYPE&loc, const char*msg);
|
||||
extern void VLerror(const YYLTYPE&loc, const char*msg, ...) __attribute__((format(printf,2,3)));
|
||||
#define yywarn VLwarn
|
||||
extern void VLwarn(const YYLTYPE&loc, const char*msg);
|
||||
|
||||
|
|
@ -95,4 +95,6 @@ extern verinum*make_unsized_binary(const char*txt);
|
|||
extern verinum*make_unsized_octal(const char*txt);
|
||||
extern verinum*make_unsized_hex(const char*txt);
|
||||
|
||||
extern char* strdupnew(char const *str);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
303
pform.cc
303
pform.cc
|
|
@ -23,6 +23,7 @@
|
|||
# include "pform.h"
|
||||
# include "parse_misc.h"
|
||||
# include "parse_api.h"
|
||||
# include "PClass.h"
|
||||
# include "PEvent.h"
|
||||
# include "PUdp.h"
|
||||
# include "PGenerate.h"
|
||||
|
|
@ -267,12 +268,30 @@ void pform_pop_scope()
|
|||
lexical_scope = lexical_scope->parent_scope();
|
||||
}
|
||||
|
||||
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
|
||||
{
|
||||
PClass*class_scope = new PClass(name, lexical_scope);
|
||||
FILE_NAME(class_scope, loc);
|
||||
|
||||
lexical_scope = class_scope;
|
||||
return class_scope;
|
||||
}
|
||||
|
||||
PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
||||
{
|
||||
perm_string task_name = lex_strings.make(name);
|
||||
|
||||
PTask*task = new PTask(task_name, lexical_scope, is_auto);
|
||||
FILE_NAME(task, loc);
|
||||
|
||||
LexicalScope*scope = lexical_scope;
|
||||
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
|
||||
while (scope && !scopex) {
|
||||
scope = scope->parent_scope();
|
||||
scopex = dynamic_cast<PScopeExtra*> (scope);
|
||||
}
|
||||
assert(scopex);
|
||||
|
||||
if (pform_cur_generate) {
|
||||
// Check if the task is already in the dictionary.
|
||||
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
|
||||
|
|
@ -286,15 +305,15 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
|||
pform_cur_generate->tasks[task->pscope_name()] = task;
|
||||
} else {
|
||||
// Check if the task is already in the dictionary.
|
||||
if (pform_cur_module->tasks.find(task->pscope_name()) !=
|
||||
pform_cur_module->tasks.end()) {
|
||||
if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) {
|
||||
cerr << task->get_fileline() << ": error: duplicate "
|
||||
"definition for task '" << name << "' in '"
|
||||
<< pform_cur_module->mod_name() << "'." << endl;
|
||||
<< scopex->pscope_name() << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
pform_cur_module->tasks[task->pscope_name()] = task;
|
||||
scopex->tasks[task->pscope_name()] = task;
|
||||
}
|
||||
|
||||
lexical_scope = task;
|
||||
|
||||
return task;
|
||||
|
|
@ -307,6 +326,15 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
|
|||
|
||||
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
|
||||
FILE_NAME(func, loc);
|
||||
|
||||
LexicalScope*scope = lexical_scope;
|
||||
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
|
||||
while (scope && !scopex) {
|
||||
scope = scope->parent_scope();
|
||||
scopex = dynamic_cast<PScopeExtra*> (scope);
|
||||
}
|
||||
assert(scopex);
|
||||
|
||||
if (pform_cur_generate) {
|
||||
// Check if the function is already in the dictionary.
|
||||
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
|
||||
|
|
@ -320,14 +348,13 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
|
|||
pform_cur_generate->funcs[func->pscope_name()] = func;
|
||||
} else {
|
||||
// Check if the function is already in the dictionary.
|
||||
if (pform_cur_module->funcs.find(func->pscope_name()) !=
|
||||
pform_cur_module->funcs.end()) {
|
||||
if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) {
|
||||
cerr << func->get_fileline() << ": error: duplicate "
|
||||
"definition for function '" << name << "' in '"
|
||||
<< pform_cur_module->mod_name() << "'." << endl;
|
||||
<< scopex->pscope_name() << "'." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
pform_cur_module->funcs[func->pscope_name()] = func;
|
||||
scopex->funcs[func->pscope_name()] = func;
|
||||
}
|
||||
lexical_scope = func;
|
||||
|
||||
|
|
@ -416,11 +443,16 @@ data_type_t* pform_test_type_identifier(const char*txt)
|
|||
return 0;
|
||||
|
||||
perm_string name = lex_strings.make(txt);
|
||||
map<perm_string,data_type_t*>::iterator cur = lexical_scope->typedefs.find(name);
|
||||
if (cur != lexical_scope->typedefs.end())
|
||||
return cur->second;
|
||||
else
|
||||
return 0;
|
||||
map<perm_string,data_type_t*>::iterator cur;
|
||||
LexicalScope*cur_scope = lexical_scope;
|
||||
do {
|
||||
cur = cur_scope->typedefs.find(name);
|
||||
if (cur != cur_scope->typedefs.end())
|
||||
return cur->second;
|
||||
|
||||
cur_scope = cur_scope->parent_scope();
|
||||
} while (cur_scope);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pform_put_behavior_in_scope(PProcess*pp)
|
||||
|
|
@ -1480,16 +1512,15 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
|||
delete init_expr;
|
||||
}
|
||||
|
||||
static void ranges_from_list(list<PWire::range_t>&rlist, const list<PExpr*>*range)
|
||||
static void ranges_from_list(list<PWire::range_t>&rlist,
|
||||
const list<index_component_t>*range)
|
||||
{
|
||||
// There must be an even number of expressions in the
|
||||
// range. The parser will assure that for us.
|
||||
assert(range->size()%2 == 0);
|
||||
list<PExpr*>::const_iterator rcur = range->begin();
|
||||
while (rcur != range->end()) {
|
||||
// Convert a list of index_component_t to PWire::range_t.
|
||||
for (list<index_component_t>::const_iterator rcur = range->begin()
|
||||
; rcur != range->end() ; ++rcur) {
|
||||
PWire::range_t rng;
|
||||
rng.msb = *rcur; ++rcur;
|
||||
rng.lsb = *rcur; ++rcur;
|
||||
rng.msb = rcur->msb;
|
||||
rng.lsb = rcur->lsb;
|
||||
rlist.push_back(rng);
|
||||
}
|
||||
}
|
||||
|
|
@ -1500,7 +1531,7 @@ static void ranges_from_list(list<PWire::range_t>&rlist, const list<PExpr*>*rang
|
|||
* and the name that I receive only has the tail component.
|
||||
*/
|
||||
static void pform_set_net_range(perm_string name,
|
||||
const list<PExpr*>*range,
|
||||
const list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt)
|
||||
|
|
@ -1527,13 +1558,11 @@ static void pform_set_net_range(perm_string name,
|
|||
cur->set_data_type(dt);
|
||||
}
|
||||
|
||||
void pform_set_net_range(list<perm_string>*names,
|
||||
list<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
static void pform_set_net_range(list<perm_string>*names,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
{
|
||||
assert((range == 0) || (range->size()%2 == 0));
|
||||
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
perm_string txt = *cur;
|
||||
|
|
@ -1601,8 +1630,8 @@ static void pform_makegate(PGBuiltin::Type type,
|
|||
|
||||
perm_string dev_name = lex_strings.make(info.name);
|
||||
PGBuiltin*cur = new PGBuiltin(type, dev_name, info.parms, delay);
|
||||
if (info.range[0])
|
||||
cur->set_range(info.range[0], info.range[1]);
|
||||
if (info.range.msb)
|
||||
cur->set_range(info.range.msb, info.range.lsb);
|
||||
|
||||
// The pform_makegates() that calls me will take care of
|
||||
// deleting the attr pointer, so tell the
|
||||
|
|
@ -1741,7 +1770,7 @@ void pform_make_modgates(perm_string type,
|
|||
if (cur.parms_by_name) {
|
||||
pform_make_modgate(type, cur_name, overrides,
|
||||
cur.parms_by_name,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.range.msb, cur.range.lsb,
|
||||
cur.file, cur.lineno);
|
||||
|
||||
} else if (cur.parms) {
|
||||
|
|
@ -1755,14 +1784,14 @@ void pform_make_modgates(perm_string type,
|
|||
}
|
||||
pform_make_modgate(type, cur_name, overrides,
|
||||
cur.parms,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.range.msb, cur.range.lsb,
|
||||
cur.file, cur.lineno);
|
||||
|
||||
} else {
|
||||
list<PExpr*>*wires = new list<PExpr*>;
|
||||
pform_make_modgate(type, cur_name, overrides,
|
||||
wires,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.range.msb, cur.range.lsb,
|
||||
cur.file, cur.lineno);
|
||||
}
|
||||
}
|
||||
|
|
@ -1835,8 +1864,8 @@ void pform_make_pgassign_list(list<PExpr*>*alist,
|
|||
void pform_make_reginit(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
if (! pform_at_module_level()) {
|
||||
VLerror(li, "variable declaration assignments are only "
|
||||
if (! pform_at_module_level() && !gn_system_verilog()) {
|
||||
VLerror(li, "error: variable declaration assignments are only "
|
||||
"allowed at the module level.");
|
||||
delete expr;
|
||||
return;
|
||||
|
|
@ -1875,7 +1904,7 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
NetNet::Type type,
|
||||
ivl_variable_type_t data_type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<named_pexpr_t>*attr)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
|
|
@ -2009,7 +2038,7 @@ void pform_makewire(const vlltype&li, perm_string name,
|
|||
* pform_makewire above.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<perm_string>*names,
|
||||
NetNet::Type type,
|
||||
|
|
@ -2036,7 +2065,7 @@ void pform_makewire(const vlltype&li,
|
|||
* This form makes nets with delays and continuous assignments.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*delay,
|
||||
str_pair_t str,
|
||||
|
|
@ -2071,39 +2100,6 @@ void pform_makewire(const vlltype&li,
|
|||
}
|
||||
}
|
||||
|
||||
void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
|
||||
FILE_NAME(cur, file, lineno);
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
}
|
||||
|
||||
switch (cur->get_port_type()) {
|
||||
case NetNet::PIMPLICIT:
|
||||
if (! cur->set_port_type(pt))
|
||||
VLerror("error setting port direction.");
|
||||
break;
|
||||
|
||||
case NetNet::NOT_A_PORT:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << name << " is not in the port list."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << name << " already has a port declaration."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called by the parser to create task ports. The
|
||||
* resulting wire (which should be a register) is put into a list to
|
||||
|
|
@ -2143,15 +2139,15 @@ void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
|||
* constraints as those of tasks, so this works fine. Functions have
|
||||
* no output or inout ports.
|
||||
*/
|
||||
svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<perm_string>*names,
|
||||
const char* file,
|
||||
unsigned lineno,
|
||||
bool isint)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
assert(names);
|
||||
svector<PWire*>*res = new svector<PWire*>(0);
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
|
|
@ -2166,7 +2162,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
|||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
|
||||
FILE_NAME(curw, file, lineno);
|
||||
FILE_NAME(curw, loc);
|
||||
pform_put_wire_in_scope(name, curw);
|
||||
}
|
||||
|
||||
|
|
@ -2191,6 +2187,71 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
|||
return res;
|
||||
}
|
||||
|
||||
svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*vtype,
|
||||
list<perm_string>*names)
|
||||
{
|
||||
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
|
||||
list<index_component_t>*range_tmp = make_range_from_width(atype->type_code);
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_BOOL,
|
||||
atype->signed_flag,
|
||||
range_tmp, names);
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, vec_type->base_type,
|
||||
vec_type->signed_flag,
|
||||
copy_range(vec_type->pdims.get()),
|
||||
names);
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_REAL,
|
||||
true, 0, names);
|
||||
}
|
||||
|
||||
VLerror(loc, "sorry: Given type not supported here.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The parser calls this in the rule that matches increment/decrement
|
||||
* statements. The rule that does the matching creates a PEUnary with
|
||||
* all the information we need, but here we convert that expression to
|
||||
* a compressed assignment statement.
|
||||
*/
|
||||
PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*exp)
|
||||
{
|
||||
PEUnary*expu = dynamic_cast<PEUnary*> (exp);
|
||||
ivl_assert(*exp, expu != 0);
|
||||
|
||||
char use_op = 0;
|
||||
switch (expu->get_op()) {
|
||||
case 'i':
|
||||
case 'I':
|
||||
use_op = '+';
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
use_op = '-';
|
||||
break;
|
||||
default:
|
||||
ivl_assert(*exp, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
PExpr*lval = expu->get_expr();
|
||||
PExpr*rval = new PENumber(new verinum((uint64_t)1, 1));
|
||||
FILE_NAME(rval, loc);
|
||||
|
||||
PAssign*tmp = new PAssign(lval, use_op, rval);
|
||||
FILE_NAME(tmp, loc);
|
||||
|
||||
delete exp;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void pform_set_attrib(perm_string name, perm_string key, char*value)
|
||||
{
|
||||
if (PWire*cur = lexical_scope->wires_find(name)) {
|
||||
|
|
@ -2259,7 +2320,7 @@ LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
|
|||
|
||||
void pform_set_parameter(const struct vlltype&loc,
|
||||
perm_string name, ivl_variable_type_t type,
|
||||
bool signed_flag, list<PExpr*>*range, PExpr*expr,
|
||||
bool signed_flag, list<index_component_t>*range, PExpr*expr,
|
||||
LexicalScope::range_t*value_range)
|
||||
{
|
||||
LexicalScope*scope = lexical_scope;
|
||||
|
|
@ -2294,11 +2355,12 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
|
||||
parm.type = type;
|
||||
if (range) {
|
||||
assert(range->size() == 2);
|
||||
assert(range->front());
|
||||
assert(range->back());
|
||||
parm.msb = range->front();
|
||||
parm.lsb = range->back();
|
||||
assert(range->size() == 1);
|
||||
index_component_t index = range->front();
|
||||
assert(index.msb);
|
||||
assert(index.lsb);
|
||||
parm.msb = index.msb;
|
||||
parm.lsb = index.lsb;
|
||||
} else {
|
||||
parm.msb = 0;
|
||||
parm.lsb = 0;
|
||||
|
|
@ -2312,7 +2374,7 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
|
||||
void pform_set_localparam(const struct vlltype&loc,
|
||||
perm_string name, ivl_variable_type_t type,
|
||||
bool signed_flag, list<PExpr*>*range, PExpr*expr)
|
||||
bool signed_flag, list<index_component_t>*range, PExpr*expr)
|
||||
{
|
||||
LexicalScope*scope = lexical_scope;
|
||||
|
||||
|
|
@ -2342,11 +2404,12 @@ void pform_set_localparam(const struct vlltype&loc,
|
|||
|
||||
parm.type = type;
|
||||
if (range) {
|
||||
assert(range->size() == 2);
|
||||
assert(range->front());
|
||||
assert(range->back());
|
||||
parm.msb = range->front();
|
||||
parm.lsb = range->back();
|
||||
assert(range->size() == 1);
|
||||
index_component_t index = range->front();
|
||||
assert(index.msb);
|
||||
assert(index.lsb);
|
||||
parm.msb = index.msb;
|
||||
parm.lsb = index.lsb;
|
||||
} else {
|
||||
parm.msb = 0;
|
||||
parm.lsb = 0;
|
||||
|
|
@ -2443,12 +2506,48 @@ extern void pform_module_specify_path(PSpecPath*obj)
|
|||
pform_cur_module->specify_paths.push_back(obj);
|
||||
}
|
||||
|
||||
|
||||
static void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
|
||||
FILE_NAME(cur, file, lineno);
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
}
|
||||
|
||||
switch (cur->get_port_type()) {
|
||||
case NetNet::PIMPLICIT:
|
||||
if (! cur->set_port_type(pt))
|
||||
VLerror("error setting port direction.");
|
||||
break;
|
||||
|
||||
case NetNet::NOT_A_PORT:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << name << " is not in the port list."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << name << " already has a port declaration."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void pform_set_port_type(const struct vlltype&li,
|
||||
list<perm_string>*names,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
NetNet::PortType pt)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
perm_string txt = *cur;
|
||||
|
|
@ -2539,6 +2638,11 @@ void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>
|
|||
*/
|
||||
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names)
|
||||
{
|
||||
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
|
||||
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names);
|
||||
return;
|
||||
}
|
||||
|
||||
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
|
||||
pform_set_struct_type(struct_type, names);
|
||||
return;
|
||||
|
|
@ -2549,6 +2653,23 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
|
|||
return;
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
|
||||
pform_set_net_range(names, vec_type->pdims.get(),
|
||||
vec_type->signed_flag,
|
||||
vec_type->base_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
|
||||
pform_set_net_range(names, 0, true, IVL_VT_REAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/*class_type_t*class_type =*/ dynamic_cast<class_type_t*> (data_type)) {
|
||||
VLerror(li, "sorry: Class types not supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
|
@ -2562,7 +2683,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
|||
cur->set_signed(enum_type->signed_flag);
|
||||
|
||||
assert(enum_type->range.get() != 0);
|
||||
assert(enum_type->range->size() == 2);
|
||||
assert(enum_type->range->size() == 1);
|
||||
list<PWire::range_t>rlist;
|
||||
ranges_from_list(rlist, enum_type->range.get());
|
||||
cur->set_range(rlist, SR_NET);
|
||||
|
|
@ -2576,7 +2697,7 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
|
|||
assert(enum_type->base_type==IVL_VT_LOGIC || enum_type->base_type==IVL_VT_BOOL);
|
||||
|
||||
assert(enum_type->range.get() != 0);
|
||||
assert(enum_type->range->size() == 2);
|
||||
assert(enum_type->range->size() == 1);
|
||||
|
||||
// Add the file and line information to the enumeration type.
|
||||
FILE_NAME(&(enum_type->li), li);
|
||||
|
|
|
|||
55
pform.h
55
pform.h
|
|
@ -58,6 +58,7 @@
|
|||
class PGate;
|
||||
class PExpr;
|
||||
class PSpecPath;
|
||||
class PClass;
|
||||
struct vlltype;
|
||||
|
||||
/*
|
||||
|
|
@ -101,22 +102,23 @@ struct net_decl_assign_t {
|
|||
|
||||
/* The lgate is gate instantiation information. */
|
||||
struct lgate {
|
||||
lgate(int =0)
|
||||
inline lgate(int =0)
|
||||
: parms(0), parms_by_name(0), file(NULL), lineno(0)
|
||||
{ range[0] = 0;
|
||||
range[1] = 0;
|
||||
}
|
||||
{ }
|
||||
|
||||
string name;
|
||||
list<PExpr*>*parms;
|
||||
list<named_pexpr_t>*parms_by_name;
|
||||
|
||||
PExpr*range[2];
|
||||
index_component_t range;
|
||||
|
||||
const char* file;
|
||||
unsigned lineno;
|
||||
};
|
||||
|
||||
extern std::list<index_component_t>* make_range_from_width(uint64_t wid);
|
||||
extern std::list<index_component_t>* copy_range(std::list<index_component_t>* orig);
|
||||
|
||||
/* Use this function to transform the parted form of the attribute
|
||||
list to the attribute map that is used later. */
|
||||
extern void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
|
||||
|
|
@ -158,7 +160,7 @@ extern void pform_module_define_port(const struct vlltype&li,
|
|||
NetNet::Type type,
|
||||
ivl_variable_type_t data_type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<named_pexpr_t>*attr);
|
||||
|
||||
extern Module::port_t* pform_module_port_reference(perm_string name,
|
||||
|
|
@ -167,6 +169,10 @@ extern Module::port_t* pform_module_port_reference(perm_string name,
|
|||
extern void pform_endmodule(const char*, bool inside_celldefine,
|
||||
Module::UCDriveType uc_drive_def);
|
||||
|
||||
extern void pform_start_class_declaration(const struct vlltype&loc,
|
||||
class_type_t*type);
|
||||
extern void pform_end_class_declaration(void);
|
||||
|
||||
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||
svector<PWire*>*decl, list<string>*table,
|
||||
Statement*init,
|
||||
|
|
@ -186,6 +192,7 @@ extern void pform_make_udp(perm_string name,
|
|||
*/
|
||||
extern void pform_pop_scope();
|
||||
|
||||
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
|
||||
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||
bool is_auto);
|
||||
extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name,
|
||||
|
|
@ -238,7 +245,7 @@ extern void pform_makewire(const struct vlltype&li, perm_string name,
|
|||
|
||||
/* This form handles simple declarations */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<perm_string>*names,
|
||||
NetNet::Type type,
|
||||
|
|
@ -255,7 +262,7 @@ extern void pform_makewire(const struct vlltype&li,
|
|||
|
||||
/* This form handles assignment declarations. */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*delay,
|
||||
str_pair_t str,
|
||||
|
|
@ -278,16 +285,11 @@ extern void pform_make_reginit(const struct vlltype&li,
|
|||
it. The second form takes a single name. */
|
||||
extern void pform_set_port_type(const struct vlltype&li,
|
||||
list<perm_string>*names,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
bool signed_flag,
|
||||
NetNet::PortType);
|
||||
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno);
|
||||
|
||||
extern void pform_set_net_range(list<perm_string>*names,
|
||||
list<PExpr*>*,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t);
|
||||
|
||||
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_integer(list<perm_string>*names);
|
||||
extern void pform_set_reg_time(list<perm_string>*names);
|
||||
|
|
@ -317,13 +319,13 @@ extern void pform_set_parameter(const struct vlltype&loc,
|
|||
perm_string name,
|
||||
ivl_variable_type_t type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
PExpr*expr, LexicalScope::range_t*value_range);
|
||||
extern void pform_set_localparam(const struct vlltype&loc,
|
||||
perm_string name,
|
||||
ivl_variable_type_t type,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
PExpr*expr);
|
||||
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
|
||||
|
||||
|
|
@ -383,15 +385,26 @@ extern void pform_make_pgassign_list(list<PExpr*>*alist,
|
|||
|
||||
/* Given a port type and a list of names, make a list of wires that
|
||||
can be used as task port information. */
|
||||
extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<index_component_t>*range,
|
||||
list<perm_string>*names,
|
||||
const char* file,
|
||||
unsigned lineno,
|
||||
bool isint = false);
|
||||
|
||||
extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*vtype,
|
||||
list<perm_string>*names);
|
||||
|
||||
/*
|
||||
* The parser uses this function to convert a unary
|
||||
* increment/decrement expression to the equivilent compressed
|
||||
* assignment statement.
|
||||
*/
|
||||
extern PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc,
|
||||
PExpr*exp);
|
||||
|
||||
/*
|
||||
* These are functions that the outside-the-parser code uses the do
|
||||
|
|
|
|||
|
|
@ -336,6 +336,9 @@ void PWire::dump(ostream&out, unsigned ind) const
|
|||
case NetNet::PINOUT:
|
||||
out << " inout";
|
||||
break;
|
||||
case NetNet::PREF:
|
||||
out << " ref";
|
||||
break;
|
||||
case NetNet::NOT_A_PORT:
|
||||
break;
|
||||
}
|
||||
|
|
@ -574,7 +577,10 @@ void PAssign::dump(ostream&out, unsigned ind) const
|
|||
if (delay_) out << "#" << *delay_ << " ";
|
||||
if (count_) out << "repeat(" << *count_ << ") ";
|
||||
if (event_) out << *event_ << " ";
|
||||
out << *rval() << ";" << " /* " << get_fileline() << " */" << endl;
|
||||
PExpr*rexpr = rval();
|
||||
if (rexpr) out << *rval() << ";";
|
||||
else out << "<no rval>;";
|
||||
out << " /* " << get_fileline() << " */" << endl;
|
||||
}
|
||||
|
||||
void PAssignNB::dump(ostream&out, unsigned ind) const
|
||||
|
|
@ -774,8 +780,8 @@ void PForever::dump(ostream&out, unsigned ind) const
|
|||
void PForStatement::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "for (" << *name1_ << " = " << *expr1_
|
||||
<< "; " << *cond_ << "; " << *name2_ << " = " << *expr2_ <<
|
||||
")" << endl;
|
||||
<< "; " << *cond_ << "; <for_step>)" << endl;
|
||||
step_->dump(out, ind+6);
|
||||
statement_->dump(out, ind+3);
|
||||
}
|
||||
|
||||
|
|
@ -809,7 +815,13 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
|||
out << "int unsigned ";
|
||||
break;
|
||||
case PTF_ATOM2_S:
|
||||
cout << "int signed ";
|
||||
out << "int signed ";
|
||||
break;
|
||||
case PTF_STRING:
|
||||
out << "string ";
|
||||
break;
|
||||
case PTF_VOID:
|
||||
out << "void ";
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -860,6 +872,10 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
out << pscope_name() << ";" << endl;
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
if ((*ports_)[idx] == 0) {
|
||||
out << setw(ind) << "" << "ERROR PORT" << endl;
|
||||
continue;
|
||||
}
|
||||
out << setw(ind) << "";
|
||||
switch ((*ports_)[idx]->get_port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
|
|
@ -871,6 +887,12 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
case NetNet::PINOUT:
|
||||
out << "inout ";
|
||||
break;
|
||||
case NetNet::PIMPLICIT:
|
||||
out << "PIMPLICIT";
|
||||
break;
|
||||
case NetNet::NOT_A_PORT:
|
||||
out << "NOT_A_PORT";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2012 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "pform.h"
|
||||
# include "PClass.h"
|
||||
|
||||
static PClass*pform_cur_class = 0;
|
||||
|
||||
void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type)
|
||||
{
|
||||
PClass*class_scope = pform_push_class_scope(loc, type->name);
|
||||
assert(pform_cur_class == 0);
|
||||
pform_cur_class = class_scope;
|
||||
}
|
||||
|
||||
void pform_end_class_declaration(void)
|
||||
{
|
||||
assert(pform_cur_class);
|
||||
pform_cur_class = 0;
|
||||
pform_pop_scope();
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __pform_types_H
|
||||
#define __pform_types_H
|
||||
/*
|
||||
* Copyright (c) 2007-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2007-2012 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
|
||||
|
|
@ -84,14 +84,14 @@ struct data_type_t : public LineInfo {
|
|||
struct enum_type_t : public data_type_t {
|
||||
ivl_variable_type_t base_type;
|
||||
bool signed_flag;
|
||||
std::auto_ptr< list<PExpr*> > range;
|
||||
std::auto_ptr< list<index_component_t> > range;
|
||||
std::auto_ptr< list<named_pexpr_t> > names;
|
||||
LineInfo li;
|
||||
};
|
||||
|
||||
struct struct_member_t : public LineInfo {
|
||||
ivl_variable_type_t type;
|
||||
std::auto_ptr< list<PExpr*> > range;
|
||||
std::auto_ptr< list<index_component_t> > range;
|
||||
std::auto_ptr< list<decl_assignment_t*> > names;
|
||||
};
|
||||
|
||||
|
|
@ -100,6 +100,34 @@ struct struct_type_t : public data_type_t {
|
|||
std::auto_ptr< list<struct_member_t*> > members;
|
||||
};
|
||||
|
||||
struct atom2_type_t : public data_type_t {
|
||||
inline explicit atom2_type_t(int tc, bool flag)
|
||||
: type_code(tc), signed_flag(flag) { }
|
||||
int type_code;
|
||||
bool signed_flag;
|
||||
};
|
||||
|
||||
struct vector_type_t : public data_type_t {
|
||||
inline explicit vector_type_t(ivl_variable_type_t bt, bool sf,
|
||||
std::list<index_component_t>*pd)
|
||||
: base_type(bt), signed_flag(sf), pdims(pd) { }
|
||||
ivl_variable_type_t base_type;
|
||||
bool signed_flag;
|
||||
std::auto_ptr< list<index_component_t> > pdims;
|
||||
};
|
||||
|
||||
struct real_type_t : public data_type_t {
|
||||
inline explicit real_type_t(int tc) : type_code(tc) { }
|
||||
int type_code;
|
||||
};
|
||||
|
||||
struct class_type_t : public data_type_t {
|
||||
inline explicit class_type_t(perm_string n)
|
||||
: name(n) { }
|
||||
|
||||
perm_string name;
|
||||
};
|
||||
|
||||
/*
|
||||
* The pform_name_t is the general form for a hierarchical
|
||||
* identifier. It is an ordered list of name components. Each name
|
||||
|
|
|
|||
Loading…
Reference in New Issue