Merge branch 'master' into verilog-ams

This commit is contained in:
Stephen Williams 2008-11-16 18:42:06 -08:00
commit e98f29e96f
42 changed files with 1094 additions and 495 deletions

View File

@ -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
View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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
View File

@ -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. */

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.
*
*/

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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:

View File

@ -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) {

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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.
*
*/

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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. */