Merge branch 'master' into verilog-ams

This commit is contained in:
Stephen Williams 2008-11-28 16:29:50 -08:00
commit 17b937740a
38 changed files with 598 additions and 145 deletions

View File

@ -60,7 +60,7 @@ bindir = @bindir@
libdir = @libdir@
# This is actually the directory where we install our own header files.
# It is a little different from the generic includedir.
includedir = @includedir@/verilog$(suffix)
includedir = @includedir@/iverilog$(suffix)
mandir = @mandir@
dllib=@DLLIB@
@ -166,7 +166,7 @@ SUBDIRS += driver-vpi
else
all: dep iverilog-vpi
iverilog-vpi: iverilog-vpi.sh
iverilog-vpi: iverilog-vpi.sh Makefile
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@SUFFIX@;$(suffix);' \
-e 's;@IVCC@;$(CC);' \

View File

@ -95,11 +95,29 @@ PEBLogic::~PEBLogic()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
PEBLeftWidth::PEBLeftWidth(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBLeftWidth::~PEBLeftWidth()
{
}
PEBPower::PEBPower(char op, PExpr*l, PExpr*r)
: PEBLeftWidth(op, l, r)
{
}
PEBPower::~PEBPower()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
: PEBLeftWidth(op, l, r)
{
}
PEBShift::~PEBShift()
{
}

47
PExpr.h
View File

@ -535,18 +535,51 @@ class PEBLogic : public PEBinary {
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
};
class PEBShift : public PEBinary {
/*
* A couple of the binary operands have a special sub-expression rule
* where the expression width is carried entirely by the left
* expression, and the right operand is self-determined.
*/
class PEBLeftWidth : public PEBinary {
public:
explicit PEBLeftWidth(char op, PExpr*l, PExpr*r);
~PEBLeftWidth() =0;
virtual NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const =0;
protected:
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag);
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*scope) const;
};
class PEBPower : public PEBLeftWidth {
public:
explicit PEBPower(char op, PExpr*l, PExpr*r);
~PEBPower();
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const;
};
class PEBShift : public PEBLeftWidth {
public:
explicit PEBShift(char op, PExpr*l, PExpr*r);
~PEBShift();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const;
};
/*

View File

@ -22,10 +22,12 @@
# include "PGenerate.h"
# include "PWire.h"
# include "ivl_assert.h"
PGenerate::PGenerate(unsigned id)
: id_number(id)
{
direct_nested_ = false;
parent = 0;
lexical_scope = 0;
}
@ -38,3 +40,75 @@ void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
void PGenerate::probe_for_direct_nesting_(void)
{
direct_nested_ = false;
ivl_assert(*this, scheme_type==GS_CASE_ITEM || scheme_type==GS_CONDIT || scheme_type==GS_ELSE);
// If this scheme has received an explicit name, then it
// cannot be direct nested.
if (scope_name[0] != '$') return;
if (tasks.size() > 0) return;
if (funcs.size() > 0) return;
if (gates.size() > 0) return;
if (parameters.size() > 0) return;
if (localparams.size() > 0) return;
if (events.size() > 0) return;
if (wires.size() > 0) return;
if (behaviors.size() > 0) return;
if (analog_behaviors.size() > 0) return;
if (generate_schemes.size() == 0) return;
switch (generate_schemes.size()) {
case 1: {
PGenerate*child = generate_schemes.front();
if (child->scheme_type == GS_CONDIT)
direct_nested_ = true;
if (child->scheme_type == GS_CASE)
direct_nested_ = true;
break;
}
case 2: {
PGenerate*child1 = generate_schemes.front();
PGenerate*child2 = generate_schemes.back();
if (child1->scheme_type==GS_CONDIT && child2->scheme_type==GS_ELSE)
direct_nested_ = true;
if (child2->scheme_type==GS_CONDIT && child1->scheme_type==GS_ELSE)
direct_nested_ = true;
break;
}
}
}
ostream& operator << (ostream&out, PGenerate::scheme_t type)
{
switch (type) {
case PGenerate::GS_NONE:
out << "GS_NONE";
break;
case PGenerate::GS_LOOP:
out << "GS_LOOP";
break;
case PGenerate::GS_CONDIT:
out << "GS_CONDIT";
break;
case PGenerate::GS_ELSE:
out << "GS_ELSE";
break;
case PGenerate::GS_CASE:
out << "GS_CASE";
break;
case PGenerate::GS_CASE_ITEM:
out << "GS_CASE_ITEM";
break;
case PGenerate::GS_NBLOCK:
out << "GS_NBLOCK";
break;
}
return out;
}

View File

@ -25,6 +25,7 @@
# include "PScope.h"
# include <list>
# include <map>
# include <valarray>
# include "pform_types.h"
class Design;
@ -74,6 +75,10 @@ class PGenerate : public LineInfo, public LexicalScope {
PExpr*loop_init;
PExpr*loop_test;
PExpr*loop_step;
// Case items may have multiple guard expression values. It is
// enough for any on of the guards to match the case statement
// test value.
std::valarray<PExpr*> item_test;
list<PGate*> gates;
void add_gate(PGate*);
@ -104,18 +109,30 @@ class PGenerate : public LineInfo, public LexicalScope {
bool generate_scope_case_(Design*des, NetScope*container);
bool generate_scope_nblock_(Design*des, NetScope*container);
// Call probe during elaborate_scope to calulate the
// directed_nested_ flag. It is OK to store the direct_nested_
// information here because "direct nested" is a property of
// the lexical generate code.
void probe_for_direct_nesting_(void);
bool direct_nested_;
// Elaborate_scope within a generated scope.
void elaborate_subscope_(Design*des, NetScope*scope);
void elaborate_subscope_direct_(Design*des, NetScope*scope);
// These are the scopes created by generate_scope.
list<NetScope*>scope_list_;
// internal function called on each scope generated by this scheme.
bool elaborate_sig_(Design*des, NetScope*scope) const;
bool elaborate_sig_direct_(Design*des, NetScope*scope) const;
bool elaborate_(Design*des, NetScope*scope) const;
bool elaborate_direct_(Design*des, NetScope*scope) const;
private: // not implemented
PGenerate(const PGenerate&);
PGenerate& operator= (const PGenerate&);
};
extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t);
#endif

View File

@ -514,7 +514,7 @@ static void setup_ivl_environment()
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I");
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS,"\\include\\\\verilog" IVERILOG_SUFFIX);
append(&gstr.pCFLAGS,"\\include\\\\iverilog" IVERILOG_SUFFIX);
/* Build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L");

View File

@ -214,6 +214,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope,
case 'G': // >= Should be handled by PEBComp
case 'n': // != Should be handled by PEBComp
case 'N': // !== Should be handled by PEBComp
case 'p': // ** should be handled by PEBPower
ivl_assert(*this, 0);
default:
if (wid_left > min)
@ -352,14 +353,15 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
tmp = elaborate_expr_base_div_(des, lp, rp, expr_wid);
break;
case 'l': // <<
tmp = elaborate_expr_base_lshift_(des, lp, rp, expr_wid);
break;
case 'r': // >>
case 'R': // >>>
tmp = elaborate_expr_base_rshift_(des, lp, rp, expr_wid);
break;
case 'l':
case 'r':
case 'R':
cerr << get_fileline() << ": internal error: "
<< "Elaboration of " << human_readable_op(op_)
<< " Should have been handled in NetEBShift::elaborate."
<< endl;
des->errors += 1;
return 0;
case '^':
case '&':
@ -898,12 +900,12 @@ NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
return tmp;
}
unsigned PEBShift::test_width(Design*des, NetScope*scope,
unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
unsigned wid_left = left_->test_width(des,scope,min, 0, expr_type__, unsized_flag);
unsigned wid_left = left_->test_width(des,scope,min, lval, expr_type__, unsized_flag);
// The right expression is self-determined and has no impact
// on the expression size that is generated.
@ -913,12 +915,15 @@ unsigned PEBShift::test_width(Design*des, NetScope*scope,
if (wid_left < lval)
wid_left = lval;
if (unsized_flag && wid_left < integer_width) {
if (unsized_flag
&& type_is_vectorable(expr_type__)
&& wid_left > 0
&& wid_left < integer_width) {
wid_left = integer_width;
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Test width of unsized left shift"
<< "Test width of unsized " << human_readable_op(op_)
<< " is padded to compiler integer width=" << wid_left
<< endl;
}
@ -934,20 +939,28 @@ unsigned PEBShift::test_width(Design*des, NetScope*scope,
unsigned wid_right = right_->test_width(des, scope, 0, 0, rtype, rflag);
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Test width of shift amount of shift expression "
<< "Test width of exponent of " << op_ << " expression "
<< "returns wid=" << wid_right << ", type=" << rtype
<< ", flag=" << rflag << endl;
return expr_width_;
}
NetExpr*PEBShift::elaborate_expr(Design*des, NetScope*scope,
NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool sys_task_arg) const
{
assert(left_);
assert(right_);
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, false);
if (expr_wid > 0 && lp->expr_width() < (unsigned)expr_wid) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Pad left operand of " << human_readable_op(op_)
<< " to " << expr_wid << "." << endl;
lp = pad_to_width(lp, expr_wid, *this);
}
NetExpr*rp = right_->elaborate_expr(des, scope, -1, false);
if ((lp == 0) || (rp == 0)) {
delete lp;
@ -955,7 +968,48 @@ NetExpr*PEBShift::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
NetExpr*tmp = elaborate_eval_expr_base_(des, lp, rp, expr_wid);
eval_expr(lp);
eval_expr(rp);
return elaborate_expr_leaf(des, lp, rp, expr_wid);
}
NetExpr*PEBPower::elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const
{
if (debug_elaborate) {
cerr << get_fileline() << ": debug: elaborate expression "
<< *this << " expr_wid=" << expr_wid << endl;
}
NetExpr*tmp = new NetEBPow(op_, lp, rp);
tmp->set_line(*this);
return tmp;
}
NetExpr*PEBShift::elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const
{
NetExpr*tmp = 0;
switch (op_) {
case 'l':
tmp = elaborate_expr_base_lshift_(des, lp, rp, expr_wid);
break;
case 'r': // >>
case 'R': // >>>
tmp = elaborate_expr_base_rshift_(des, lp, rp, expr_wid);
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Unexpected opcode " << human_readable_op(op_)
<< " in PEBShift::elaborate_expr_leaf." << endl;
des->errors += 1;
}
return tmp;
}
@ -1682,6 +1736,7 @@ NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
ivl_assert(*this, index_tail.lsb != 0);
ivl_assert(*this, index_tail.msb != 0);
probe_expr_width(des, scope, index_tail.msb);
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1);
return tmp;
}
@ -1756,6 +1811,11 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
break;
}
case index_component_t::SEL_BIT:
{ ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb);
probe_expr_width(des, scope, index_tail.msb);
}
use_width = 1;
break;
default:
@ -2928,7 +2988,6 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope,
bool flag = false;
expr_->test_width(des, scope, 0, 0, sub_type, flag);
expr_type_ = sub_type;
ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE);
}
expr_width_ = 1;
@ -2976,6 +3035,8 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
NetExpr*ip = expr_->elaborate_expr(des, scope, expr_wid, false);
if (ip == 0) return 0;
ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE);
NetExpr*tmp;
switch (op_) {
default:

View File

@ -81,6 +81,20 @@ NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
return tmp;
}
NetExpr*PEBLeftWidth::elaborate_pexpr (Design*des, NetScope*scope) const
{
NetExpr*lp = left_->elaborate_pexpr(des, scope);
NetExpr*rp = right_->elaborate_pexpr(des, scope);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
return 0;
}
NetExpr*tmp = elaborate_expr_leaf(des, lp, rp, -2);
return tmp;
}
NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const
{
NetExpr*lp = left_->elaborate_pexpr(des, scope);

View File

@ -114,6 +114,7 @@ static void elaborate_parm_item_(perm_string name,
tmp->high_open_flag = range->high_open_flag;
if (range->low_expr) {
probe_expr_width(des, scope, range->low_expr);
tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1);
ivl_assert(*range->low_expr, tmp->low_expr);
} else {
@ -130,6 +131,7 @@ static void elaborate_parm_item_(perm_string name,
tmp->high_expr = tmp->low_expr;
} else if (range->high_expr) {
probe_expr_width(des, scope, range->high_expr);
tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1);
ivl_assert(*range->high_expr, tmp->high_expr);
} else {
@ -493,6 +495,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other parameter value is evaluated.
probe_expr_width(des, container, loop_init);
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
@ -522,6 +525,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = genvar;
probe_expr_width(des, container, loop_test);
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
if (test == 0) {
@ -574,6 +578,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
elaborate_subscope_(des, scope);
// Calculate the step for the loop variable.
probe_expr_width(des, container, loop_step);
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
if (step == 0) {
@ -590,6 +595,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
probe_expr_width(des, container, loop_test);
test_ex = elab_and_eval(des, container, loop_test, -1);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
@ -604,6 +610,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
{
probe_expr_width(des, container, loop_test);
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
if (test == 0) {
@ -634,14 +641,26 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
<< " value=" << test->value() << ": Generate scope="
<< use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
probe_for_direct_nesting_();
if (direct_nested_) {
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
<< " detected direct nesting." << endl;
elaborate_subscope_direct_(des, container);
return true;
}
// If this is not directly nested, then generate a scope
// for myself. That is what I will pass to the subscope.
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
elaborate_subscope_(des, scope);
@ -651,6 +670,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
probe_expr_width(des, container, loop_test);
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
if (case_value_co == 0) {
@ -673,24 +693,32 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
// Detect that the item is a default.
if (item->loop_test == 0) {
if (item->item_test.size() == 0) {
default_item = item;
cur ++;
continue;
}
NetExpr*item_value_ex = elab_and_eval(des, container, item->loop_test, -1);
bool match_flag = false;
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
probe_expr_width(des, container, item->item_test[idx]);
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
assert(item_value_co);
// If we stumble on the item that matches, then break
// out now.
if (case_value_co->value() == item_value_co->value()) {
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case "
<< "item value=" << item_value_co->value() << endl;
if (case_value_co->value() == item_value_co->value())
match_flag = true;
delete item_value_co;
break;
}
delete item_value_co;
// If we stumble on the item that matches, then break out now.
if (match_flag)
break;
cur ++;
}
@ -712,6 +740,15 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
// The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name);
item->probe_for_direct_nesting_();
if (item->direct_nested_) {
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case item " << scope_name
<< " detected direct nesting." << endl;
item->elaborate_subscope_direct_(des, container);
return true;
}
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
@ -743,6 +780,15 @@ bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
return true;
}
void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
{
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
}
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
// Scan the generated scope for nested generate schemes,
@ -785,6 +831,10 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
if (debug_scopes)
cerr << get_fileline() << ": debug: Generated scope " << scope_path(scope)
<< " by generate block " << scope_name << endl;
// Save the scope that we created, for future use.
scope_list_.push_back(scope);
}
@ -900,6 +950,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
*/
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
{
if (msb_) probe_expr_width(des, sc, msb_);
if (lsb_) probe_expr_width(des, sc, lsb_);
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);

