Merge branch 'master' into verilog-ams
This commit is contained in:
commit
e98f29e96f
69
PExpr.cc
69
PExpr.cc
|
|
@ -24,6 +24,7 @@
|
|||
# include "compiler.h"
|
||||
# include "PExpr.h"
|
||||
# include "Module.h"
|
||||
# include "netmisc.h"
|
||||
# include <typeinfo>
|
||||
|
||||
PExpr::PExpr()
|
||||
|
|
@ -35,6 +36,11 @@ PExpr::~PExpr()
|
|||
{
|
||||
}
|
||||
|
||||
bool PExpr::has_aa_term(Design*, NetScope*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PExpr::is_the_same(const PExpr*that) const
|
||||
{
|
||||
return typeid(this) == typeid(that);
|
||||
|
|
@ -64,6 +70,12 @@ PEBinary::~PEBinary()
|
|||
{
|
||||
}
|
||||
|
||||
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(left_ && right_);
|
||||
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
|
|
@ -130,6 +142,15 @@ PECallFunction::~PECallFunction()
|
|||
{
|
||||
}
|
||||
|
||||
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
|
||||
: parms_(p), repeat_(r)
|
||||
{
|
||||
|
|
@ -140,6 +161,18 @@ PEConcat::~PEConcat()
|
|||
delete repeat_;
|
||||
}
|
||||
|
||||
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
if (repeat_)
|
||||
flag = repeat_->has_aa_term(des, scope) || flag;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
|
||||
: type_(t), expr_(e)
|
||||
{
|
||||
|
|
@ -154,6 +187,12 @@ PEEvent::edge_t PEEvent::type() const
|
|||
return type_;
|
||||
}
|
||||
|
||||
bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PExpr* PEEvent::expr() const
|
||||
{
|
||||
return expr_;
|
||||
|
|
@ -188,6 +227,22 @@ PEIdent::~PEIdent()
|
|||
{
|
||||
}
|
||||
|
||||
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet* net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
|
||||
if (scope)
|
||||
return scope->is_auto();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
PENumber::PENumber(verinum*vp)
|
||||
: value_(vp)
|
||||
{
|
||||
|
|
@ -237,6 +292,14 @@ PETernary::~PETernary()
|
|||
{
|
||||
}
|
||||
|
||||
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_ && tru_ && fal_);
|
||||
return expr_->has_aa_term(des, scope)
|
||||
|| tru_->has_aa_term(des, scope)
|
||||
|| fal_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PEUnary::PEUnary(char op, PExpr*ex)
|
||||
: op_(op), expr_(ex)
|
||||
{
|
||||
|
|
@ -245,3 +308,9 @@ PEUnary::PEUnary(char op, PExpr*ex)
|
|||
PEUnary::~PEUnary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
}
|
||||
|
|
|
|||
22
PExpr.h
22
PExpr.h
|
|
@ -46,6 +46,10 @@ class PExpr : public LineInfo {
|
|||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// This method tests whether the expression contains any
|
||||
// references to automatically allocated variables.
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method tests the width that the expression wants to
|
||||
// be. It is used by elaboration of assignments to figure out
|
||||
// the width of the expression.
|
||||
|
|
@ -156,6 +160,8 @@ class PEConcat : public PExpr {
|
|||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -200,6 +206,8 @@ class PEEvent : public PExpr {
|
|||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
edge_t type_;
|
||||
PExpr *expr_;
|
||||
|
|
@ -247,6 +255,9 @@ class PEIdent : public PExpr {
|
|||
void append_name(perm_string);
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -420,6 +431,8 @@ class PEUnary : public PExpr {
|
|||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -448,6 +461,8 @@ class PEBinary : public PExpr {
|
|||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -541,6 +556,9 @@ class PETernary : public PExpr {
|
|||
~PETernary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -579,7 +597,9 @@ class PECallFunction : public PExpr {
|
|||
|
||||
virtual void dump(ostream &) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class PGenerate : public LineInfo, public LexicalScope {
|
|||
PScope*lexical_scope;
|
||||
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
|
||||
GS_CASE, GS_CASE_ITEM};
|
||||
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
|
||||
scheme_t scheme_type;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
|
|
@ -102,6 +102,7 @@ class PGenerate : public LineInfo, public LexicalScope {
|
|||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
|
||||
bool generate_scope_case_(Design*des, NetScope*container);
|
||||
bool generate_scope_nblock_(Design*des, NetScope*container);
|
||||
|
||||
// Elaborate_scope within a generated scope.
|
||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||
|
|
|
|||
|
|
@ -228,6 +228,15 @@ void PEventStatement::set_statement(Statement*st)
|
|||
statement_ = st;
|
||||
}
|
||||
|
||||
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||
flag = expr_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PForce::PForce(PExpr*l, PExpr*r)
|
||||
: lval_(l), expr_(r)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -347,6 +347,8 @@ class PEventStatement : public Statement {
|
|||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
bool has_aa_term(Design*des, NetScope*scope);
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
|
||||
|
|
|
|||
46
elab_expr.cc
46
elab_expr.cc
|
|
@ -786,20 +786,26 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
left_width = left_->test_width(des, scope, 0, 0, left_type, unsized_flag);
|
||||
|
||||
/* Width of operands is self-determined. */
|
||||
int use_wid = left_width;
|
||||
if (right_width > left_width)
|
||||
use_wid = right_width;
|
||||
|
||||
int use_wid_l = left_width;
|
||||
if (type_is_vectorable(left_type) && (right_width > left_width))
|
||||
use_wid_l = right_width;
|
||||
|
||||
int use_wid_r = right_width;
|
||||
if (type_is_vectorable(right_type) && (left_width > right_width))
|
||||
use_wid_r = left_width;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Comparison expression operands are "
|
||||
<< left_width << " bits and "
|
||||
<< right_width << " bits. Resorting to "
|
||||
<< use_wid << " bits." << endl;
|
||||
<< use_wid_l << " bits and "
|
||||
<< use_wid_r << " bits." << endl;
|
||||
}
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, use_wid, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, use_wid, false);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, use_wid_l, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, use_wid_r, false);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -812,12 +818,12 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
// pad the width here. This matters because if the arguments
|
||||
// are signed, then this padding will do sign extension.
|
||||
if (type_is_vectorable(lp->expr_type()))
|
||||
lp = pad_to_width(lp, use_wid);
|
||||
lp = pad_to_width(lp, use_wid_l);
|
||||
if (type_is_vectorable(rp->expr_type()))
|
||||
rp = pad_to_width(rp, use_wid);
|
||||
rp = pad_to_width(rp, use_wid_r);
|
||||
|
||||
eval_expr(lp, use_wid);
|
||||
eval_expr(rp, use_wid);
|
||||
eval_expr(lp, use_wid_l);
|
||||
eval_expr(rp, use_wid_r);
|
||||
|
||||
// Handle some operand-specific special cases...
|
||||
switch (op_) {
|
||||
|
|
@ -1413,12 +1419,26 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope,
|
|||
{
|
||||
expr_type_ = IVL_VT_LOGIC;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: CONCAT MISSING TEST_WIDTH!" << endl;
|
||||
unsigned count_width = 0;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
count_width += parms_[idx]->test_width(des, scope, 0, 0, expr_type__, unsized_flag);
|
||||
|
||||
if (repeat_) {
|
||||
// The repeat expression is self-determined and its own type.
|
||||
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
|
||||
bool tmp_flag = false;
|
||||
repeat_->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
|
||||
|
||||
count_width = 0;
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "CONCAT MISSING TEST_WIDTH WHEN REPEAT IS PRESENT!"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
expr_type__ = expr_type_;
|
||||
unsized_flag = false;
|
||||
return 0;
|
||||
return count_width;
|
||||
}
|
||||
|
||||
// Keep track of the concatenation/repeat depth.
|
||||
|
|
|
|||
|
|
@ -461,7 +461,9 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
|
|||
|
||||
case GS_CASE:
|
||||
return generate_scope_case_(des, container);
|
||||
return true;
|
||||
|
||||
case GS_NBLOCK:
|
||||
return generate_scope_nblock_(des, container);
|
||||
|
||||
case GS_CASE_ITEM:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
|
|
@ -718,6 +720,29 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
|
||||
{
|
||||
hname_t use_name (scope_name);
|
||||
if (container->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: block/scope name "
|
||||
<< scope_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate named block "
|
||||
<< ": Generate scope=" << use_name << endl;
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
|
||||
elaborate_subscope_(des, scope);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
{
|
||||
// Scan the generated scope for nested generate schemes,
|
||||
|
|
@ -1123,8 +1148,9 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
|||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
my_scope->set_line(get_file(), get_lineno());
|
||||
my_scope->is_auto(scope->is_auto());
|
||||
|
||||
// Scan the parameters in the module, and create stub parameter
|
||||
// Scan the parameters in the scope, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(my_scope, parameters);
|
||||
|
|
|
|||
116
elaborate.cc
116
elaborate.cc
|
|
@ -969,7 +969,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
|
||||
// This is the array of pin expressions, shuffled to match the
|
||||
// order of the declaration. If the source instantiation uses
|
||||
// bind by order, this is the same as the source list.Otherwise,
|
||||
// bind by order, this is the same as the source list. Otherwise,
|
||||
// the source list is rearranged by name binding into this list.
|
||||
svector<PExpr*>pins (rmod->port_count());
|
||||
|
||||
|
|
@ -1051,10 +1051,13 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
// later.
|
||||
|
||||
NetScope::scope_vec_t&instance = scope->instance_arrays[get_name()];
|
||||
if (debug_elaborate) cerr << get_fileline() << ": debug: start "
|
||||
"recursive elaboration of " << instance.size() << " instance(s) of " <<
|
||||
get_name() << "..." << endl;
|
||||
for (unsigned inst = 0 ; inst < instance.size() ; inst += 1) {
|
||||
rmod->elaborate(des, instance[inst]);
|
||||
}
|
||||
|
||||
if (debug_elaborate) cerr << get_fileline() << ": debug: ...done." << endl;
|
||||
|
||||
|
||||
// Now connect the ports of the newly elaborated designs to
|
||||
|
|
@ -1110,7 +1113,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: " << get_name()
|
||||
<< ": Port " << idx << " has " << prts.size()
|
||||
<< ": Port " << (idx+1) << " has " << prts.size()
|
||||
<< " sub-ports." << endl;
|
||||
}
|
||||
|
||||
|
|
@ -1427,7 +1430,7 @@ v NOTE that this also handles the case that the
|
|||
<< " bits across all "
|
||||
<< prts_vector_width/instance.size()
|
||||
<< " input sub-ports of port "
|
||||
<< idx << "." << endl;
|
||||
<< (idx+1) << "." << endl;
|
||||
}
|
||||
|
||||
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1) {
|
||||
|
|
@ -1440,11 +1443,23 @@ v NOTE that this also handles the case that the
|
|||
spin += sp->vector_width();
|
||||
}
|
||||
break;
|
||||
|
||||
case NetNet::PINOUT:
|
||||
cerr << get_fileline() << ": XXXX: "
|
||||
<< "Forgot how to bind inout ports!" << endl;
|
||||
des->errors += 1;
|
||||
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1) {
|
||||
NetNet*sp = prts[prts.size()-ldx-1];
|
||||
NetTran*ttmp = new NetTran(scope,
|
||||
scope->local_symbol(),
|
||||
sig->vector_width(),
|
||||
sp->vector_width(),
|
||||
spin);
|
||||
des->add_node(ttmp);
|
||||
ttmp->set_line(*this);
|
||||
connect(ttmp->pin(0), sig->pin(0));
|
||||
connect(ttmp->pin(1), sp->pin(0));
|
||||
spin += sp->vector_width();
|
||||
}
|
||||
break;
|
||||
|
||||
case NetNet::PIMPLICIT:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unexpected IMPLICIT port" << endl;
|
||||
|
|
@ -2012,17 +2027,26 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (scope->is_auto() && lval()->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using non-blocking "
|
||||
"assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Elaborate the l-value. */
|
||||
NetAssign_*lv = elaborate_lval(des, scope);
|
||||
if (lv == 0) return 0;
|
||||
|
||||
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
|
||||
if (rv == 0) return 0;
|
||||
|
||||
/* Handle the (common) case that the r-value is a vector. This
|
||||
includes just about everything but reals. In this case, we
|
||||
need to pad the r-value to match the width of the l-value.
|
||||
|
||||
If in this case the l-val is a variable (i.e. real) then
|
||||
If in this case the l-val is a variable (i.e., real) then
|
||||
the width to pad to will be 0, so this code is harmless. */
|
||||
if (rv->expr_type() == IVL_VT_REAL) {
|
||||
|
||||
|
|
@ -2042,6 +2066,15 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
NetEvWait*event = 0;
|
||||
if (count_ != 0 || event_ != 0) {
|
||||
if (count_ != 0) {
|
||||
if (scope->is_auto() && count_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically "
|
||||
"allocated variables may not be referenced "
|
||||
"in intra-assignment event controls of "
|
||||
"non-blocking assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(event_ != 0);
|
||||
count = elab_and_eval(des, scope, count_, -1);
|
||||
if (count == 0) {
|
||||
|
|
@ -2052,6 +2085,15 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
}
|
||||
}
|
||||
|
||||
if (scope->is_auto() && event_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically "
|
||||
"allocated variables may not be referenced "
|
||||
"in intra-assignment event controls of "
|
||||
"non-blocking assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetProc*st = event_->elaborate(des, scope);
|
||||
if (st == 0) {
|
||||
cerr << get_fileline() << ": unable to elaborate "
|
||||
|
|
@ -2586,6 +2628,22 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
|||
NetCAssign*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"continuous assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scope->is_auto() && expr_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be referenced in procedural "
|
||||
"continuous assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
@ -2617,6 +2675,14 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"continuous assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
@ -2875,6 +2941,16 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
|||
the sub-expression as a net and decide how to handle
|
||||
the edge. */
|
||||
|
||||
if (scope->is_auto()) {
|
||||
if (! dynamic_cast<PEIdent*>(expr_[idx]->expr())) {
|
||||
cerr << get_fileline() << ": sorry, complex event "
|
||||
"expressions are not yet supported in "
|
||||
"automatic tasks." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool save_flag = error_implicit;
|
||||
error_implicit = true;
|
||||
NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), 0);
|
||||
|
|
@ -3150,6 +3226,22 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
|||
NetForce*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scope->is_auto() && expr_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be referenced in procedural force "
|
||||
"statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
@ -3355,6 +3447,14 @@ NetProc* PRelease::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
|
|||
17
eval_tree.cc
17
eval_tree.cc
|
|
@ -133,7 +133,18 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
|||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
ivl_assert(*this, se->expr_width() == this->expr_width());
|
||||
if (lval.len() < expr_width())
|
||||
lval = pad_to_width(lval, expr_width());
|
||||
if (rval.len() < expr_width())
|
||||
rval = pad_to_width(rval, expr_width());
|
||||
|
||||
if (se->expr_width() > this->expr_width()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "expr_width()=" << expr_width()
|
||||
<< ", sub expr_width()=" << se->expr_width()
|
||||
<< ", sub expression=" << *se << endl;
|
||||
}
|
||||
ivl_assert(*this, se->expr_width() <= this->expr_width());
|
||||
|
||||
verinum val;
|
||||
if (op_ == se->op_) {
|
||||
|
|
@ -146,7 +157,9 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
|||
val = rval - lval;
|
||||
}
|
||||
|
||||
val = pad_to_width(val, expr_width());
|
||||
// Since we padded the operands above to be the minimum
|
||||
// width, the val should also be at least expr_width().
|
||||
ivl_assert(*this, val.len() >= expr_width());
|
||||
if (val.len() > expr_width()) {
|
||||
verinum tmp (val, expr_width());
|
||||
tmp.has_sign(val.has_sign());
|
||||
|
|
|
|||
10
parse.y
10
parse.y
|
|
@ -2235,6 +2235,16 @@ module_item
|
|||
cerr << @2 << ": warning: Anachronistic use of begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
}
|
||||
| K_generate K_begin ':' IDENTIFIER {
|
||||
pform_start_generate_nblock(@1, $4);
|
||||
} module_item_list_opt K_end K_endgenerate
|
||||
{ /* Detect and warn about anachronistic named begin/end use */
|
||||
if (generation_flag > GN_VER2001) {
|
||||
warn_count += 1;
|
||||
cerr << @2 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl;
|
||||
}
|
||||
pform_endgenerate();
|
||||
}
|
||||
|
||||
/* specify blocks are parsed but ignored. */
|
||||
|
||||
|
|
|
|||
22
pform.cc
22
pform.cc
|
|
@ -530,6 +530,28 @@ void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
|
|||
pform_cur_generate->loop_step = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The named block generate case.
|
||||
*/
|
||||
void pform_start_generate_nblock(const struct vlltype&li, char*name)
|
||||
{
|
||||
PGenerate*gen = new PGenerate(scope_generate_counter++);
|
||||
|
||||
FILE_NAME(gen, li);
|
||||
|
||||
gen->parent = pform_cur_generate;
|
||||
pform_cur_generate = gen;
|
||||
|
||||
pform_cur_generate->scheme_type = PGenerate::GS_NBLOCK;
|
||||
|
||||
pform_cur_generate->loop_init = 0;
|
||||
pform_cur_generate->loop_test = 0;
|
||||
pform_cur_generate->loop_step = 0;
|
||||
|
||||
pform_cur_generate->scope_name = lex_strings.make(name);
|
||||
delete[]name;
|
||||
}
|
||||
|
||||
/*
|
||||
* The generate case item is a special case schema that takes its id
|
||||
* from the case schema that it is a part of. The idea is that the
|
||||
|
|
|
|||
1
pform.h
1
pform.h
|
|
@ -204,6 +204,7 @@ extern void pform_start_generate_for(const struct vlltype&li,
|
|||
extern void pform_start_generate_if(const struct vlltype&li, PExpr*test);
|
||||
extern void pform_start_generate_else(const struct vlltype&li);
|
||||
extern void pform_start_generate_case(const struct vlltype&lp, PExpr*test);
|
||||
extern void pform_start_generate_nblock(const struct vlltype&lp, char*name);
|
||||
extern void pform_generate_case_item(const struct vlltype&lp, PExpr*test);
|
||||
extern void pform_generate_block_name(char*name);
|
||||
extern void pform_endgenerate();
|
||||
|
|
|
|||
|
|
@ -1002,6 +1002,8 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
|||
else
|
||||
out << " default:";
|
||||
break;
|
||||
case GS_NBLOCK:
|
||||
out << " begin";
|
||||
}
|
||||
|
||||
if (scope_name)
|
||||
|
|
@ -1035,7 +1037,11 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
|||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
out << setw(indent) << "" << "endgenerate" << endl;
|
||||
if (scheme_type == GS_NBLOCK) {
|
||||
out << setw(indent) << "" << "end endgenerate" << endl;
|
||||
} else {
|
||||
out << setw(indent) << "" << "endgenerate" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void LexicalScope::dump_parameters_(ostream&out, unsigned indent) const
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
|||
|
||||
scope = des->find_scope(scope, path_list);
|
||||
|
||||
if (scope->is_auto() && li) {
|
||||
if (scope && scope->is_auto() && li) {
|
||||
cerr << li->get_fileline() << ": error: Hierarchical "
|
||||
"reference to automatically allocated item "
|
||||
"`" << key << "' in path `" << path << "'" << endl;
|
||||
|
|
|
|||
|
|
@ -446,12 +446,9 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
|
|||
|
||||
static vhdl_expr *translate_select(ivl_expr_t e)
|
||||
{
|
||||
vhdl_var_ref *from =
|
||||
dynamic_cast<vhdl_var_ref*>(translate_expr(ivl_expr_oper1(e)));
|
||||
if (NULL == from) {
|
||||
error("Can only select from variable reference");
|
||||
vhdl_expr *from = translate_expr(ivl_expr_oper1(e));
|
||||
if (NULL == from)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ivl_expr_t o2 = ivl_expr_oper2(e);
|
||||
if (o2) {
|
||||
|
|
@ -459,9 +456,21 @@ static vhdl_expr *translate_select(ivl_expr_t e)
|
|||
if (NULL == base)
|
||||
return NULL;
|
||||
|
||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||
from->set_slice(base->cast(&integer), ivl_expr_width(e) - 1);
|
||||
return from;
|
||||
vhdl_var_ref *from_var_ref = dynamic_cast<vhdl_var_ref*>(from);
|
||||
if (NULL == from_var_ref) {
|
||||
// We can't directly select bits from something that's not
|
||||
// a variable reference in VHDL, but we can emulate the
|
||||
// effect with a shift and a resize
|
||||
return new vhdl_binop_expr(from, VHDL_BINOP_SR, base->to_integer(),
|
||||
new vhdl_type(*from->get_type()));
|
||||
}
|
||||
else {
|
||||
// We can use the more idomatic VHDL slice notation on a
|
||||
// single variable reference
|
||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||
from_var_ref->set_slice(base->cast(&integer), ivl_expr_width(e) - 1);
|
||||
return from_var_ref;
|
||||
}
|
||||
}
|
||||
else
|
||||
return from->resize(ivl_expr_width(e));
|
||||
|
|
|
|||
|
|
@ -276,11 +276,24 @@ static string make_safe_name(ivl_signal_t sig)
|
|||
if (base[0] == '_')
|
||||
return string("VL") + base;
|
||||
|
||||
// This is the complete list of VHDL reserved words
|
||||
const char *vhdl_reserved[] = {
|
||||
"in", "out", "entity", "architecture", "inout", "array",
|
||||
"is", "not", "and", "or", "bus", "bit", "line", // Etc...
|
||||
"abs", "access", "after", "alias", "all", "and", "architecture",
|
||||
"array", "assert", "attribute", "begin", "block", "body", "buffer",
|
||||
"bus", "case", "component", "configuration", "constant", "disconnect",
|
||||
"downto", "else", "elsif", "end", "entity", "exit", "file", "for",
|
||||
"function", "generate", "generic", "group", "guarded", "if", "impure",
|
||||
"in", "inertial", "inout", "is", "label", "library", "linkage",
|
||||
"literal", "loop", "map", "mod", "nand", "new", "next", "nor", "not",
|
||||
"null", "of", "on", "open", "or", "others", "out", "package", "port",
|
||||
"postponed", "procedure", "process", "pure", "range", "record", "register",
|
||||
"reject", "rem", "report", "return", "rol", "ror", "select", "severity",
|
||||
"signal", "shared", "sla", "sll", "sra", "srl", "subtype", "then", "to",
|
||||
"transport", "type", "unaffected", "units", "until", "use", "variable",
|
||||
"wait", "when", "while", "with", "xnor", "xor",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (const char **p = vhdl_reserved; *p != NULL; p++) {
|
||||
if (strcasecmp(*p, base) == 0) {
|
||||
return string("VL_") + base;
|
||||
|
|
|
|||
|
|
@ -1053,7 +1053,7 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
|||
|
||||
/* shifting 0 gets 0. */
|
||||
if (lv.base == 0)
|
||||
break;
|
||||
return lv;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
|
|
@ -1088,7 +1088,7 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
|||
|
||||
/* shifting 0 gets 0. */
|
||||
if (lv.base == 0)
|
||||
break;
|
||||
return lv;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
|
|
@ -1123,12 +1123,12 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
|||
|
||||
/* shifting 0 gets 0. */
|
||||
if (lv.base == 0)
|
||||
break;
|
||||
return lv;
|
||||
|
||||
/* Sign extend any constant begets itself, if this
|
||||
expression is signed. */
|
||||
if ((lv.base < 4) && (ivl_expr_signed(exp)))
|
||||
break;
|
||||
return lv;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
|
|
@ -1823,6 +1823,8 @@ static struct vector_info draw_pad_expr(ivl_expr_t exp, unsigned wid)
|
|||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+subv.wid, res.wid - subv.wid);
|
||||
}
|
||||
if (subv.base >= 8)
|
||||
clr_vector(subv);
|
||||
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ static PLI_INT32 sys_clog2_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
/* We must have an argument. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("$clog2 requires one numeric argument.\n");
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -79,7 +79,7 @@ static PLI_INT32 sys_clog2_compiletf(PLI_BYTE8 *name)
|
|||
/* The argument must be numeric. */
|
||||
arg = vpi_scan(argv);
|
||||
if (! is_numeric_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("The first argument to $clog2 must be numeric.\n");
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -90,7 +90,7 @@ static PLI_INT32 sys_clog2_compiletf(PLI_BYTE8 *name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ static void double2bits(double real, PLI_UINT32 bits[2])
|
|||
|
||||
static void error_message(vpiHandle callh, const char* msg)
|
||||
{
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf(msg, vpi_get_str(vpiName, callh));
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
|
|||
|
|
@ -2198,6 +2198,27 @@ static PLI_INT32 sys_printtimescale_calltf(PLI_BYTE8*xx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 sys_no_aa_compiletf(PLI_BYTE8 *name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
vpiHandle arg;
|
||||
/* If there are no arguments, just return. */
|
||||
if (argv == 0) return 0;
|
||||
|
||||
for (arg = vpi_scan(argv) ; arg ; arg = vpi_scan(argv)) {
|
||||
if (vpi_get(vpiAutomatic, arg)) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s arguments may not be automatically "
|
||||
"allocated variables.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_display_register()
|
||||
{
|
||||
s_cb_data cb_data;
|
||||
|
|
@ -2273,7 +2294,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$strobe";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$strobe";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2281,7 +2302,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$strobeh";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$strobeh";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2289,7 +2310,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$strobeo";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$strobeo";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2297,7 +2318,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$strobeb";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$strobeb";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2306,7 +2327,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$fstrobe";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$fstrobe";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2314,7 +2335,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$fstrobeh";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$fstrobeh";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2322,7 +2343,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$fstrobeo";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$fstrobeo";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2330,7 +2351,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$fstrobeb";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$fstrobeb";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2339,7 +2360,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$monitor";
|
||||
tf_data.calltf = sys_monitor_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$monitor";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2347,7 +2368,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$monitorh";
|
||||
tf_data.calltf = sys_monitor_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$monitorh";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2355,7 +2376,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$monitoro";
|
||||
tf_data.calltf = sys_monitor_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$monitoro";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
@ -2363,7 +2384,7 @@ void sys_display_register()
|
|||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$monitorb";
|
||||
tf_data.calltf = sys_monitor_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_no_aa_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$monitorb";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
|
|
|||
|
|
@ -41,14 +41,14 @@ static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
/* Check that there is a file name argument and that it is a string. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires a string file name argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
if (! is_string_obj(vpi_scan(argv))) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's file name argument must be a string.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -60,7 +60,7 @@ static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
/* When provided, the type argument must be a string. */
|
||||
if (! is_string_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's type argument must be a string.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -71,7 +71,7 @@ static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8 *name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
vpi_get_value(mode, &val);
|
||||
/* Verify that we have a string and that it is not NULL. */
|
||||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_printf("WARNING: %s:%d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument is not a valid string.\n",
|
||||
|
|
@ -116,7 +116,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
|
||||
/* Make sure the mode string is correct. */
|
||||
if (strlen(val.value.str) > 3) {
|
||||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_printf("WARNING: %s:%d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument (%s) is too long.\n",
|
||||
|
|
@ -147,7 +147,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
if (! fail) break;
|
||||
|
||||
default:
|
||||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_printf("WARNING: %s:%d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument (%s) is invalid.\n",
|
||||
|
|
@ -169,7 +169,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
|
||||
/* Verify that we have a string and that it is not NULL. */
|
||||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's file name argument is not a valid string.\n",
|
||||
name);
|
||||
|
|
@ -185,7 +185,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
for (idx = 0; idx < len; idx++) {
|
||||
if (! isprint(val.value.str[idx])) {
|
||||
char msg [64];
|
||||
snprintf(msg, 64, "WARNING: %s line %d:",
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s %s's file name argument contains non-"
|
||||
|
|
@ -236,7 +236,7 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
|
|||
|
||||
/* Verify that we have a string and that it is not NULL. */
|
||||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's file name argument is not a valid string.\n",
|
||||
name);
|
||||
|
|
@ -251,7 +251,7 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
|
|||
for (idx = 0; idx < len; idx++) {
|
||||
if (! isprint(val.value.str[idx])) {
|
||||
char msg [64];
|
||||
snprintf(msg, 64, "WARNING: %s line %d:",
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s %s's file name argument contains non-"
|
||||
|
|
@ -355,7 +355,7 @@ static PLI_INT32 sys_fputc_calltf(PLI_BYTE8*name)
|
|||
fp = vpi_get_file(fd_mcd);
|
||||
val.format = vpiIntVal;
|
||||
if (!fp || IS_MCD(fd_mcd)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||
name);
|
||||
|
|
@ -378,7 +378,7 @@ static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
|
|||
* register and that the second is numeric.
|
||||
*/
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires two arguments.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -386,7 +386,7 @@ static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
|
|||
}
|
||||
|
||||
if (vpi_get(vpiType, vpi_scan(argv)) != vpiReg) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's first argument must be a reg.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -394,7 +394,7 @@ static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
|
|||
|
||||
arg = vpi_scan(argv);
|
||||
if (! arg) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires a second (numeric) argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -402,7 +402,7 @@ static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
|
|||
}
|
||||
|
||||
if (! is_numeric_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's second argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -413,7 +413,7 @@ static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ static PLI_INT32 sys_fgets_calltf(PLI_BYTE8*name)
|
|||
/* Return zero if this is not a valid fd. */
|
||||
fp = vpi_get_file(fd_mcd);
|
||||
if (!fp || IS_MCD(fd_mcd)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||
name);
|
||||
|
|
@ -519,7 +519,7 @@ static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name)
|
|||
/* Return EOF if this is not a valid fd. */
|
||||
fp = vpi_get_file(fd_mcd);
|
||||
if (!fp || IS_MCD(fd_mcd)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||
name);
|
||||
|
|
@ -545,7 +545,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
|||
|
||||
/* Check that there are three numeric arguments. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires three arguments.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -554,7 +554,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
|||
|
||||
/* Check that the first argument is numeric. */
|
||||
if (! is_numeric_obj(vpi_scan(argv))) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's first argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -563,7 +563,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
|||
/* Check that the second argument exists and is numeric. */
|
||||
arg = vpi_scan(argv);
|
||||
if (! arg) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires a second (numeric) argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -571,7 +571,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
|||
}
|
||||
|
||||
if (!arg || !is_numeric_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's second argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -580,7 +580,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
|||
/* Check that the third argument exists and is numeric. */
|
||||
arg = vpi_scan(argv);
|
||||
if (! arg) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires a third (numeric) argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -588,7 +588,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
|||
}
|
||||
|
||||
if (!arg || !is_numeric_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's third argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -599,7 +599,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -647,7 +647,7 @@ static PLI_INT32 sys_fseek_calltf(PLI_BYTE8*name)
|
|||
|
||||
/* Check that the operation is in the valid range. */
|
||||
if ((oper < 0) || (oper > 2)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's operation must be 0, 1 or 2 given %d.\n",
|
||||
name, oper);
|
||||
|
|
@ -660,7 +660,7 @@ static PLI_INT32 sys_fseek_calltf(PLI_BYTE8*name)
|
|||
/* Return EOF if this is not a valid fd. */
|
||||
fp = vpi_get_file(fd_mcd);
|
||||
if (!fp || IS_MCD(fd_mcd)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||
name);
|
||||
|
|
@ -696,7 +696,7 @@ static PLI_INT32 sys_common_fd_calltf(PLI_BYTE8*name)
|
|||
/* Return EOF if this is not a valid fd. */
|
||||
fp = vpi_get_file(fd_mcd);
|
||||
if (!fp || IS_MCD(fd_mcd)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||
name);
|
||||
|
|
@ -721,7 +721,7 @@ static PLI_INT32 sys_common_fd_calltf(PLI_BYTE8*name)
|
|||
val.value.integer = fgetc(fp);
|
||||
break;
|
||||
default:
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s cannot be processed with this routine.\n", name);
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ static void open_dumpfile(vpiHandle callh)
|
|||
dump_file = lt_init(dump_path);
|
||||
|
||||
if (dump_file == 0) {
|
||||
vpi_printf("LXT Error: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("LXT Error: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Unable to open %s for output.\n", dump_path);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ static void open_dumpfile(vpiHandle callh)
|
|||
dump_file = lxt2_wr_init(dump_path);
|
||||
|
||||
if (dump_file == 0) {
|
||||
vpi_printf("LXT2 Error: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("LXT2 Error: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Unable to open %s for output.\n", dump_path);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2008 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
|
||||
|
|
@ -16,87 +16,32 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_plusargs.c,v 1.7 2007/03/14 04:05:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "sys_priv.h"
|
||||
# include <vpi_user.h>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
static PLI_INT32 sys_plusargs_sizetf(PLI_BYTE8*x)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* The compiletf for $test$plusargs checks that there is one argument
|
||||
* to the function call, and that argument is a constant string.
|
||||
*/
|
||||
static PLI_INT32 sys_test_plusargs_compiletf(PLI_BYTE8*xx)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg;
|
||||
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: $test$plusargs requires one argument\n");
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg = vpi_scan(argv);
|
||||
assert(arg != 0);
|
||||
|
||||
switch (vpi_get(vpiType, arg)) {
|
||||
case vpiConstant:
|
||||
if (vpi_get(vpiConstType, arg) != vpiStringConst) {
|
||||
vpi_printf("ERROR: Argument of $test$plusargs "
|
||||
" must be a constant string.\n");
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_printf("ERROR: Argument of $test$plusargs "
|
||||
" must be a constant string.\n");
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
vpi_printf("ERROR: too many arguments to $test$plusargs\n");
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the +arguments passed to the simulator with the argument
|
||||
* passed to the $test$plusargs. If there is a simulator argument that
|
||||
* is like this argument, then return true. Otherwise return false.
|
||||
*/
|
||||
static PLI_INT32 sys_test_plusargs_calltf(PLI_BYTE8*xx)
|
||||
static PLI_INT32 sys_test_plusargs_calltf(PLI_BYTE8*name)
|
||||
{
|
||||
s_vpi_value val;
|
||||
s_vpi_vlog_info info;
|
||||
int idx;
|
||||
int flag = 0;
|
||||
size_t slen, len;
|
||||
s_vpi_vlog_info info;
|
||||
s_vpi_value value;
|
||||
s_vpi_value result;
|
||||
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg = vpi_scan(argv);
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(arg, &value);
|
||||
slen = strlen(value.value.str);
|
||||
val.format = vpiStringVal;
|
||||
vpi_get_value(vpi_scan(argv), &val);
|
||||
slen = strlen(val.value.str);
|
||||
|
||||
vpi_get_vlog_info(&info);
|
||||
|
||||
|
|
@ -111,97 +56,52 @@ static PLI_INT32 sys_test_plusargs_calltf(PLI_BYTE8*xx)
|
|||
if (len < slen)
|
||||
continue;
|
||||
|
||||
if (strncmp(value.value.str, info.argv[idx]+1, slen) != 0)
|
||||
if (strncmp(val.value.str, info.argv[idx]+1, slen) != 0)
|
||||
continue;
|
||||
|
||||
flag = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
result.format = vpiIntVal;
|
||||
result.value.integer = flag;
|
||||
vpi_put_value(sys, &result, 0, vpiNoDelay);
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = flag;
|
||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 sys_value_plusargs_compiletf(PLI_BYTE8*xx)
|
||||
static PLI_INT32 sys_value_plusargs_compiletf(PLI_BYTE8*name)
|
||||
{
|
||||
s_vpi_value value;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
vpiHandle arg;
|
||||
|
||||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: $value$plusargs requires two arguments\n");
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires two arguments.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check that the first argument is a string. */
|
||||
arg = vpi_scan(argv);
|
||||
assert(arg != 0);
|
||||
|
||||
switch (vpi_get(vpiType, arg)) {
|
||||
case vpiConstant:
|
||||
if (vpi_get(vpiConstType, arg) != vpiStringConst) {
|
||||
vpi_printf("ERROR: First argument of $value$plusargs "
|
||||
" must be a constant string.\n");
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_printf("ERROR: First argument of $value$plusargs "
|
||||
" must be a constant string.\n");
|
||||
if ( ! is_string_obj(arg)) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's first argument must be a string.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that the format string has a reasonable format. */
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(arg, &value);
|
||||
{ char*fmt = value.value.str;
|
||||
char*cp = strchr(fmt, '%');
|
||||
|
||||
if (cp == 0) {
|
||||
vpi_printf("ERROR: Invalid argument format string"
|
||||
": %s\n", fmt);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cp += 1;
|
||||
if (*cp == '0')
|
||||
cp += 1;
|
||||
|
||||
switch (*cp) {
|
||||
case 'd':
|
||||
case 'o':
|
||||
case 'b':
|
||||
case 'h':
|
||||
case 's':
|
||||
cp += 1;
|
||||
break;
|
||||
default:
|
||||
vpi_printf("ERROR: Invalid argument format string"
|
||||
": %s\n", fmt);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*cp != 0) {
|
||||
vpi_printf("ERROR: Trailing junk after value format"
|
||||
": %s\n", fmt);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
arg = vpi_scan(argv);
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: $value$plusargs requires two arguments\n");
|
||||
if (! arg) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's requires a second variable argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -210,55 +110,129 @@ static PLI_INT32 sys_value_plusargs_compiletf(PLI_BYTE8*xx)
|
|||
|
||||
case vpiReg:
|
||||
case vpiIntegerVar:
|
||||
case vpiRealVar:
|
||||
case vpiTimeVar:
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_printf("ERROR: value field doesn\'t match format: %s\n",
|
||||
value.value.str);
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's second argument must be a variable, found a %s.\n",
|
||||
name, vpi_get_str(vpiType, arg));
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
vpi_printf("ERROR: too many arguments to $value$plusargs\n");
|
||||
/* Make sure there are no extra arguments. */
|
||||
if (vpi_scan(argv) != 0) {
|
||||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
argc = 1;
|
||||
while (vpi_scan(argv)) argc += 1;
|
||||
|
||||
vpi_printf("%s %s takes two arguments.\n", msg, name);
|
||||
vpi_printf("%*s Found %u extra argument%s.\n",
|
||||
(int)strlen(msg), " ", argc, argc == 1 ? "" : "s");
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 sys_value_plusargs_calltf(PLI_BYTE8*xx)
|
||||
static PLI_INT32 sys_value_plusargs_calltf(PLI_BYTE8*name)
|
||||
{
|
||||
s_vpi_vlog_info info;
|
||||
s_vpi_value fmt;
|
||||
s_vpi_value res;
|
||||
char msg [64];
|
||||
char*cp;
|
||||
int idx;
|
||||
int flag = 0;
|
||||
size_t slen, len;
|
||||
s_vpi_vlog_info info;
|
||||
s_vpi_value format;
|
||||
s_vpi_value result;
|
||||
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg1 = vpi_scan(argv);
|
||||
vpiHandle arg2 = vpi_scan(argv);
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
|
||||
format.format = vpiStringVal;
|
||||
vpi_get_value(arg1, &format);
|
||||
fmt.format = vpiStringVal;
|
||||
vpi_get_value(vpi_scan(argv), &fmt);
|
||||
|
||||
/* Check for the start of a format string. */
|
||||
cp = strchr(fmt.value.str, '%');
|
||||
if (cp == 0) {
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
vpi_printf("%s %s is missing a format code.\n", msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the length of string we will look for. */
|
||||
slen = cp - fmt.value.str;
|
||||
|
||||
/* Skip a zero. */
|
||||
cp += 1;
|
||||
if (*cp == '0') cp += 1;
|
||||
|
||||
/* Check the format code. */
|
||||
switch (*cp) {
|
||||
case 'd':
|
||||
case 'D':
|
||||
case 'o':
|
||||
case 'O':
|
||||
case 'h':
|
||||
case 'H':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 's':
|
||||
case 'S':
|
||||
break;
|
||||
default:
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
vpi_printf("%s %s has an invalid format string:\n", msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Warn if there is any trailing garbage. */
|
||||
if (*(cp+1) != '\0') {
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
vpi_printf("%s Skipping trailing garbage in %s's format string:\n",
|
||||
msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
|
||||
*(cp+1) = '\0';
|
||||
}
|
||||
|
||||
vpi_get_vlog_info(&info);
|
||||
|
||||
cp = strchr(format.value.str, '%');
|
||||
assert(cp);
|
||||
slen = cp - format.value.str;
|
||||
|
||||
cp += 1;
|
||||
if (*cp == '0')
|
||||
cp += 1;
|
||||
|
||||
/* Look for a +arg that matches the prefix supplied. */
|
||||
for (idx = 0 ; idx < info.argc ; idx += 1) {
|
||||
char*sp, *tp, *end;
|
||||
size_t sp_len;
|
||||
|
||||
/* Skip arguments that are not +args. */
|
||||
if (info.argv[idx][0] != '+')
|
||||
continue;
|
||||
|
||||
|
|
@ -266,43 +240,146 @@ static PLI_INT32 sys_value_plusargs_calltf(PLI_BYTE8*xx)
|
|||
if (len < slen)
|
||||
continue;
|
||||
|
||||
if (strncmp(format.value.str, info.argv[idx]+1, slen) != 0)
|
||||
if (strncmp(fmt.value.str, info.argv[idx]+1, slen) != 0)
|
||||
continue;
|
||||
|
||||
sp = info.argv[idx]+1+slen;
|
||||
sp_len = strlen(sp);
|
||||
switch (*cp) {
|
||||
case 'd':
|
||||
result.format = vpiIntVal;
|
||||
result.value.integer = strtoul(info.argv[idx]+1+slen,0,10);
|
||||
case 'D':
|
||||
res.format = vpiDecStrVal;
|
||||
/* A decimal string can set the value to "x" or "z". */
|
||||
if (sp_len == strspn(sp, "xX_") ||
|
||||
sp_len == strspn(sp, "zZ_")) {
|
||||
res.value.str = sp;
|
||||
/* A decimal string must contain only these characters.
|
||||
* A decimal string can not start with an "_" character.
|
||||
* A "-" can only be at the start of the string. */
|
||||
} else if (sp_len != strspn(sp, "-0123456789_") ||
|
||||
*sp == '_' ||
|
||||
((tp = strrchr(sp, '-')) && tp != sp)) {
|
||||
res.value.str = "x";
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s Invalid decimal value passed to %s:\n",
|
||||
msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
|
||||
} else {
|
||||
res.value.str = sp;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
result.format = vpiIntVal;
|
||||
result.value.integer = strtoul(info.argv[idx]+1+slen,0,8);
|
||||
case 'O':
|
||||
res.format = vpiOctStrVal;
|
||||
/* An octal string must contain only these characters.
|
||||
* An octal string can not start with an "_" character.
|
||||
* A "-" can only be at the start of the string. */
|
||||
if (sp_len != strspn(sp, "-01234567_xXzZ") ||
|
||||
*sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
|
||||
res.value.str = "x";
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s Invalid octal value passed to %s:\n",
|
||||
msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
|
||||
} else {
|
||||
res.value.str = sp;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
result.format = vpiIntVal;
|
||||
result.value.integer = strtoul(info.argv[idx]+1+slen,0,16);
|
||||
case 'H':
|
||||
case 'x':
|
||||
case 'X':
|
||||
res.format = vpiHexStrVal;
|
||||
/* A hex. string must contain only these characters.
|
||||
* A hex. string can not start with an "_" character.
|
||||
* A "-" can only be at the start of the string. */
|
||||
if (sp_len != strspn(sp, "-0123456789aAbBcCdDeEfF_xXzZ") ||
|
||||
*sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
|
||||
res.value.str = "x";
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s Invalid hex value passed to %s:\n",
|
||||
msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
|
||||
} else {
|
||||
res.value.str = sp;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
result.format = vpiIntVal;
|
||||
result.value.integer = strtoul(info.argv[idx]+1+slen,0,12);
|
||||
case 'B':
|
||||
res.format = vpiBinStrVal;
|
||||
/* A binary string must contain only these characters.
|
||||
* A binary string can not start with an "_" character.
|
||||
* A "-" can only be at the start of the string. */
|
||||
if (sp_len != strspn(sp, "-01_xXzZ") ||
|
||||
*sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
|
||||
res.value.str = "x";
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s Invalid binary value passed to %s:\n",
|
||||
msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
|
||||
} else {
|
||||
res.value.str = sp;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
res.format = vpiRealVal;
|
||||
res.value.real = strtod(sp, &end);
|
||||
/* If we didn't get a full conversion print a warning. */
|
||||
if (*end) {
|
||||
/* We had an invalid value passed. */
|
||||
if (end == sp) {
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s Invalid real value passed to "
|
||||
"%s:\n", msg, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ",
|
||||
sp);
|
||||
/* We have extra garbage at the end. */
|
||||
} else {
|
||||
snprintf(msg, 64, "WARNING: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s Extra character(s) \"%s\" found "
|
||||
"in %s's real string:\n",
|
||||
msg, end, name);
|
||||
vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ",
|
||||
sp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
result.format = vpiStringVal;
|
||||
result.value.str = info.argv[idx]+1+slen;
|
||||
case 'S':
|
||||
res.format = vpiStringVal;
|
||||
res.value.str = sp;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vpi_put_value(arg2, &result, 0, vpiNoDelay);
|
||||
vpi_put_value(vpi_scan(argv), &res, 0, vpiNoDelay);
|
||||
flag = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
result.format = vpiIntVal;
|
||||
result.value.integer = flag;
|
||||
vpi_put_value(sys, &result, 0, vpiNoDelay);
|
||||
res.format = vpiIntVal;
|
||||
res.value.integer = flag;
|
||||
vpi_put_value(callh, &res, 0, vpiNoDelay);
|
||||
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -311,44 +388,22 @@ void sys_plusargs_register()
|
|||
s_vpi_systf_data tf_data;
|
||||
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$test$plusargs";
|
||||
tf_data.calltf = sys_test_plusargs_calltf;
|
||||
tf_data.compiletf = sys_test_plusargs_compiletf;
|
||||
tf_data.sizetf = sys_plusargs_sizetf;
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiIntFunc;
|
||||
tf_data.tfname = "$test$plusargs";
|
||||
tf_data.calltf = sys_test_plusargs_calltf;
|
||||
tf_data.compiletf = sys_one_string_arg_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$test$plusargs";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$value$plusargs";
|
||||
tf_data.calltf = sys_value_plusargs_calltf;
|
||||
tf_data.compiletf = sys_value_plusargs_compiletf;
|
||||
tf_data.sizetf = sys_plusargs_sizetf;
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiIntFunc;
|
||||
tf_data.tfname = "$value$plusargs";
|
||||
tf_data.calltf = sys_value_plusargs_calltf;
|
||||
tf_data.compiletf = sys_value_plusargs_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$value$plusargs";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sys_plusargs.c,v $
|
||||
* Revision 1.7 2007/03/14 04:05:51 steve
|
||||
* VPI tasks take PLI_BYTE* by the standard.
|
||||
*
|
||||
* Revision 1.6 2006/10/30 22:45:37 steve
|
||||
* Updates for Cygwin portability (pr1585922)
|
||||
*
|
||||
* Revision 1.5 2004/10/04 01:10:58 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.4 2002/08/12 01:35:05 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/08/11 23:47:04 steve
|
||||
* Add missing Log and Ident strings.
|
||||
*
|
||||
* Revision 1.2 2002/08/10 17:00:31 steve
|
||||
* Allow vpiIntegerVar as parameter to $value$plusarg
|
||||
*
|
||||
* Revision 1.1 2002/04/07 04:37:53 steve
|
||||
* Add $plusargs system functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ unsigned is_numeric_obj(vpiHandle obj)
|
|||
case vpiRealVar:
|
||||
case vpiReg:
|
||||
case vpiTimeVar:
|
||||
rtn = 1;;
|
||||
rtn = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ unsigned is_string_obj(vpiHandle obj)
|
|||
case vpiPartSelect:
|
||||
case vpiReg:
|
||||
case vpiTimeVar:
|
||||
rtn = 1;;
|
||||
rtn = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ PLI_INT32 sys_no_arg_compiletf(PLI_BYTE8 *name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ PLI_INT32 sys_one_numeric_arg_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
/* Check that there is an argument and that it is numeric. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires a single numeric argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -184,7 +184,7 @@ PLI_INT32 sys_one_numeric_arg_compiletf(PLI_BYTE8 *name)
|
|||
}
|
||||
|
||||
if (! is_numeric_obj(vpi_scan(argv))) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -195,7 +195,7 @@ PLI_INT32 sys_one_numeric_arg_compiletf(PLI_BYTE8 *name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ PLI_INT32 sys_one_opt_numeric_arg_compiletf(PLI_BYTE8 *name)
|
|||
if (argv == 0) return 0;
|
||||
|
||||
if (! is_numeric_obj(vpi_scan(argv))) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -232,7 +232,7 @@ PLI_INT32 sys_one_opt_numeric_arg_compiletf(PLI_BYTE8 *name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -258,7 +258,7 @@ PLI_INT32 sys_two_numeric_args_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
/* Check that there are two argument and that they are numeric. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires two numeric arguments.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -266,7 +266,7 @@ PLI_INT32 sys_two_numeric_args_compiletf(PLI_BYTE8 *name)
|
|||
}
|
||||
|
||||
if (! is_numeric_obj(vpi_scan(argv))) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's first argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -274,7 +274,7 @@ PLI_INT32 sys_two_numeric_args_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
arg = vpi_scan(argv);
|
||||
if (! arg) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires a second (numeric) argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -282,7 +282,7 @@ PLI_INT32 sys_two_numeric_args_compiletf(PLI_BYTE8 *name)
|
|||
}
|
||||
|
||||
if (! is_numeric_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's second argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -293,7 +293,7 @@ PLI_INT32 sys_two_numeric_args_compiletf(PLI_BYTE8 *name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -317,14 +317,14 @@ PLI_INT32 sys_one_string_arg_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
/* Check that there is an argument and that it is a string. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s requires a single string argument.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
if (! is_string_obj(vpi_scan(argv))) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's argument must be a string.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -335,7 +335,7 @@ PLI_INT32 sys_one_string_arg_compiletf(PLI_BYTE8 *name)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ static void open_dumpfile(vpiHandle callh)
|
|||
dump_file = fopen(dump_path, "w");
|
||||
|
||||
if (dump_file == 0) {
|
||||
vpi_printf("VCD Error: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("VCD Error: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Unable to open %s for output.\n", dump_path);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -677,7 +677,7 @@ static int draw_scope(vpiHandle item, vpiHandle callh)
|
|||
case vpiNamedFork: type = "fork"; break;
|
||||
case vpiModule: type = "module"; break;
|
||||
default:
|
||||
vpi_printf("VCD Error: %s line %d: $dumpvars: Unsupported scope "
|
||||
vpi_printf("VCD Error: %s:%d: $dumpvars: Unsupported scope "
|
||||
"type (%d)\n", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh), vpi_get(vpiType, item));
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ static PLI_INT32 simparam_compiletf(PLI_BYTE8 *name_ext)
|
|||
|
||||
/* We must have at least one argument. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("$simparam%s requires a string argument.\n", name_ext);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -54,7 +54,7 @@ static PLI_INT32 simparam_compiletf(PLI_BYTE8 *name_ext)
|
|||
/* The first argument must be a string. */
|
||||
arg = vpi_scan(argv);
|
||||
if (! is_string_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("The first argument to $simparam%s must be a string.\n",
|
||||
name_ext);
|
||||
|
|
@ -68,7 +68,7 @@ static PLI_INT32 simparam_compiletf(PLI_BYTE8 *name_ext)
|
|||
/* For the string version the default must also be a string. */
|
||||
if (strcmp(name_ext, "$str") == 0) {
|
||||
if (! is_string_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("When provided, the second argument to $simparam%s"
|
||||
"must be a string.\n", name_ext);
|
||||
|
|
@ -77,7 +77,7 @@ static PLI_INT32 simparam_compiletf(PLI_BYTE8 *name_ext)
|
|||
/* For the rest the default must be numeric. */
|
||||
} else {
|
||||
if (! is_numeric_obj(arg)) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("When provided, the second argument to $simparam%s"
|
||||
"must be numeric.\n", name_ext);
|
||||
|
|
@ -90,7 +90,7 @@ static PLI_INT32 simparam_compiletf(PLI_BYTE8 *name_ext)
|
|||
char msg [64];
|
||||
unsigned argc;
|
||||
|
||||
snprintf(msg, 64, "ERROR: %s line %d:",
|
||||
snprintf(msg, 64, "ERROR: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ static PLI_INT32 simparam_calltf(PLI_BYTE8 *name_ext)
|
|||
retval = 8.0*sizeof(long);
|
||||
} else {
|
||||
if (! have_def_val) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("$simparam%s unknown parameter name \"%s\".\n",
|
||||
name_ext, param);
|
||||
|
|
@ -229,7 +229,7 @@ static PLI_INT32 simparam_str_calltf(PLI_BYTE8 *name_ext)
|
|||
vpi_handle(vpiScope,callh)));
|
||||
} else {
|
||||
if (defval == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("$simparam%s unknown parameter name \"%s\".\n",
|
||||
name_ext, param);
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name)
|
|||
|
||||
/* The first argument is the numeric level. */
|
||||
if (! is_numeric_obj(vpi_scan(argv))) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's argument must be numeric.\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -215,7 +215,7 @@ PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name)
|
|||
switch(vpi_get(vpiType, arg)) {
|
||||
case vpiMemoryWord:
|
||||
if (vpi_get(vpiConstantSelect, arg) == 0) {
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s cannot dump a non-constant select %s.\n", name,
|
||||
vpi_get_str(vpiType, arg));
|
||||
|
|
@ -235,7 +235,7 @@ PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name)
|
|||
case vpiRealVar:
|
||||
break;
|
||||
default:
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s cannot dump a %s.\n", name,
|
||||
vpi_get_str(vpiType, arg));
|
||||
|
|
|
|||
|
|
@ -454,6 +454,9 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
|||
case vpiRightRange:
|
||||
return parent->lsb.value;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) parent->scope->is_automatic;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -634,6 +637,9 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref)
|
|||
case vpiRightRange:
|
||||
return parent->lsb.value;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) parent->scope->is_automatic;
|
||||
|
||||
// For now &A<> is only a constant select. This will need
|
||||
// to be changed when it supports variable selection.
|
||||
case vpiConstantSelect:
|
||||
|
|
|
|||
|
|
@ -119,6 +119,14 @@ void delete_vpi_callback(struct __vpiCallback* ref)
|
|||
*/
|
||||
static struct __vpiCallback* make_value_change(p_cb_data data)
|
||||
{
|
||||
if (vpi_get(vpiAutomatic, data->obj)) {
|
||||
fprintf(stderr, "vpi error: cannot place value change "
|
||||
"callback on automatically allocated "
|
||||
"variable '%s'\n",
|
||||
vpi_get_str(vpiName, data->obj));
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct __vpiCallback*obj = new_vpi_callback();
|
||||
obj->cb_data = *data;
|
||||
if (data->time) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ static int string_get(int code, vpiHandle ref)
|
|||
case vpiConstType:
|
||||
return vpiStringConst;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiStringConst\n", code);
|
||||
|
|
@ -343,6 +346,9 @@ static int binary_get(int code, vpiHandle ref)
|
|||
case vpiSize:
|
||||
return rfp->bits.size();
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiBinaryConst\n", code);
|
||||
|
|
@ -533,6 +539,9 @@ static int dec_get(int code, vpiHandle ref)
|
|||
case vpiSize:
|
||||
return 32;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiDecConst\n", code);
|
||||
|
|
@ -636,6 +645,9 @@ static int real_get(int code, vpiHandle ref)
|
|||
case vpiSigned:
|
||||
return 1;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiDecConst\n", code);
|
||||
|
|
|
|||
|
|
@ -692,6 +692,14 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
|||
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
|
||||
vvp_time64_t dly;
|
||||
|
||||
if (vpi_get(vpiAutomatic, obj)) {
|
||||
fprintf(stderr, "vpi error: cannot put a value with "
|
||||
"a delay on automatically allocated "
|
||||
"variable '%s'\n",
|
||||
vpi_get_str(vpiName, obj));
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(when != 0);
|
||||
|
||||
switch (when->type) {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@ struct __vpiSignal {
|
|||
unsigned signed_flag : 1;
|
||||
unsigned isint_ : 1; // original type was integer
|
||||
unsigned is_netarray : 1; // This is word of a net array
|
||||
unsigned is_automatic : 1;
|
||||
/* The represented value is here. */
|
||||
vvp_net_t*node;
|
||||
};
|
||||
|
|
@ -563,8 +562,6 @@ extern unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
|
|||
char *buf, unsigned int nbuf,
|
||||
int signed_flag);
|
||||
|
||||
extern void vpip_bin_str_to_vec4(vvp_vector4_t&val,
|
||||
const char*buf, bool signed_flag);
|
||||
|
||||
extern void vpip_vec4_to_hex_str(const vvp_vector4_t&bits, char*buf,
|
||||
unsigned nbuf, bool signed_flag);
|
||||
|
|
@ -572,8 +569,9 @@ extern void vpip_vec4_to_hex_str(const vvp_vector4_t&bits, char*buf,
|
|||
extern void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf,
|
||||
unsigned nbuf, bool signed_flag);
|
||||
|
||||
extern void vpip_bin_str_to_vec4(vvp_vector4_t&val, const char*buf);
|
||||
extern void vpip_oct_str_to_vec4(vvp_vector4_t&val, const char*str);
|
||||
extern void vpip_dec_str_to_vec4(vvp_vector4_t&val, const char*str, bool sign);
|
||||
extern void vpip_dec_str_to_vec4(vvp_vector4_t&val, const char*str);
|
||||
extern void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str);
|
||||
|
||||
extern vvp_vector4_t vec4_from_vpi_value(s_vpi_value*vp, unsigned wid);
|
||||
|
|
|
|||
|
|
@ -136,23 +136,37 @@ static void real_var_get_value(vpiHandle ref, s_vpi_value*vp)
|
|||
|
||||
static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp, int)
|
||||
{
|
||||
vvp_vector4_t vec4(1024);
|
||||
double result;
|
||||
bool is_signed = false;
|
||||
assert(ref->vpi_type->type_code == vpiRealVar);
|
||||
|
||||
struct __vpiRealVar*rfp
|
||||
= (struct __vpiRealVar*)ref;
|
||||
|
||||
vvp_net_ptr_t destination (rfp->net, 0);
|
||||
|
||||
switch (vp->format) {
|
||||
|
||||
case vpiRealVal:
|
||||
vvp_send_real(destination, vp->value.real,
|
||||
vthread_get_wt_context());
|
||||
result = vp->value.real;
|
||||
break;
|
||||
|
||||
case vpiIntVal:
|
||||
vvp_send_real(destination, (double)vp->value.integer,
|
||||
vthread_get_wt_context());
|
||||
result = (double)vp->value.integer;
|
||||
break;
|
||||
case vpiBinStrVal:
|
||||
vpip_bin_str_to_vec4(vec4, vp->value.str);
|
||||
if (vp->value.str[0] == '-') is_signed = true;
|
||||
vector4_to_value(vec4, result, is_signed);
|
||||
break;
|
||||
case vpiOctStrVal:
|
||||
vpip_oct_str_to_vec4(vec4, vp->value.str);
|
||||
if (vp->value.str[0] == '-') is_signed = true;
|
||||
vector4_to_value(vec4, result, is_signed);
|
||||
break;
|
||||
case vpiDecStrVal:
|
||||
vpip_dec_str_to_vec4(vec4, vp->value.str);
|
||||
if (vp->value.str[0] == '-') is_signed = true;
|
||||
vector4_to_value(vec4, result, is_signed);
|
||||
break;
|
||||
case vpiHexStrVal:
|
||||
vpip_hex_str_to_vec4(vec4, vp->value.str);
|
||||
if (vp->value.str[0] == '-') is_signed = true;
|
||||
vector4_to_value(vec4, result, is_signed);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -160,8 +174,12 @@ static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
vp->format);
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
||||
assert(rfp);
|
||||
vvp_net_ptr_t destination (rfp->net, 0);
|
||||
vvp_send_real(destination, result, vthread_get_wt_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ static int scope_get(int code, vpiHandle obj)
|
|||
|
||||
case vpiTopModule:
|
||||
return 0x0 == ref->scope;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) ref->is_automatic;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -330,33 +333,29 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
struct __vpiScope*scope = new struct __vpiScope;
|
||||
count_vpi_scopes += 1;
|
||||
|
||||
if (strcmp(type,"module") == 0) {
|
||||
char*base_type = 0;
|
||||
if (strncmp(type,"auto",4) == 0) {
|
||||
scope->is_automatic = true;
|
||||
base_type = &type[4];
|
||||
} else {
|
||||
scope->is_automatic = false;
|
||||
base_type = &type[0];
|
||||
}
|
||||
|
||||
if (strcmp(base_type,"module") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_module_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"autofunction") == 0) {
|
||||
} else if (strcmp(base_type,"function") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_function_rt;
|
||||
scope->is_automatic = true;
|
||||
} else if (strcmp(type,"function") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_function_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"autotask") == 0) {
|
||||
} else if (strcmp(base_type,"task") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_task_rt;
|
||||
scope->is_automatic = true;
|
||||
} else if (strcmp(type,"task") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_task_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"fork") == 0) {
|
||||
} else if (strcmp(base_type,"fork") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_fork_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"begin") == 0) {
|
||||
} else if (strcmp(base_type,"begin") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_begin_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"generate") == 0) {
|
||||
} else if (strcmp(base_type,"generate") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_begin_rt;
|
||||
scope->is_automatic = false;
|
||||
} else {
|
||||
scope->base.vpi_type = &vpip_scope_module_rt;
|
||||
scope->is_automatic = false;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
|
@ -396,10 +395,6 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
scope->time_units = sp->time_units;
|
||||
scope->time_precision = sp->time_precision;
|
||||
|
||||
/* Scopes within automatic scopes are themselves automatic. */
|
||||
if (sp->is_automatic)
|
||||
scope->is_automatic = true;
|
||||
|
||||
} else {
|
||||
scope->scope = 0x0;
|
||||
|
||||
|
|
@ -476,5 +471,3 @@ unsigned vpip_add_item_to_context(automatic_hooks_s*item,
|
|||
/* Offset the context index by 2 to leave space for the list links. */
|
||||
return 2 + idx;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -528,10 +528,14 @@ static int signal_get(int code, vpiHandle ref)
|
|||
else
|
||||
return 0;
|
||||
|
||||
case vpiLeftRange: return rfp->msb;
|
||||
case vpiRightRange: return rfp->lsb;
|
||||
case vpiLeftRange:
|
||||
return rfp->msb;
|
||||
|
||||
case vpiAutomatic: return rfp->is_automatic;
|
||||
case vpiRightRange:
|
||||
return rfp->lsb;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) vpip_scope(rfp)->is_automatic;
|
||||
|
||||
case _vpiNexusId:
|
||||
if (rfp->msb == rfp->lsb)
|
||||
|
|
@ -800,13 +804,13 @@ vvp_vector4_t vec4_from_vpi_value(s_vpi_value*vp, unsigned wid)
|
|||
}
|
||||
break;
|
||||
case vpiBinStrVal:
|
||||
vpip_bin_str_to_vec4(val, vp->value.str, false);
|
||||
vpip_bin_str_to_vec4(val, vp->value.str);
|
||||
break;
|
||||
case vpiOctStrVal:
|
||||
vpip_oct_str_to_vec4(val, vp->value.str);
|
||||
break;
|
||||
case vpiDecStrVal:
|
||||
vpip_dec_str_to_vec4(val, vp->value.str, false);
|
||||
vpip_dec_str_to_vec4(val, vp->value.str);
|
||||
break;
|
||||
case vpiHexStrVal:
|
||||
vpip_hex_str_to_vec4(val, vp->value.str);
|
||||
|
|
@ -817,6 +821,9 @@ vvp_vector4_t vec4_from_vpi_value(s_vpi_value*vp, unsigned wid)
|
|||
case vpiStringVal:
|
||||
val = from_stringval(vp->value.str, wid);
|
||||
break;
|
||||
case vpiRealVal:
|
||||
val = vvp_vector4_t(wid, vp->value.real);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp internal error: put_value: "
|
||||
|
|
@ -863,7 +870,6 @@ vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
|
|||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->isint_ = true;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -874,9 +880,7 @@ vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
|||
bool signed_flag, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -915,7 +919,6 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
obj->signed_flag = signed_flag? 1 : 0;
|
||||
obj->isint_ = 0;
|
||||
obj->is_netarray = 0;
|
||||
obj->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
obj->node = node;
|
||||
|
||||
// Place this object within a scope. If this object is
|
||||
|
|
@ -972,11 +975,15 @@ static int PV_get(int code, vpiHandle ref)
|
|||
case vpiConstantSelect:
|
||||
return rfp->twid == 0;
|
||||
|
||||
case vpiLeftRange: rval += rfp->width;
|
||||
case vpiLeftRange:
|
||||
rval += rfp->width;
|
||||
case vpiRightRange:
|
||||
rval += vpi_get(vpiRightRange, rfp->parent) + PV_get_base(rfp);
|
||||
return rval;
|
||||
|
||||
case vpiAutomatic:
|
||||
return vpi_get(vpiAutomatic, rfp->parent);
|
||||
|
||||
default:
|
||||
fprintf(stderr, "PV_get: property %d is unknown\n", code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ static int timevar_time_get(int code, vpiHandle ref)
|
|||
case vpiFuncType:
|
||||
return vpiTimeFunc;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Code: %d\n", code);
|
||||
assert(0);
|
||||
|
|
@ -148,6 +151,9 @@ static int timevar_realtime_get(int code, vpiHandle ref)
|
|||
case vpiFuncType:
|
||||
return vpiRealFunc;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Code: %d\n", code);
|
||||
assert(0);
|
||||
|
|
|
|||
125
vvp/vpip_bin.cc
125
vvp/vpip_bin.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2006 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2008 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
|
||||
|
|
@ -16,9 +16,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpip_bin.cc,v 1.4 2006/08/03 05:05:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "vpi_priv.h"
|
||||
|
|
@ -31,69 +28,89 @@
|
|||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
void vpip_bin_str_to_vec4(vvp_vector4_t&vec4,
|
||||
const char*buf, bool signed_flag)
|
||||
void vpip_bin_str_to_vec4(vvp_vector4_t&vec4, const char*buf)
|
||||
{
|
||||
const char*ebuf = buf + strlen(buf);
|
||||
vvp_bit4_t last = BIT4_0;
|
||||
|
||||
unsigned idx = 0;
|
||||
unsigned skip_chars = 0;
|
||||
const char*tbuf = buf;
|
||||
/* Find the number of non-numeric characters. */
|
||||
while ((tbuf = strpbrk(tbuf, "-_"))) {
|
||||
skip_chars += 1;
|
||||
tbuf += 1;
|
||||
}
|
||||
vvp_vector4_t tval(strlen(buf)-skip_chars);
|
||||
while (ebuf > buf) {
|
||||
vvp_bit4_t val;
|
||||
|
||||
if (idx == vec4.size())
|
||||
break;
|
||||
|
||||
ebuf -= 1;
|
||||
switch (*ebuf) {
|
||||
case '0': val = BIT4_0; break;
|
||||
case '1': val = BIT4_1; break;
|
||||
case 'x':
|
||||
case 'X': val = BIT4_X; break;
|
||||
case 'z':
|
||||
case 'Z': val = BIT4_Z; break;
|
||||
default: val = BIT4_0; break;
|
||||
/* Skip any "_" characters in the string. */
|
||||
while (*ebuf == '_') {
|
||||
ebuf -= 1;
|
||||
assert(ebuf > buf);
|
||||
}
|
||||
|
||||
/* If we find a "-" it must be at the head of the string. */
|
||||
if (*ebuf == '-') {
|
||||
if (ebuf != buf) assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(idx < tval.size());
|
||||
switch (*ebuf) {
|
||||
case '0':
|
||||
tval.set_bit(idx, BIT4_0);
|
||||
break;
|
||||
case '1':
|
||||
tval.set_bit(idx, BIT4_1);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
tval.set_bit(idx, BIT4_X);
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
tval.set_bit(idx, BIT4_Z);
|
||||
break;
|
||||
default:
|
||||
/* Return "x" if there are invalid digits in the string. */
|
||||
fprintf(stderr, "Warning: Invalid binary digit %c(%d) in "
|
||||
"\"%s\".\n", *ebuf, *ebuf, buf);
|
||||
for (unsigned idx = 0 ; idx < vec4.size() ; idx += 1) {
|
||||
vec4.set_bit(idx, BIT4_X);
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
last = val;
|
||||
vec4.set_bit(idx, val);
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
/* Calculate the pad value based on the top bit and the signed
|
||||
flag. We may sign extend or zero extend. */
|
||||
switch (last) {
|
||||
case BIT4_0:
|
||||
last = BIT4_0;
|
||||
/* Make a negative value when needed. */
|
||||
if (buf[0] == '-') {
|
||||
tval.invert();
|
||||
tval += (int64_t) 1;
|
||||
}
|
||||
|
||||
/* Find the correct padding value. */
|
||||
vvp_bit4_t pad;
|
||||
switch (tval.value(tval.size()-1)) {
|
||||
case BIT4_X: // Pad MSB 'x' with 'x'
|
||||
pad = BIT4_X;
|
||||
break;
|
||||
case BIT4_1:
|
||||
last = signed_flag? BIT4_1 : BIT4_0;
|
||||
case BIT4_Z: // Pad MSB 'z' with 'z'
|
||||
pad = BIT4_Z;
|
||||
break;
|
||||
case BIT4_X:
|
||||
last = BIT4_X;
|
||||
break;
|
||||
case BIT4_Z:
|
||||
last = BIT4_Z;
|
||||
case BIT4_1: // If negative pad MSB '1' with '1'
|
||||
if (buf[0] == '-') {
|
||||
pad = BIT4_1;
|
||||
break;
|
||||
}
|
||||
default: // Everything else gets '0' padded/
|
||||
pad = BIT4_0;
|
||||
break;
|
||||
}
|
||||
|
||||
while (idx < vec4.size())
|
||||
vec4.set_bit(idx++, last);
|
||||
for (unsigned idx = 0 ; idx < vec4.size() ; idx += 1) {
|
||||
if (idx < tval.size()) vec4.set_bit(idx, tval.value(idx));
|
||||
else vec4.set_bit(idx, pad);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpip_bin.cc,v $
|
||||
* Revision 1.4 2006/08/03 05:05:06 steve
|
||||
* Fix infinite loop padding binary string to result.
|
||||
*
|
||||
* Revision 1.3 2006/02/21 05:31:54 steve
|
||||
* Put strings for reg objects.
|
||||
*
|
||||
* Revision 1.2 2002/08/12 01:35:09 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/05/11 04:39:35 steve
|
||||
* Set and get memory words by string value.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -33,29 +33,30 @@ extern const char hex_digits[256];
|
|||
void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str)
|
||||
{
|
||||
unsigned str_len = strlen(str);
|
||||
|
||||
char pad = '0';
|
||||
switch (str[0]) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
pad = 'x';
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
pad = 'z';
|
||||
break;
|
||||
unsigned skip_chars = 0;
|
||||
const char*tstr = str;
|
||||
/* Find the number of non-numeric characters. */
|
||||
while ((tstr = strpbrk(tstr, "-_"))) {
|
||||
skip_chars += 1;
|
||||
tstr += 1;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
vvp_vector4_t tval(4*(str_len-skip_chars));
|
||||
skip_chars = 0;
|
||||
for (unsigned idx = 0 ; idx < tval.size() ; idx += 1) {
|
||||
unsigned tmp;
|
||||
unsigned bit_off = idx%4;
|
||||
unsigned str_off = idx/4;
|
||||
|
||||
char ch;
|
||||
if (str_off >= str_len)
|
||||
ch = pad;
|
||||
else
|
||||
ch = str[str_len-str_off-1];
|
||||
|
||||
assert (str_off+skip_chars < str_len);
|
||||
/* Skip any "_" characters in the string. */
|
||||
while((ch = str[str_len-str_off-1-skip_chars]) == '_') {
|
||||
skip_chars += 1;
|
||||
assert (str_off+skip_chars < str_len);
|
||||
}
|
||||
|
||||
/* If we find a "-" it must be at the head of the string. */
|
||||
if (ch == '-') assert(0);
|
||||
|
||||
switch (ch) {
|
||||
case '0':
|
||||
|
|
@ -69,7 +70,7 @@ void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str)
|
|||
case '8':
|
||||
case '9':
|
||||
tmp = ch - '0';
|
||||
val.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
tval.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
|
|
@ -78,7 +79,7 @@ void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str)
|
|||
case 'e':
|
||||
case 'f':
|
||||
tmp = ch - 'a' + 10;
|
||||
val.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
tval.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
|
|
@ -87,22 +88,58 @@ void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str)
|
|||
case 'E':
|
||||
case 'F':
|
||||
tmp = ch - 'A' + 10;
|
||||
val.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
tval.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
val.set_bit(idx, BIT4_X);
|
||||
tval.set_bit(idx, BIT4_X);
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
val.set_bit(idx, BIT4_Z);
|
||||
tval.set_bit(idx, BIT4_Z);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported digit %c(%d).\n", ch, ch);
|
||||
assert(0);
|
||||
/* Return "x" if there are invalid digits in the string. */
|
||||
fprintf(stderr, "Warning: Invalid hex digit %c(%d) in "
|
||||
"\"%s\".\n", ch, ch, str);
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
val.set_bit(idx, BIT4_X);
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a negative value when needed. */
|
||||
if (str[0] == '-') {
|
||||
tval.invert();
|
||||
tval += (int64_t) 1;
|
||||
}
|
||||
|
||||
/* Find the correct padding value. */
|
||||
vvp_bit4_t pad;
|
||||
switch (tval.value(tval.size()-1)) {
|
||||
case BIT4_X: // Pad MSB 'x' with 'x'.
|
||||
pad = BIT4_X;
|
||||
break;
|
||||
case BIT4_Z: // Pad MSB 'z' with 'z'.
|
||||
pad = BIT4_Z;
|
||||
break;
|
||||
case BIT4_1: // If negative pad MSB '1' with '1'.
|
||||
if (str[0] == '-') {
|
||||
pad = BIT4_1;
|
||||
break;
|
||||
}
|
||||
default: // Everything else gets '0' padded.
|
||||
pad = BIT4_0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the temporary value to the real value, padding if needed. */
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
if (idx < tval.size()) val.set_bit(idx, tval.value(idx));
|
||||
else val.set_bit(idx, pad);
|
||||
}
|
||||
}
|
||||
|
||||
void vpip_vec4_to_hex_str(const vvp_vector4_t&bits, char*buf,
|
||||
|
|
|
|||
|
|
@ -33,29 +33,30 @@ extern const char oct_digits[64];
|
|||
void vpip_oct_str_to_vec4(vvp_vector4_t&val, const char*str)
|
||||
{
|
||||
unsigned str_len = strlen(str);
|
||||
|
||||
char pad = '0';
|
||||
switch (str[0]) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
pad = 'x';
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
pad = 'z';
|
||||
break;
|
||||
unsigned skip_chars = 0;
|
||||
const char*tstr = str;
|
||||
/* Find the number of non-numeric characters. */
|
||||
while ((tstr = strpbrk(tstr, "-_"))) {
|
||||
skip_chars += 1;
|
||||
tstr += 1;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
vvp_vector4_t tval(3*(str_len-skip_chars));
|
||||
skip_chars = 0;
|
||||
for (unsigned idx = 0 ; idx < tval.size() ; idx += 1) {
|
||||
unsigned tmp;
|
||||
unsigned bit_off = idx%3;
|
||||
unsigned str_off = idx/3;
|
||||
|
||||
char ch;
|
||||
if (str_off >= str_len)
|
||||
ch = pad;
|
||||
else
|
||||
ch = str[str_len-str_off-1];
|
||||
|
||||
assert(str_off+skip_chars < str_len);
|
||||
/* Skip any "_" characters in the string. */
|
||||
while ((ch = str[str_len-str_off-1-skip_chars]) == '_') {
|
||||
skip_chars += 1;
|
||||
assert(str_off+skip_chars < str_len);
|
||||
}
|
||||
|
||||
/* If we find a "-" it must be at the head of the string. */
|
||||
if (ch == '-') assert(0);
|
||||
|
||||
switch (ch) {
|
||||
case '0':
|
||||
|
|
@ -67,22 +68,59 @@ void vpip_oct_str_to_vec4(vvp_vector4_t&val, const char*str)
|
|||
case '6':
|
||||
case '7':
|
||||
tmp = ch - '0';
|
||||
val.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
tval.set_bit(idx, ((tmp>>bit_off)&1)? BIT4_1 : BIT4_0);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
val.set_bit(idx, BIT4_X);
|
||||
tval.set_bit(idx, BIT4_X);
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
val.set_bit(idx, BIT4_Z);
|
||||
tval.set_bit(idx, BIT4_Z);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported digit %c(%d).\n", ch, ch);
|
||||
assert(0);
|
||||
/* Return "x" if there are invalid digits in the string. */
|
||||
fprintf(stderr, "Warning: Invalid octal digit %c(%d) in "
|
||||
"\"%s\".\n", ch, ch, str);
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
val.set_bit(idx, BIT4_X);
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a negative value when needed. */
|
||||
if (str[0] == '-') {
|
||||
tval.invert();
|
||||
tval += (int64_t) 1;
|
||||
}
|
||||
|
||||
/* Find the correct padding value. */
|
||||
vvp_bit4_t pad;
|
||||
switch (tval.value(tval.size()-1)) {
|
||||
case BIT4_X: // Pad MSB 'x' with 'x'
|
||||
pad = BIT4_X;
|
||||
break;
|
||||
case BIT4_Z: // Pad MSB 'z' with 'z'
|
||||
pad = BIT4_Z;
|
||||
break;
|
||||
case BIT4_1: // If negative pad MSB '1' with '1'
|
||||
if (str[0] == '-') {
|
||||
pad = BIT4_1;
|
||||
break;
|
||||
}
|
||||
default: // Everything else gets '0' padded.
|
||||
pad = BIT4_0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the temporary value to the real value, padding if needed. */
|
||||
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
|
||||
if (idx < tval.size()) val.set_bit(idx, tval.value(idx));
|
||||
else val.set_bit(idx, pad);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf, unsigned nbuf,
|
||||
|
|
|
|||
|
|
@ -220,26 +220,74 @@ unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void vpip_dec_str_to_vec4(vvp_vector4_t&vec,
|
||||
const char*buf, bool signed_flag)
|
||||
void vpip_dec_str_to_vec4(vvp_vector4_t&vec, const char*buf)
|
||||
{
|
||||
/* Support for [xX]_*. */
|
||||
if (buf[0] == 'x' || buf[0] == 'X') {
|
||||
for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
|
||||
vec.set_bit(idx, BIT4_X);
|
||||
}
|
||||
const char*tbuf = buf+1;
|
||||
/* See if this is a valid constant. */
|
||||
while (*tbuf) {
|
||||
if (*tbuf != '_') {
|
||||
fprintf(stderr, "Warning: Invalid decimal \"x\" "
|
||||
"value \"%s\".\n", buf);
|
||||
return;
|
||||
}
|
||||
tbuf += 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Support for [zZ]_*. */
|
||||
if (buf[0] == 'z' || buf[0] == 'Z') {
|
||||
const char*tbuf = buf+1;
|
||||
/* See if this is a valid constant, if not return "x". */
|
||||
while (*tbuf) {
|
||||
if (*tbuf != '_') {
|
||||
fprintf(stderr, "Warning: Invalid decimal \"z\" "
|
||||
"value \"%s\".\n", buf);
|
||||
for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
|
||||
vec.set_bit(idx, BIT4_X);
|
||||
}
|
||||
return;
|
||||
}
|
||||
tbuf += 1;
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
|
||||
vec.set_bit(idx, BIT4_Z);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* The str string is the decimal value with the least
|
||||
significant digit first. This loop creates that string by
|
||||
reversing the order of the buf string. For example, if the
|
||||
input is "1234", str gets "4321". */
|
||||
unsigned slen = strlen(buf);
|
||||
char*str = new char[slen + 1];
|
||||
int is_negative = 0;
|
||||
bool is_negative = false;
|
||||
for (unsigned idx = 0 ; idx < slen ; idx += 1) {
|
||||
if (idx == slen-1 && buf[slen-idx-1] == '-') {
|
||||
is_negative = 1;
|
||||
is_negative = true;
|
||||
slen--;
|
||||
continue;
|
||||
}
|
||||
while (buf[slen-idx-1] == '_') {
|
||||
slen--;
|
||||
}
|
||||
if (isdigit(buf[slen-idx-1]))
|
||||
str[idx] = buf[slen-idx-1];
|
||||
else
|
||||
str[idx] = '0';
|
||||
else {
|
||||
/* Return "x" if there are invalid digits in the string. */
|
||||
fprintf(stderr, "Warning: Invalid decimal digit %c(%d) in "
|
||||
"\"%s.\"\n", buf[slen-idx-1], buf[slen-idx-1], buf);
|
||||
for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
|
||||
vec.set_bit(idx, BIT4_X);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
str[slen] = 0;
|
||||
|
|
@ -274,7 +322,7 @@ void vpip_dec_str_to_vec4(vvp_vector4_t&vec,
|
|||
|
||||
if (is_negative) {
|
||||
vec.invert();
|
||||
vec += 1;
|
||||
vec += (int64_t) 1;
|
||||
}
|
||||
|
||||
delete[]str;
|
||||
|
|
|
|||
|
|
@ -2730,14 +2730,18 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
assert(thr->fork_count > 0);
|
||||
|
||||
if (thr->wt_context != thr->rd_context) {
|
||||
/* Pop the child context from the write context stack. */
|
||||
vvp_context_t child_context = thr->wt_context;
|
||||
thr->wt_context = vvp_get_stacked_context(child_context);
|
||||
/* If the child thread is in an automatic scope... */
|
||||
if (thr->child->wt_context) {
|
||||
/* and is the top level task/function thread... */
|
||||
if (thr->wt_context != thr->rd_context) {
|
||||
/* Pop the child context from the write context stack. */
|
||||
vvp_context_t child_context = thr->wt_context;
|
||||
thr->wt_context = vvp_get_stacked_context(child_context);
|
||||
|
||||
/* Push the child context onto the read context stack */
|
||||
vvp_set_stacked_context(child_context, thr->rd_context);
|
||||
thr->rd_context = child_context;
|
||||
/* Push the child context onto the read context stack */
|
||||
vvp_set_stacked_context(child_context, thr->rd_context);
|
||||
thr->rd_context = child_context;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the child has already ended, reap it now. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue