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.
This commit is contained in:
Cary R 2008-04-28 19:00:29 -07:00 committed by Stephen Williams
parent 64c92f9fdd
commit 436e2fca13
16 changed files with 102 additions and 40 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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