View File

@ -412,6 +412,9 @@ bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
{
if (direct_nested_)
return elaborate_sig_direct_(des, container);
bool flag = true;
// Handle the special case that this is a CASE scheme. In this
@ -428,7 +431,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
if (item->direct_nested_ || !item->scope_list_.empty()) {
flag &= item->elaborate_sig(des, container);
}
}
@ -454,6 +457,32 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
return flag;
}
bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
{
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Direct nesting " << scope_name
<< " (scheme_type=" << scheme_type << ")"
<< " elaborate_sig in scope "
<< scope_path(container) << "." << endl;
// Elaborate_sig for a direct nested generated scheme knows
// that there are only sub_schemes to be elaborated. There
// should be exactly 1 active generate scheme, search for it
// using this loop.
bool flag = true;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
PGenerate*item = *cur;
if (item->direct_nested_ || !item->scope_list_.empty()) {
// Found the item, and it is direct nested.
flag &= item->elaborate_sig(des, container);
}
}
return flag;
}
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
@ -530,6 +559,9 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_REG:
case PTF_REG_S:
if (return_type_.range) {
probe_expr_width(des, scope, (*return_type_.range)[0]);
probe_expr_width(des, scope, (*return_type_.range)[1]);
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1);
assert(me);
@ -823,6 +855,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
bool bad_lsb = false, bad_msb = false;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && port_msb_ != 0) {
probe_expr_width(des, scope, port_msb_);
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
if (! eval_as_long(pmsb, texpr)) {
@ -837,6 +870,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr;
probe_expr_width(des, scope, port_lsb_);
texpr = elab_and_eval(des, scope, port_lsb_, -1);
if (! eval_as_long(plsb, texpr)) {
@ -859,6 +893,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
/* If they exist get the net/etc. definition MSB and LSB */
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
probe_expr_width(des, scope, net_msb_);
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
if (! eval_as_long(nmsb, texpr)) {
@ -873,6 +908,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr;
probe_expr_width(des, scope, net_lsb_);
texpr = elab_and_eval(des, scope, net_lsb_, -1);
if (! eval_as_long(nlsb, texpr)) {
@ -964,6 +1000,9 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
probe_expr_width(des, scope, lidx_);
probe_expr_width(des, scope, ridx_);
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);

View File

@ -700,7 +700,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
const PExpr*ex = pin(idx);
PExpr*ex = pin(idx);
if (ex == 0) {
cerr << get_fileline() << ": error: Logic gate port "
"expressions are not optional." << endl;
@ -713,6 +713,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
} else {
unsigned use_width = array_count * instance_width;
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
bool flag = false;
ex->test_width(des, scope, 0, use_width, tmp_type, flag);
NetExpr*tmp = elab_and_eval(des, scope, ex,
use_width, use_width);
sig = tmp->synthesize(des, scope);
@ -1171,10 +1174,14 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
width. We use that, then, to decide how to hook
it up.
v NOTE that this also handles the case that the
NOTE that this also handles the case that the
port is actually empty on the inside. We assume
in that case that the port is input. */
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
bool flag = false;
pins[idx]->test_width(des, scope, 0, desired_vector_width,
tmp_type, flag);
NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx],
desired_vector_width,
desired_vector_width);
@ -1790,6 +1797,7 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
*/
static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
{
probe_expr_width(des, scope, expr);
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* If the delay expression is a real constant or vector
@ -2280,17 +2288,8 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: Elaborate condition statement"
<< " with conditional: " << *expr_ << endl;
// Run a test-width on the condition so that its types are
// worked out for elaboration later on.
ivl_variable_type_t rtype = IVL_VT_NO_TYPE;
bool rflag = false;
unsigned expr_wid = expr_->test_width(des, scope, 0, 0, rtype, rflag);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Test width of condition expression"
<< " returns wid=" << expr_wid << ", type=" << rtype
<< ", flag=" << rflag << endl;
// Elaborate and try to evaluate the conditional expression.
probe_expr_width(des, scope, expr_);
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
cerr << get_fileline() << ": error: Unable to elaborate"
@ -2545,6 +2544,10 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
NetAssign_*lv = new NetAssign_(port);
unsigned wid = count_lval_width(lv);
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
bool flag = false;
parms_[idx]->test_width(des, scope, 0, wid, tmp_type, flag);
NetExpr*rv = elab_and_eval(des, scope, parms_[idx], wid);
rv->set_width(wid);
rv = pad_to_width(rv, wid, *this);
@ -2650,8 +2653,9 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
return 0;
unsigned lwid = count_lval_width(lval);
ivl_variable_type_t ltype = lval->expr_type();
NetExpr*rexp = elab_and_eval(des, scope, expr_, lwid);
NetExpr*rexp = elaborate_rval_expr(des, scope, ltype, lwid, expr_);
if (rexp == 0)
return 0;
@ -2954,6 +2958,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
bool save_flag = error_implicit;
error_implicit = true;
probe_expr_width(des, scope, expr_[idx]->expr());
NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), 0);
if (tmp == 0) {
expr_[idx]->dump(cerr);
@ -3054,10 +3059,12 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
return 0;
}
const PExpr *pe = expr_[0]->expr();
PExpr *pe = expr_[0]->expr();
/* Elaborate wait expression. Don't eval yet, we will do that
shortly, after we apply a reduction or. */
probe_expr_width(des, scope, pe);
NetExpr*expr = pe->elaborate_expr(des, scope, -1, false);
if (expr == 0) {
cerr << get_fileline() << ": error: Unable to elaborate"
@ -3248,8 +3255,9 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
return 0;
unsigned lwid = count_lval_width(lval);
ivl_variable_type_t ltype = lval->expr_type();
NetExpr*rexp = elab_and_eval(des, scope, expr_, lwid);
NetExpr*rexp = elaborate_rval_expr(des, scope, ltype, lwid, expr_);
if (rexp == 0)
return 0;
@ -3379,6 +3387,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
/* Elaborate the condition expression. Try to evaluate it too,
in case it is a constant. This is an interesting case
worthy of a warning. */
probe_expr_width(des, scope, cond_);
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
if (ce == 0) {
delete top;
@ -3591,8 +3600,9 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
*/
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
{
NetWhile*loop = new NetWhile(elab_and_eval(des, scope, cond_, -1),
statement_->elaborate(des, scope));
probe_expr_width(des, scope, cond_);
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
NetWhile*loop = new NetWhile(tmp, statement_->elaborate(des, scope));
return loop;
}
@ -3683,6 +3693,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
them for the timescale/precision of the scope. */
for (unsigned idx = 0 ; idx < ndelays ; idx += 1) {
PExpr*exp = delays[idx];
probe_expr_width(des, scope, exp);
NetExpr*cur = elab_and_eval(des, scope, exp, 0);
if (NetEConst*cur_con = dynamic_cast<NetEConst*> (cur)) {
@ -3720,6 +3731,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
NetNet*condit_sig = 0;
if (conditional && condition) {
probe_expr_width(des, scope, condition);
NetExpr*tmp = elab_and_eval(des, scope, condition, -1);
ivl_assert(*condition, tmp);
@ -3962,6 +3974,9 @@ bool Module::elaborate(Design*des, NetScope*scope) const
bool PGenerate::elaborate(Design*des, NetScope*container) const
{
if (direct_nested_)
return elaborate_direct_(des, container);
bool flag = true;
// Handle the special case that this is a CASE scheme. In this
@ -3978,7 +3993,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
if (item->direct_nested_ || !item->scope_list_.empty()) {
flag &= item->elaborate(des, container);
}
}
@ -4016,6 +4031,30 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
return flag;
}
bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
{
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Direct nesting elaborate in scope "
<< scope_path(container) << "." << endl;
// Elaborate for a direct nested generated scheme knows
// that there are only sub_schemes to be elaborated. There
// should be exactly 1 active generate scheme, search for it
// using this loop.
bool flag = true;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
PGenerate*item = *cur;
if (item->direct_nested_ || !item->scope_list_.empty()) {
// Found the item, and it is direct nested.
flag &= item->elaborate(des, container);
}
}
return flag;
}
bool PGenerate::elaborate_(Design*des, NetScope*scope) const
{
elaborate_functions(des, scope, funcs);

View File

@ -18,12 +18,9 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.18 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
VERSION = 0.9.devel
suffix = @install_suffix@

View File

@ -16,9 +16,6 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.36 2007/02/06 05:07:32 steve Exp $"
#
#
SHELL = /bin/sh
suffix = @install_suffix@

View File

@ -250,6 +250,13 @@ NetExpr* condition_reduce(NetExpr*expr)
return cmp;
}
void probe_expr_width(Design*des, NetScope*scope, PExpr*pe)
{
ivl_variable_type_t expr_type = IVL_VT_NO_TYPE;
bool flag = false;
pe->test_width(des, scope, 0, 0, expr_type, flag);
}
NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid, int prune_width)
{
@ -398,6 +405,7 @@ const char *human_readable_op(const char op)
case 'r': type = ">>"; break; // Logical right shift
case 'R': type = ">>>"; break; // Arithmetic right shift
case 'p': type = "**"; break; // Power
default:
assert(0);
}

View File

@ -154,6 +154,8 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid,
int prune_width =-1);
void probe_expr_width(Design*des, NetScope*scope, PExpr*pe);
/*
* This function elaborates an expression as if it is for the r-value
* of an assignment, The data_type_lv and expr_wid_lv are the type and

View File

@ -929,7 +929,7 @@ expression
$$ = tmp;
}
| expression K_POW expression
{ PEBinary*tmp = new PEBinary('p', $1, $3);
{ PEBinary*tmp = new PEBPower('p', $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
@ -2321,7 +2321,7 @@ generate_case_items
;
generate_case_item
: expression ':' { pform_generate_case_item(@1, $1); } generate_block_opt
: expression_list_proper ':' { pform_generate_case_item(@1, $1); } generate_block_opt
{ pform_endgenerate(); }
| K_default ':' { pform_generate_case_item(@1, 0); } generate_block_opt
{ pform_endgenerate(); }

View File

@ -558,7 +558,7 @@ void pform_start_generate_nblock(const struct vlltype&li, char*name)
* case schema can only instantiate exactly one item, so the items
* need not have a unique number.
*/
void pform_generate_case_item(const struct vlltype&li, PExpr*expr)
void pform_generate_case_item(const struct vlltype&li, svector<PExpr*>*expr_list)
{
assert(pform_cur_generate);
assert(pform_cur_generate->scheme_type == PGenerate::GS_CASE);
@ -573,8 +573,14 @@ void pform_generate_case_item(const struct vlltype&li, PExpr*expr)
pform_cur_generate->scheme_type = PGenerate::GS_CASE_ITEM;
pform_cur_generate->loop_init = 0;
pform_cur_generate->loop_test = expr;
pform_cur_generate->loop_test = 0;
pform_cur_generate->loop_step = 0;
if (expr_list != 0) {
pform_cur_generate->item_test.resize(expr_list->count());
for (unsigned idx = 0 ; idx < expr_list->count() ; idx += 1)
pform_cur_generate->item_test[idx] = expr_list[0][idx];
}
}
void pform_generate_block_name(char*name)

View File

@ -205,7 +205,7 @@ 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_case_item(const struct vlltype&lp, svector<PExpr*>*test);
extern void pform_generate_block_name(char*name);
extern void pform_endgenerate();

View File

@ -17,12 +17,9 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.16 2004/02/10 19:25:01 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
VERSION = 0.9.devel
suffix = @install_suffix@

View File

@ -16,12 +16,9 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.11 2004/02/10 19:25:01 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
VERSION = 0.9.devel
prefix = @prefix@
exec_prefix = @exec_prefix@

View File

@ -16,12 +16,9 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.12 2004/02/10 19:25:01 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
VERSION = 0.9.devel
prefix = @prefix@
exec_prefix = @exec_prefix@

View File

@ -18,7 +18,7 @@
#
SHELL = /bin/sh
VERSION = 0.0
VERSION = 0.9.devel
suffix = @install_suffix@
@ -38,7 +38,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = -I. -I.. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ @PICFLAG@
CXXFLAGS = -Wall @CXXFLAGS@
LDFLAGS = @LDFLAGS@

View File

@ -115,7 +115,9 @@ static vhdl_expr *part_select_vp_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
if (NULL == off)
return NULL;
if (selfrom->get_type()->get_width() > 1)
selfrom->set_slice(off, ivl_lpm_width(lpm) - 1);
return selfrom;
}

View File

@ -139,7 +139,7 @@ static vhdl_var_ref *make_assign_lhs(ivl_lval_t lval, vhdl_scope *scope)
if (base) {
if (decl->get_type()->get_name() == VHDL_TYPE_ARRAY)
lval_ref->set_slice(base, 0);
else
else if (ivl_signal_width(sig) > 1)
lval_ref->set_slice(base, lval_width - 1);
}

View File

@ -40,7 +40,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = -I. -I.. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@

View File

@ -1469,8 +1469,13 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
break;
case 'p':
fprintf(vvp_out, " %%pow%s %u, %u, %u;\n", sign_string,
if (ivl_expr_signed(le) || ivl_expr_signed(re)) {
fprintf(vvp_out, " %%pow/s %u, %u, %u;\n",
lv.base, rv.base, wid);
} else {
fprintf(vvp_out, " %%pow %u, %u, %u;\n",
lv.base, rv.base, wid);
}
break;
default:

View File

@ -53,7 +53,15 @@ __inline__ static void draw_execute_header(ivl_design_t des)
fprintf(vvp_out, "#! %s\n", cp);
fchmod(fileno(vvp_out), 0755);
}
#else
fprintf(vvp_out, "# MinGW does not support an executable header.\n");
#endif
fprintf(vvp_out, ":ivl_version \"" VERSION "\"");
/* I am assuming that a base release will have a blank tag. */
if (strcmp(VERSION_TAG, "") != 0) {
fprintf(vvp_out, " \"(" VERSION_TAG ")\"");
}
fprintf(vvp_out, ";\n");
}
__inline__ static void draw_module_declarations(ivl_design_t des)

View File

@ -76,13 +76,16 @@ rm -rf $RPM_BUILD_ROOT
%attr(-,root,root) %{_libdir}/libveriuser.a
%attr(-,root,root) %{_libdir}/ivl/include/constants.vams
%attr(-,root,root) %{_libdir}/ivl/include/disciplines.vams
%attr(-,root,root) /usr/include/verilog/ivl_target.h
%attr(-,root,root) /usr/include/verilog/vpi_user.h
%attr(-,root,root) /usr/include/verilog/acc_user.h
%attr(-,root,root) /usr/include/verilog/veriuser.h
%attr(-,root,root) /usr/include/verilog/_pli_types.h
%attr(-,root,root) /usr/include/iverilog/ivl_target.h
%attr(-,root,root) /usr/include/iverilog/vpi_user.h
%attr(-,root,root) /usr/include/iverilog/acc_user.h
%attr(-,root,root) /usr/include/iverilog/veriuser.h
%attr(-,root,root) /usr/include/iverilog/_pli_types.h
%changelog -n verilog
* Tue Nov 25 2008 - steve@icarus.com
- Move header files frim /verilog/ to /iverilog/
* Tue Nov 18 2008 - steve@icarus.com
- New snapshot 20080905

View File

@ -727,12 +727,28 @@ ostream& operator<< (ostream&o, const verinum&v)
verinum::V operator == (const verinum&left, const verinum&right)
{
if (left.len() != right.len())
return verinum::V0;
verinum::V left_pad = verinum::V0;
verinum::V right_pad = verinum::V0;
if (left.has_sign() && right.has_sign()) {
left_pad = left.get(left.len()-1);
right_pad = right.get(right.len()-1);
for (unsigned idx = 0 ; idx < left.len() ; idx += 1)
if (left[idx] != right[idx])
if (left_pad == verinum::V1 && right_pad == verinum::V0)
return verinum::V1;
if (left_pad == verinum::V0 && right_pad == verinum::V1)
return verinum::V0;
}
unsigned max_len = left.len();
if (right.len() > max_len)
max_len = right.len();
for (unsigned idx = 0 ; idx < max_len ; idx += 1) {
verinum::V left_bit = idx < left.len() ? left[idx] : left_pad;
verinum::V right_bit = idx < right.len()? right[idx] : right_pad;
if (left_bit != right_bit)
return verinum::V0;
}
return verinum::V1;
}

View File

@ -16,12 +16,9 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.73 2007/02/06 05:07:32 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
VERSION = 0.9.devel
suffix = @install_suffix@

View File

@ -135,6 +135,7 @@ extern bool of_NORR(vthread_t thr, vvp_code_t code);
extern bool of_OR(vthread_t thr, vvp_code_t code);
extern bool of_ORR(vthread_t thr, vvp_code_t code);
extern bool of_POW(vthread_t thr, vvp_code_t code);
extern bool of_POW_S(vthread_t thr, vvp_code_t code);
extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);

