From 436e2fca1378a71d18813fec6133acad51b4f81a Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 28 Apr 2008 19:00:29 -0700 Subject: [PATCH] Add ifnone functionality. This patch adds ifnone functionality. It does not produce an error when both an ifnone and an unconditional simple module path are given. For this case the ifnone delays are ignored. --- design_dump.cc | 3 +++ elaborate.cc | 28 ++++++++++++++-------------- ivl.def | 1 + ivl_target.h | 3 +++ netlist.cc | 10 ++++++++-- netlist.h | 6 ++++-- t-dll-api.cc | 6 ++++++ t-dll.cc | 3 ++- t-dll.h | 1 + tgt-stub/stub.c | 7 ++----- tgt-vvp/modpath.c | 3 ++- vvp/compile.cc | 14 +++++++++----- vvp/compile.h | 3 ++- vvp/delay.cc | 39 ++++++++++++++++++++++++++++++++++----- vvp/delay.h | 3 ++- vvp/parse.y | 12 +++++++++--- 16 files changed, 102 insertions(+), 40 deletions(-) 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); } ;