diff --git a/Makefile.in b/Makefile.in index a6220e0c8..58638d592 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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);' \ diff --git a/PExpr.cc b/PExpr.cc index 7ee5f9298..f375515b2 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -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() { } diff --git a/PExpr.h b/PExpr.h index c72b21457..3f85f7932 100644 --- a/PExpr.h +++ b/PExpr.h @@ -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; }; /* diff --git a/PGenerate.cc b/PGenerate.cc index a769501e7..360344df8 100644 --- a/PGenerate.cc +++ b/PGenerate.cc @@ -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; +} diff --git a/PGenerate.h b/PGenerate.h index 74082a27a..7f8cecefc 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -25,6 +25,7 @@ # include "PScope.h" # include # include +# include # 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 item_test; list 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. listscope_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 diff --git a/driver-vpi/main.c b/driver-vpi/main.c index c4b503d4e..54b05c5b4 100644 --- a/driver-vpi/main.c +++ b/driver-vpi/main.c @@ -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"); diff --git a/elab_expr.cc b/elab_expr.cc index 21d1fe307..8cb1b164f 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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, - int expr_wid, bool sys_task_arg) const +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,8 +1811,13 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, break; } case index_component_t::SEL_BIT: - use_width = 1; - break; + { 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: ivl_assert(*this, 0); } @@ -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: diff --git a/elab_pexpr.cc b/elab_pexpr.cc index a8728cafc..e30eaac64 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -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); diff --git a/elab_scope.cc b/elab_scope.cc index cf617a640..267246e8b 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -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 (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(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(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(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 (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(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); - NetEConst*item_value_co = dynamic_cast(item_value_ex); - assert(item_value_co); + 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(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::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 (mse); diff --git a/elab_sig.cc b/elab_sig.cc index 167f068a7..176b6abff 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -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::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); diff --git a/elaborate.cc b/elaborate.cc index bd67391b0..010a43e05 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -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 (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::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); diff --git a/ivlpp/Makefile.in b/ivlpp/Makefile.in index ef4fa0e7f..991fbf79d 100644 --- a/ivlpp/Makefile.in +++ b/ivlpp/Makefile.in @@ -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@ diff --git a/libveriuser/Makefile.in b/libveriuser/Makefile.in index 7a4591c34..76055cbff 100644 --- a/libveriuser/Makefile.in +++ b/libveriuser/Makefile.in @@ -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@ diff --git a/netmisc.cc b/netmisc.cc index b223795d3..4223a0399 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -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); } diff --git a/netmisc.h b/netmisc.h index c51ba02f7..d5ff896ae 100644 --- a/netmisc.h +++ b/netmisc.h @@ -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 diff --git a/parse.y b/parse.y index 1a0f29bd6..b78e8318c 100644 --- a/parse.y +++ b/parse.y @@ -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(); } diff --git a/pform.cc b/pform.cc index a737a33b4..2737b0ea0 100644 --- a/pform.cc +++ b/pform.cc @@ -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*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) diff --git a/pform.h b/pform.h index 553fa650b..4c86d9018 100644 --- a/pform.h +++ b/pform.h @@ -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*test); extern void pform_generate_block_name(char*name); extern void pform_endgenerate(); diff --git a/tgt-fpga/Makefile.in b/tgt-fpga/Makefile.in index ed9b0c96e..aba45bdec 100644 --- a/tgt-fpga/Makefile.in +++ b/tgt-fpga/Makefile.in @@ -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@ diff --git a/tgt-pal/Makefile.in b/tgt-pal/Makefile.in index 3c89e6bc3..110ae349d 100644 --- a/tgt-pal/Makefile.in +++ b/tgt-pal/Makefile.in @@ -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@ diff --git a/tgt-verilog/Makefile.in b/tgt-verilog/Makefile.in index eac3269e7..277a42266 100644 --- a/tgt-verilog/Makefile.in +++ b/tgt-verilog/Makefile.in @@ -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@ diff --git a/tgt-vhdl/Makefile.in b/tgt-vhdl/Makefile.in index d7e32fc0e..2ad81531b 100644 --- a/tgt-vhdl/Makefile.in +++ b/tgt-vhdl/Makefile.in @@ -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@ diff --git a/tgt-vhdl/lpm.cc b/tgt-vhdl/lpm.cc index b37866fca..2d0fc46e6 100644 --- a/tgt-vhdl/lpm.cc +++ b/tgt-vhdl/lpm.cc @@ -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; - selfrom->set_slice(off, ivl_lpm_width(lpm) - 1); + if (selfrom->get_type()->get_width() > 1) + selfrom->set_slice(off, ivl_lpm_width(lpm) - 1); + return selfrom; } diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index c319abb34..69b98b31d 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -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); } diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 476b4458d..a03ed93ec 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -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@ diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 72f48ae62..1c22c394b 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -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, - lv.base, rv.base, wid); + 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: diff --git a/tgt-vvp/vvp.c b/tgt-vvp/vvp.c index 3fe0bf0ef..70815794f 100644 --- a/tgt-vvp/vvp.c +++ b/tgt-vvp/vvp.c @@ -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) diff --git a/verilog.spec b/verilog.spec index b4492160a..846c7eca1 100644 --- a/verilog.spec +++ b/verilog.spec @@ -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 diff --git a/verinum.cc b/verinum.cc index 4aa58538c..67a57e81b 100644 --- a/verinum.cc +++ b/verinum.cc @@ -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; } diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 791d64484..9cc1b023d 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -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@ diff --git a/vvp/codes.h b/vvp/codes.h index 0e634a95b..eff9a2b14 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -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); diff --git a/vvp/compile.cc b/vvp/compile.cc index 167c8d94a..fa569d90e 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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} }, diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 362773f4f..813681569 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -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; } diff --git a/vvp/main.cc b/vvp/main.cc index ddf7aacd4..a2879ada3 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -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"); } diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index c9419c405..db3de0c4e 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -653,10 +653,14 @@ and the is a writable scalar. The gets the value of the or of all the bits of the src vector. -* %pow , +* %pow , , +* %pow/s , , -This opcode raises (unsigned) to the power of (unsigned). -The result replaces the left operand. +The %pow opcode raises (unsigned) to the power of +(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 , diff --git a/vvp/parse.y b/vvp/parse.y index 3a99ce994..74e631c35 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -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 T_INSTR %token 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); } diff --git a/vvp/parse_misc.h b/vvp/parse_misc.h index 441e42ab3..859ff8787 100644 --- a/vvp/parse_misc.h +++ b/vvp/parse_misc.h @@ -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 diff --git a/vvp/vthread.cc b/vvp/vthread.cc index ddeda1c11..250a43d7f 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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;