View File

@ -178,6 +178,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pow/s", of_POW_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%pow/wr", of_POW_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },

View File

@ -32,6 +32,7 @@
%%
/* These are some special header/footer keywords. */
^":ivl_version" { return K_ivl_version; }
^":vpi_module" { return K_vpi_module; }
^":vpi_time_precision" { return K_vpi_time_precision; }
^":file_names" { return K_file_names; }

View File

@ -133,6 +133,62 @@ inline static void print_rusage(struct rusage *, struct rusage *){};
#endif // ! defined(HAVE_SYS_RESOURCE_H)
static bool have_ivl_version = false;
/*
* Verify that the input file has a compatible version.
*/
void verify_version(char*ivl_ver, char*commit)
{
have_ivl_version = true;
if (verbose_flag) {
vpi_mcd_printf(1, " ... VVP file version %s", ivl_ver);
if (commit) vpi_mcd_printf(1, " %s", commit);
vpi_mcd_printf(1, "\n");
}
free(commit);
char*vvp_ver = strdup(VERSION);
char *vp, *ip;
/* Check the major/minor version. */
ip = strrchr(ivl_ver, '.');
*ip = '\0';
vp = strrchr(vvp_ver, '.');
*vp = '\0';
if (strcmp(ivl_ver, vvp_ver) != 0) {
vpi_mcd_printf(1, "Error: VVP input file version %s can not "
"be run with run time version %s!\n",
ivl_ver, vvp_ver);
exit(1);
}
/* Check that the sub-version is compatible. */
ip += 1;
vp += 1;
int ivl_sv, vvp_sv;
if (strcmp(ip, "devel") == 0) {
ivl_sv = -1;
} else {
int res = sscanf(ip, "%d", &ivl_sv);
assert(res == 1);
}
if (strcmp(vp, "devel") == 0) {
vvp_sv = -1;
} else {
int res = sscanf(vp, "%d", &vvp_sv);
assert(res == 1);
}
if (ivl_sv > vvp_sv) {
if (verbose_flag) vpi_mcd_printf(1, " ... ");
vpi_mcd_printf(1, "Warning: VVP input file sub-version %s is "
"greater than the run time sub-version %s!\n",
ip, vp);
}
free(ivl_ver);
free(vvp_ver);
}
unsigned module_cnt = 0;
const char*module_tab[64];
@ -289,6 +345,12 @@ int main(int argc, char*argv[])
if (int rc = compile_design(design_path))
return rc;
if (!have_ivl_version) {
if (verbose_flag) vpi_mcd_printf(1, "... ");
vpi_mcd_printf(1, "Warning: vvp input file may not be correct "
"version!\n");
}
if (verbose_flag) {
vpi_mcd_printf(1, "Compile cleanup...\n");
}

