diff --git a/design_dump.cc b/design_dump.cc index f95842476..31453ba7d 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -112,6 +112,9 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const o << setw(ind) << "" << "specify delay"; if (posedge_) o << " posedge"; if (negedge_) o << " negedge"; + if (is_condit()) + if (has_condit()) o << " if"; + else o << " ifnone"; o << " src " << "(" << transition_delays_[IVL_PE_01] << "," << transition_delays_[IVL_PE_10] diff --git a/elaborate.cc b/elaborate.cc index 06f08fe97..2d25b1b7a 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3307,16 +3307,6 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const if (!gn_specify_blocks_flag) return; - /* Check for various path types that are not supported. */ - if (conditional && !condition) { - cerr << get_fileline() << ": sorry: ifnone specify paths" - << " are not supported." << endl; - cerr << get_fileline() << ": : Use -g no-specify to ignore" - << " specify blocks." << endl; - des->errors += 1; - return; - } - ivl_assert(*this, conditional || (condition==0)); ndelays = delays.size(); @@ -3364,8 +3354,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const } NetNet*condit_sig = 0; - if (conditional) { - ivl_assert(*this, condition); + if (conditional && condition) { NetExpr*tmp = elab_and_eval(des, scope, condition, -1); ivl_assert(*condition, tmp); @@ -3386,7 +3375,9 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const cerr << get_fileline() << ": debug: Path to " << (*cur); if (condit_sig) cerr << " if " << condit_sig->name(); - cerr << endl; + else if (conditional) + cerr << " ifnone"; + cerr << " from "; } NetNet*dst_sig = scope->find_signal(*cur); @@ -3406,7 +3397,8 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const } NetDelaySrc*path = new NetDelaySrc(scope, scope->local_symbol(), - src.size(), condit_sig); + src.size(), condit_sig, + conditional); path->set_line(*this); // The presence of the data_source_expression indicates @@ -3449,6 +3441,11 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const NetNet*src_sig = scope->find_signal(*cur_src); assert(src_sig); + if (debug_elaborate) { + if (cur_src != src.begin()) cerr << " and "; + cerr << src_sig->name(); + } + if ( (src_sig->port_type() != NetNet::PINPUT) && (src_sig->port_type() != NetNet::PINOUT) ) { @@ -3461,6 +3458,9 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const connect(src_sig->pin(0), path->pin(idx)); idx += 1; } + if (debug_elaborate) { + cerr << endl; + } if (condit_sig) connect(condit_sig->pin(0), path->pin(idx)); diff --git a/ivl.def b/ivl.def index 6e3772b39..9a0883b62 100644 --- a/ivl.def +++ b/ivl.def @@ -121,6 +121,7 @@ ivl_parameter_expr ivl_path_condit ivl_path_delay +ivl_path_is_condit ivl_path_scope ivl_path_source ivl_path_source_negedge diff --git a/ivl_target.h b/ivl_target.h index d3ae71ab8..75d5e29ed 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -395,6 +395,8 @@ typedef const struct ivl_attribute_s*ivl_attribute_t; * ivl_path_condit * This returns the nexus that tracks the condition for the * delay. If the delay path is unconditional, this returns nil. + * ivl_path_is_condit + * Is this a conditional structure? Needed for ifnone. * * ivl_path_source_posedge * ivl_path_source_negedge @@ -404,6 +406,7 @@ extern ivl_scope_t ivl_path_scope(ivl_delaypath_t obj); extern ivl_nexus_t ivl_path_source(ivl_delaypath_t obj); extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt); extern ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj); +extern int ivl_path_is_condit(ivl_delaypath_t obj); extern int ivl_path_source_posedge(ivl_delaypath_t obj); extern int ivl_path_source_negedge(ivl_delaypath_t obj); diff --git a/netlist.cc b/netlist.cc index 25a262d91..03b6be397 100644 --- a/netlist.cc +++ b/netlist.cc @@ -235,11 +235,12 @@ NetBus::~NetBus() { } -NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, - unsigned npins, bool condit_src) +NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins, + bool condit_src, bool conditional) : NetObj(s, n, npins + (condit_src?1:0)) { condit_flag_ = false; + conditional_ = conditional; posedge_ = false; negedge_ = false; for (unsigned idx = 0 ; idx < npins ; idx += 1) { @@ -379,6 +380,11 @@ const Link& NetDelaySrc::src_pin(unsigned idx) const } bool NetDelaySrc::is_condit() const +{ + return conditional_; +} + +bool NetDelaySrc::has_condit() const { return condit_flag_; } diff --git a/netlist.h b/netlist.h index 02f406029..63eb17d34 100644 --- a/netlist.h +++ b/netlist.h @@ -382,8 +382,8 @@ class NetNode : public NetObj { class NetDelaySrc : public NetObj { public: - explicit NetDelaySrc(NetScope*s, perm_string n, - unsigned nsrc, bool condit_src); + explicit NetDelaySrc(NetScope*s, perm_string n, unsigned nsrc, + bool condit_src, bool conditional); ~NetDelaySrc(); // These functions set the delays from the values in the @@ -415,6 +415,7 @@ class NetDelaySrc : public NetObj { const Link&src_pin(unsigned) const; bool is_condit() const; + bool has_condit() const; Link&condit_pin(); const Link&condit_pin() const; @@ -423,6 +424,7 @@ class NetDelaySrc : public NetObj { private: uint64_t transition_delays_[12]; bool condit_flag_; + bool conditional_; bool posedge_; bool negedge_; diff --git a/t-dll-api.cc b/t-dll-api.cc index b8f8621cd..fab3f1807 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1356,6 +1356,12 @@ extern "C" ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj) return obj->condit; } +extern "C" int ivl_path_is_condit(ivl_delaypath_t obj) +{ + assert(obj); + return obj->conditional ? 1 : 0; +} + extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t edg) { assert(obj); diff --git a/t-dll.cc b/t-dll.cc index f56318188..911bac7e7 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -2382,7 +2382,7 @@ bool dll_target::signal_paths(const NetNet*net) /* If this path has a condition, then hook it up. */ ivl_nexus_t path_condit = 0; - if (src->is_condit()) { + if (src->has_condit()) { const Nexus*nt = src->condit_pin().nexus(); path_condit = nt->t_cookie(); } @@ -2399,6 +2399,7 @@ bool dll_target::signal_paths(const NetNet*net) obj->path[ptr].scope = lookup_scope_(src->scope()); obj->path[ptr].src = nex->t_cookie(); obj->path[ptr].condit = path_condit; + obj->path[ptr].conditional = src->is_condit(); obj->path[ptr].posedge = src->is_posedge(); obj->path[ptr].negedge = src->is_negedge(); for (unsigned pe = 0 ; pe < 12 ; pe += 1) { diff --git a/t-dll.h b/t-dll.h index 4cb3f7545..15e4d62a6 100644 --- a/t-dll.h +++ b/t-dll.h @@ -178,6 +178,7 @@ struct ivl_delaypath_s { ivl_scope_t scope; ivl_nexus_t src; ivl_nexus_t condit; + bool conditional; bool posedge; bool negedge; uint64_t delay[12]; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index eac616ca9..917b4b43d 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -16,9 +16,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: stub.c,v 1.148 2007/06/12 02:23:40 steve Exp $" -#endif /* * This is a sample target module. All this does is write to the @@ -1166,6 +1163,7 @@ static void show_signal(ivl_signal_t net) if (posedge) fprintf(out, " posedge"); if (negedge) fprintf(out, " negedge"); if (con) fprintf(out, " (if %s)", ivl_nexus_name(con)); + else if (ivl_path_is_condit(path)) fprintf(out, " (ifnone)"); fprintf(out, " %" PRIu64 ",%" PRIu64 ",%" PRIu64 " %" PRIu64 ",%" PRIu64 ",%" PRIu64 " %" PRIu64 ",%" PRIu64 ",%" PRIu64 @@ -1549,4 +1547,3 @@ int target_design(ivl_design_t des) return stub_errors; } - diff --git a/tgt-vvp/modpath.c b/tgt-vvp/modpath.c index cfb79fa29..07b37df22 100644 --- a/tgt-vvp/modpath.c +++ b/tgt-vvp/modpath.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-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 @@ -68,6 +68,7 @@ static void draw_modpath_record(const char*label, const char*driver, src_drivers[idx] = draw_net_input(src); if (con) con_drivers[idx] = draw_net_input(con); + else if (ivl_path_is_condit(path)) con_drivers[idx] = ""; else con_drivers[idx] = 0; } diff --git a/vvp/compile.cc b/vvp/compile.cc index ccd1d7795..cf3b8e26b 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1324,7 +1324,8 @@ struct __vpiModPath* compile_modpath(char*label, struct symb_s drv, static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path, char edge, struct symb_s src, - struct numbv_s vals) + struct numbv_s vals, + bool ifnone) { vvp_fun_modpath*dst = path->modpath; @@ -1377,7 +1378,7 @@ static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path, /* Save the vpiEdge directory into the input path term. */ srcobj->path_term_in.edge = vpi_edge; input_connect(net, 0, src.text); - dst->add_modpath_src(obj); + dst->add_modpath_src(obj, ifnone); return srcobj; } @@ -1388,7 +1389,8 @@ void compile_modpath_src(struct __vpiModPath*dst, char edge, struct symb_s condit_src, struct symb_s path_term_in) { - struct __vpiModPathSrc*obj = make_modpath_src(dst, edge, src, vals); + struct __vpiModPathSrc*obj = + make_modpath_src(dst, edge, src, vals, false); input_connect(obj->net, 1, condit_src.text); compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text); } @@ -1397,10 +1399,12 @@ void compile_modpath_src(struct __vpiModPath*dst, char edge, struct symb_s src, struct numbv_s vals, int condit_src, - struct symb_s path_term_in) + struct symb_s path_term_in, + bool ifnone) { assert(condit_src == 0); - struct __vpiModPathSrc*obj = make_modpath_src(dst, edge, src, vals); + struct __vpiModPathSrc*obj = + make_modpath_src(dst, edge, src, vals, ifnone); compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text); } diff --git a/vvp/compile.h b/vvp/compile.h index b6558ce76..9181d0638 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -199,7 +199,8 @@ extern void compile_modpath_src(__vpiModPath*dst, struct symb_s input, struct numbv_s d, int condit_input, /* match with '0' */ - struct symb_s path_term_input); + struct symb_s path_term_input, + bool ifnone); extern void compile_modpath_src(__vpiModPath*dst, char edge, struct symb_s input, diff --git a/vvp/delay.cc b/vvp/delay.cc index 066bfe0f6..8d8c1b85f 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -350,7 +350,7 @@ void vvp_fun_delay::run_run_real_(struct vvp_fun_delay::event_*cur) } vvp_fun_modpath::vvp_fun_modpath(vvp_net_t*net) -: net_(net), src_list_(0) +: net_(net), src_list_(0), ifnone_list_(0) { } @@ -362,16 +362,27 @@ vvp_fun_modpath::~vvp_fun_modpath() src_list_ = tmp->next_; delete tmp; } + while (ifnone_list_) { + vvp_fun_modpath_src*tmp = ifnone_list_; + ifnone_list_ = tmp->next_; + delete tmp; + } } -void vvp_fun_modpath::add_modpath_src(vvp_fun_modpath_src*that) +void vvp_fun_modpath::add_modpath_src(vvp_fun_modpath_src*that, bool ifnone) { assert(that->next_ == 0); - that->next_ = src_list_; - src_list_ = that; + if (ifnone) { + that->next_ = ifnone_list_; + ifnone_list_ = that; + } else { + that->next_ = src_list_; + src_list_ = that; + } } -static vvp_time64_t delay_from_edge(vvp_bit4_t a, vvp_bit4_t b, vvp_time64_t array[12]) +static vvp_time64_t delay_from_edge(vvp_bit4_t a, vvp_bit4_t b, + vvp_time64_t array[12]) { typedef delay_edge_t bit4_table4[4]; const static bit4_table4 edge_table[4] = { @@ -416,6 +427,24 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) } } + /* Only add the ifnone delay if it has a later wake_time_ or + * if there are no normal delays. */ + vvp_time64_t ifnone_wake_time = candidate_wake_time; + for (vvp_fun_modpath_src*cur = ifnone_list_ ; cur ; cur=cur->next_) { + if (candidate_list.empty()) { + candidate_list.push_back(cur); + ifnone_wake_time = cur->wake_time_; + } else if (cur->wake_time_ == ifnone_wake_time && + ifnone_wake_time > candidate_wake_time) { + candidate_list.push_back(cur); + } else if (cur->wake_time_ > ifnone_wake_time) { + candidate_list.assign(1, cur); + ifnone_wake_time = cur->wake_time_; + } else { + continue; /* Skip this entry. */ + } + } + /* Handle the special case that there are no delays that match. This may happen, for example, if the set of conditional delays is incomplete, leaving some cases diff --git a/vvp/delay.h b/vvp/delay.h index a95293fd0..412e6304a 100644 --- a/vvp/delay.h +++ b/vvp/delay.h @@ -150,7 +150,7 @@ class vvp_fun_modpath : public vvp_net_fun_t, private vvp_gen_event_s { vvp_fun_modpath(vvp_net_t*net); ~vvp_fun_modpath(); - void add_modpath_src(vvp_fun_modpath_src*that); + void add_modpath_src(vvp_fun_modpath_src*that, bool ifnone); void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit); @@ -163,6 +163,7 @@ class vvp_fun_modpath : public vvp_net_fun_t, private vvp_gen_event_s { vvp_vector4_t cur_vec4_; vvp_fun_modpath_src*src_list_; + vvp_fun_modpath_src*ifnone_list_; private: // not implemented vvp_fun_modpath(const vvp_fun_modpath&); diff --git a/vvp/parse.y b/vvp/parse.y index d7391cde1..44607c3f7 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -863,15 +863,21 @@ modpath_src_list modpath_src : symbol '(' numbers ')' symbol - { compile_modpath_src(modpath_dst, 0, $1, $3, 0, $5); } + { compile_modpath_src(modpath_dst, 0, $1, $3, 0, $5, false); } + | symbol '(' numbers '?' ')' symbol + { compile_modpath_src(modpath_dst, 0, $1, $3, 0, $6, true); } | symbol '(' numbers '?' symbol ')' symbol { compile_modpath_src(modpath_dst, 0, $1, $3, $5, $7); } | symbol '+' '(' numbers ')' symbol - { compile_modpath_src(modpath_dst, '+', $1, $4, 0, $6); } + { compile_modpath_src(modpath_dst, '+', $1, $4, 0, $6, false); } + | symbol '+' '(' numbers '?' ')' symbol + { compile_modpath_src(modpath_dst, '+', $1, $4, 0, $7, true); } | symbol '+' '(' numbers '?' symbol ')' symbol { compile_modpath_src(modpath_dst, '+', $1, $4, $6, $8); } | symbol '-' '(' numbers ')' symbol - { compile_modpath_src(modpath_dst, '-', $1, $4, 0, $6); } + { compile_modpath_src(modpath_dst, '-', $1, $4, 0, $6, false); } + | symbol '-' '(' numbers '?' ')' symbol + { compile_modpath_src(modpath_dst, '-', $1, $4, 0, $7, true); } | symbol '-' '(' numbers '?' symbol ')' symbol { compile_modpath_src(modpath_dst, '-', $1, $4, $6, $8); } ;