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:
parent
64c92f9fdd
commit
436e2fca13
|
|
@ -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]
|
||||
|
|
|
|||
28
elaborate.cc
28
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));
|
||||
|
|
|
|||
1
ivl.def
1
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
10
netlist.cc
10
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_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
3
t-dll.cc
3
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) {
|
||||
|
|
|
|||
1
t-dll.h
1
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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
39
vvp/delay.cc
39
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
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
12
vvp/parse.y
12
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); }
|
||||
;
|
||||
|
|
|
|||
Loading…
Reference in New Issue