View File

@ -653,10 +653,14 @@ and the <dst> is a writable scalar. The <dst> gets the value of the
or of all the bits of the src vector.
* %pow <bit-l>, <bit-r>
* %pow <bit-l>, <bit-r>, <wid>
* %pow/s <bit-l>, <bit-r>, <wid>
This opcode raises <bit-l> (unsigned) to the power of <bit-r> (unsigned).
The result replaces the left operand.
The %pow opcode raises <bit-l> (unsigned) to the power of <bit-r>
(unsigned) giving an exact integer result. The %pow/s opcode does
the same for signed values, except it uses the double pow() function
to calculate the result so may not produce exact results. The result
replaces the left operand.
* %pow/wr <bit-l>, <bit-r>

View File

@ -86,7 +86,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_UDP K_UDP_C K_UDP_S
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_func K_vpi_func_r
%token K_disable K_fork
%token K_vpi_module K_vpi_time_precision K_file_names
%token K_ivl_version K_vpi_module K_vpi_time_precision K_file_names
%token <text> T_INSTR
%token <text> T_LABEL
@ -121,7 +121,11 @@ header_lines
;
header_line
: K_vpi_module T_STRING ';'
: K_ivl_version T_STRING ';'
{ verify_version($2, NULL); }
| K_ivl_version T_STRING T_STRING ';'
{ verify_version($2, $3); }
| K_vpi_module T_STRING ';'
{ compile_load_vpi_module($2); }
| K_vpi_time_precision '+' T_NUMBER ';'
{ compile_vpi_time_precision($3); }

View File

@ -1,7 +1,7 @@
#ifndef __parse_misc_H
#define __parse_misc_H
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -18,10 +18,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: parse_misc.h,v 1.8 2006/09/23 04:57:20 steve Exp $"
#endif
# include "vpi_priv.h"
@ -31,6 +27,12 @@
*/
extern int compile_design(const char*path);
/*
* This routine is called to check that the input file has a compatible
* version.
*/
extern void verify_version(char *ivl_ver, char* commit);
/*
* various functions shared by the lexor and the parser.
*/
@ -76,35 +78,4 @@ extern void argv_add(struct argv_s*obj, vpiHandle);
extern void argv_sym_add(struct argv_s*obj, char *);
extern void argv_sym_lookup(struct argv_s*obj);
/*
* $Log: parse_misc.h,v $
* Revision 1.8 2006/09/23 04:57:20 steve
* Basic support for specify timing.
*
* Revision 1.7 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2001/07/11 04:43:57 steve
* support postpone of $systask parameters. (Stephan Boettcher)
*
* Revision 1.5 2001/05/02 23:16:50 steve
* Document memory related opcodes,
* parser uses numbv_s structures instead of the
* symbv_s and a mess of unions,
* Add the %is/sub instruction.
* (Stephan Boettcher)
*
* Revision 1.4 2001/05/01 01:09:39 steve
* Add support for memory objects. (Stephan Boettcher)
*
* Revision 1.3 2001/03/20 06:16:24 steve
* Add support for variable vectors.
*
* Revision 1.2 2001/03/18 04:35:18 steve
* Add support for string constants to VPI.
*
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/
#endif

View File

@ -3838,6 +3838,36 @@ bool of_POW(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_POW_S(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
unsigned idx = cp->bit_idx[0];
unsigned idy = cp->bit_idx[1];
unsigned wid = cp->number;
vvp_vector4_t xv = vthread_bits_to_vector(thr, idx, wid);
vvp_vector4_t yv = vthread_bits_to_vector(thr, idy, wid);
/* If we have an X or Z in the arguments return X. */
if (xv.has_xz() || yv.has_xz()) {
for (unsigned jdx = 0 ; jdx < wid ; jdx += 1)
thr_put_bit(thr, cp->bit_idx[0]+jdx, BIT4_X);
return true;
}
/* Calculate the result using the double pow() function. */
double xd, yd;
vector4_to_value(xv, xd, true);
vector4_to_value(yv, yd, true);
vvp_vector4_t res = vvp_vector4_t(wid, pow(xd, yd));
/* Copy the result. */
for (unsigned jdx = 0; jdx < wid; jdx += 1)
thr_put_bit(thr, cp->bit_idx[0]+jdx, res.value(jdx));
return true;
}
bool of_POW_WR(vthread_t thr, vvp_code_t cp)
{
double l = thr->words[cp->bit_idx[0]].w_real;