Add support for SV edge
This commit is contained in:
parent
8f908a213d
commit
32787bb973
2
PExpr.h
2
PExpr.h
|
|
@ -281,7 +281,7 @@ class PEConcat : public PExpr {
|
|||
class PEEvent : public PExpr {
|
||||
|
||||
public:
|
||||
enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, POSITIVE};
|
||||
enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, EDGE, POSITIVE};
|
||||
|
||||
// Use this constructor to create events based on edges or levels.
|
||||
PEEvent(edge_t t, PExpr*e);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2021 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
|
||||
|
|
@ -1285,6 +1285,9 @@ void NetEvProbe::dump_node(ostream&o, unsigned ind) const
|
|||
case NEGEDGE:
|
||||
o << "negedge ";
|
||||
break;
|
||||
case EDGE:
|
||||
o << "edge ";
|
||||
break;
|
||||
}
|
||||
o << setw(ind) << "" << "-> " << event_->name() << "; " << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
|
|
|
|||
|
|
@ -4665,6 +4665,11 @@ cerr << endl;
|
|||
NetEvProbe::NEGEDGE, pins);
|
||||
break;
|
||||
|
||||
case PEEvent::EDGE:
|
||||
pr = new NetEvProbe(scope, scope->local_symbol(), ev,
|
||||
NetEvProbe::EDGE, pins);
|
||||
break;
|
||||
|
||||
case PEEvent::ANYEDGE:
|
||||
pr = new NetEvProbe(scope, scope->local_symbol(), ev,
|
||||
NetEvProbe::ANYEDGE, pins);
|
||||
|
|
|
|||
2
ivl.def
2
ivl.def
|
|
@ -41,10 +41,12 @@ ivl_enum_width
|
|||
|
||||
ivl_event_any
|
||||
ivl_event_basename
|
||||
ivl_event_edg
|
||||
ivl_event_file
|
||||
ivl_event_lineno
|
||||
ivl_event_name
|
||||
ivl_event_nany
|
||||
ivl_event_nedg
|
||||
ivl_event_neg
|
||||
ivl_event_nneg
|
||||
ivl_event_npos
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_ivl_target_H
|
||||
#define IVL_ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 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
|
||||
|
|
@ -768,6 +768,9 @@ extern ivl_scope_t ivl_event_scope(ivl_event_t net);
|
|||
extern unsigned ivl_event_nany(ivl_event_t net);
|
||||
extern ivl_nexus_t ivl_event_any(ivl_event_t net, unsigned idx);
|
||||
|
||||
extern unsigned ivl_event_nedg(ivl_event_t net);
|
||||
extern ivl_nexus_t ivl_event_edg(ivl_event_t net, unsigned idx);
|
||||
|
||||
extern unsigned ivl_event_nneg(ivl_event_t net);
|
||||
extern ivl_nexus_t ivl_event_neg(ivl_event_t net, unsigned idx);
|
||||
|
||||
|
|
|
|||
|
|
@ -3522,7 +3522,7 @@ class NetEvProbe : public NetNode {
|
|||
friend class NetEvent;
|
||||
|
||||
public:
|
||||
enum edge_t { ANYEDGE, POSEDGE, NEGEDGE };
|
||||
enum edge_t { ANYEDGE, POSEDGE, NEGEDGE, EDGE };
|
||||
|
||||
explicit NetEvProbe(NetScope*s, perm_string n,
|
||||
NetEvent*tgt, edge_t t, unsigned p);
|
||||
|
|
|
|||
9
parse.y
9
parse.y
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -3430,6 +3430,13 @@ event_expression
|
|||
(*tl)[0] = tmp;
|
||||
$$ = tl;
|
||||
}
|
||||
| K_edge expression
|
||||
{ PEEvent*tmp = new PEEvent(PEEvent::EDGE, $2);
|
||||
FILE_NAME(tmp, @1);
|
||||
svector<PEEvent*>*tl = new svector<PEEvent*>(1);
|
||||
(*tl)[0] = tmp;
|
||||
$$ = tl;
|
||||
}
|
||||
| expression
|
||||
{ PEEvent*tmp = new PEEvent(PEEvent::ANYEDGE, $1);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
|
|
|||
|
|
@ -406,6 +406,9 @@ void PEEvent::dump(ostream&out) const
|
|||
case PEEvent::NEGEDGE:
|
||||
out << "negedge ";
|
||||
break;
|
||||
case PEEvent::EDGE:
|
||||
out << "edge ";
|
||||
break;
|
||||
case PEEvent::POSITIVE:
|
||||
out << "positive ";
|
||||
break;
|
||||
|
|
|
|||
15
t-dll-api.cc
15
t-dll-api.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch)
|
||||
*
|
||||
|
|
@ -366,6 +366,19 @@ extern "C" ivl_nexus_t ivl_event_any(ivl_event_t net, unsigned idx)
|
|||
return net->pins[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_event_nedg(ivl_event_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->nedg;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_event_edg(ivl_event_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->nedg);
|
||||
return net->pins[net->nany + net->nneg + net->npos + idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_event_nneg(ivl_event_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 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
|
||||
|
|
@ -370,6 +370,7 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
|
|||
unsigned iany = 0;
|
||||
unsigned ineg = ev_tmp->nany;
|
||||
unsigned ipos = ineg + ev_tmp->nneg;
|
||||
unsigned iedg = ipos + ev_tmp->npos;
|
||||
|
||||
for (unsigned idx = 0; idx < ev->nprobe(); idx += 1) {
|
||||
const NetEvProbe*pr = ev->probe(idx);
|
||||
|
|
@ -388,6 +389,10 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
|
|||
base = ipos;
|
||||
ipos += pr->pin_count();
|
||||
break;
|
||||
case NetEvProbe::EDGE:
|
||||
base = iedg;
|
||||
iedg += pr->pin_count();
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned bit = 0; bit < pr->pin_count();
|
||||
|
|
@ -895,6 +900,7 @@ bool dll_target::proc_wait(const NetEvWait*net)
|
|||
unsigned iany = 0;
|
||||
unsigned ineg = ev_tmp->nany;
|
||||
unsigned ipos = ineg + ev_tmp->nneg;
|
||||
unsigned iedg = ipos + ev_tmp->npos;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
|
||||
const NetEvProbe*pr = ev->probe(idx);
|
||||
|
|
@ -913,6 +919,10 @@ bool dll_target::proc_wait(const NetEvWait*net)
|
|||
base = ipos;
|
||||
ipos += pr->pin_count();
|
||||
break;
|
||||
case NetEvProbe::EDGE:
|
||||
base = iedg;
|
||||
iedg += pr->pin_count();
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned bit = 0; bit < pr->pin_count(); bit += 1) {
|
||||
|
|
|
|||
4
t-dll.cc
4
t-dll.cc
|
|
@ -914,6 +914,7 @@ void dll_target::event(const NetEvent*net)
|
|||
obj->nany = 0;
|
||||
obj->nneg = 0;
|
||||
obj->npos = 0;
|
||||
obj->nedg = 0;
|
||||
|
||||
if (net->nprobe() >= 1) {
|
||||
|
||||
|
|
@ -929,6 +930,9 @@ void dll_target::event(const NetEvent*net)
|
|||
case NetEvProbe::POSEDGE:
|
||||
obj->npos += pr->pin_count();
|
||||
break;
|
||||
case NetEvProbe::EDGE:
|
||||
obj->nedg += pr->pin_count();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
4
t-dll.h
4
t-dll.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_t_dll_H
|
||||
#define IVL_t_dll_H
|
||||
/*
|
||||
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2021 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
|
||||
|
|
@ -217,7 +217,7 @@ struct ivl_event_s {
|
|||
ivl_scope_t scope;
|
||||
perm_string file;
|
||||
unsigned lineno;
|
||||
unsigned nany, nneg, npos;
|
||||
unsigned nany, nneg, npos, nedg;
|
||||
ivl_nexus_t*pins;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2011-2021 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -77,6 +77,18 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt)
|
|||
emit_nexus_as_ca(scope, ivl_event_neg(event, idx), 0, 0);
|
||||
}
|
||||
|
||||
/* Check for edge events. */
|
||||
count = ivl_event_nedg(event);
|
||||
if (count) had_edge = 1;
|
||||
for (idx = 0; idx < count; idx += 1) {
|
||||
if (first) first = 0;
|
||||
else fprintf(vlog_out, " or ");
|
||||
fprintf(vlog_out, "posedge ");
|
||||
emit_nexus_as_ca(scope, ivl_event_edg(event, idx), 0, 0);
|
||||
fprintf(vlog_out, " or negedge ");
|
||||
emit_nexus_as_ca(scope, ivl_event_edg(event, idx), 0, 0);
|
||||
}
|
||||
|
||||
/* We have a named event if there were no edge events. */
|
||||
if (!had_edge) {
|
||||
ivl_scope_t ev_scope = ivl_event_scope(event);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2021 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
|
||||
|
|
@ -1153,6 +1153,7 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
unsigned nany = ivl_event_nany(obj);
|
||||
unsigned nneg = ivl_event_nneg(obj);
|
||||
unsigned npos = ivl_event_npos(obj);
|
||||
unsigned nedg = ivl_event_nedg(obj);
|
||||
|
||||
unsigned cnt = 0;
|
||||
|
||||
|
|
@ -1166,6 +1167,9 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
if (npos > 0)
|
||||
cnt += (npos+ntmp-1) / ntmp;
|
||||
|
||||
if (nedg > 0)
|
||||
cnt += (nedg+ntmp-1) / ntmp;
|
||||
|
||||
if (cnt == 0) {
|
||||
/* If none are needed, then this is a named event. The
|
||||
code needed is easy. */
|
||||
|
|
@ -1189,7 +1193,7 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
strncpy(tmp[sub-idx], draw_input_from_net(nex), sizeof(tmp[0]));
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "E_%p/%u .event edge", obj, ecnt);
|
||||
fprintf(vvp_out, "E_%p/%u .event anyedge", obj, ecnt);
|
||||
for (sub = idx ; sub < top ; sub += 1)
|
||||
fprintf(vvp_out, ", %s", tmp[sub-idx]);
|
||||
|
||||
|
|
@ -1232,6 +1236,24 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < nedg ; idx += ntmp, ecnt += 1) {
|
||||
unsigned sub, top;
|
||||
|
||||
top = idx + ntmp;
|
||||
if (nedg < top)
|
||||
top = nedg;
|
||||
for (sub = idx ; sub < top ; sub += 1) {
|
||||
ivl_nexus_t nex = ivl_event_edg(obj, sub);
|
||||
strncpy(tmp[sub-idx], draw_input_from_net(nex), sizeof(tmp[0]));
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "E_%p/%u .event edge", obj, ecnt);
|
||||
for (sub = idx ; sub < top ; sub += 1)
|
||||
fprintf(vvp_out, ", %s", tmp[sub-idx]);
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
assert(ecnt == cnt);
|
||||
|
||||
fprintf(vvp_out, "E_%p .event/or", obj);
|
||||
|
|
@ -1243,15 +1265,15 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
fprintf(vvp_out, ";\n");
|
||||
|
||||
} else {
|
||||
unsigned num_input_strings = nany + nneg + npos;
|
||||
unsigned num_input_strings = nany + nneg + npos + nedg;
|
||||
unsigned idx;
|
||||
const char*edge = 0;
|
||||
|
||||
assert(num_input_strings <= ntmp);
|
||||
|
||||
if (nany > 0) {
|
||||
assert((nneg + npos) == 0);
|
||||
edge = "edge";
|
||||
assert((nneg + npos + nedg) == 0);
|
||||
edge = "anyedge";
|
||||
|
||||
for (idx = 0 ; idx < nany ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_event_any(obj, idx);
|
||||
|
|
@ -1259,7 +1281,7 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
}
|
||||
|
||||
} else if (nneg > 0) {
|
||||
assert((nany + npos) == 0);
|
||||
assert((nany + npos + nedg) == 0);
|
||||
edge = "negedge";
|
||||
|
||||
for (idx = 0 ; idx < nneg ; idx += 1) {
|
||||
|
|
@ -1267,14 +1289,22 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0]));
|
||||
}
|
||||
|
||||
} else {
|
||||
assert((nany + nneg) == 0);
|
||||
} else if (npos > 0) {
|
||||
assert((nany + nneg + nedg) == 0);
|
||||
edge = "posedge";
|
||||
|
||||
for (idx = 0 ; idx < npos ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_event_pos(obj, idx);
|
||||
strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0]));
|
||||
}
|
||||
} else {
|
||||
assert((nany + nneg + npos) == 0);
|
||||
edge = "edge";
|
||||
|
||||
for (idx = 0 ; idx < nedg ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_event_edg(obj, idx);
|
||||
strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0]));
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "E_%p .event %s", obj, edge);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -458,9 +458,9 @@ itself in the notification list of the event and suspends. The
|
|||
<symbols_list> is a set of inputs that can trigger the event.
|
||||
|
||||
The <type> describes the conditions needed to trigger the event. It
|
||||
may be posedge, negedge or edge. If the type is instead a "name"
|
||||
string, then this is a named event which receives events by the %set
|
||||
instruction instead of from the output of a functor.
|
||||
may be posedge, negedge, edge or anyedge. If the type is instead a
|
||||
"name" string, then this is a named event which receives events by
|
||||
the %set instruction instead of from the output of a functor.
|
||||
|
||||
If the event has inputs (a requirement unless it is a named event)
|
||||
then it has up to 4 symbols that address functors. The event then
|
||||
|
|
|
|||
19
vvp/event.cc
19
vvp/event.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2004-2021 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
|
||||
|
|
@ -199,6 +199,19 @@ const vvp_fun_edge::edge_t vvp_edge_negedge
|
|||
| VVP_EDGE(BIT4_Z,BIT4_0)
|
||||
;
|
||||
|
||||
const vvp_fun_edge::edge_t vvp_edge_edge
|
||||
= VVP_EDGE(BIT4_0,BIT4_1)
|
||||
| VVP_EDGE(BIT4_1,BIT4_0)
|
||||
| VVP_EDGE(BIT4_0,BIT4_X)
|
||||
| VVP_EDGE(BIT4_X,BIT4_0)
|
||||
| VVP_EDGE(BIT4_0,BIT4_Z)
|
||||
| VVP_EDGE(BIT4_Z,BIT4_0)
|
||||
| VVP_EDGE(BIT4_X,BIT4_1)
|
||||
| VVP_EDGE(BIT4_1,BIT4_X)
|
||||
| VVP_EDGE(BIT4_Z,BIT4_1)
|
||||
| VVP_EDGE(BIT4_1,BIT4_Z)
|
||||
;
|
||||
|
||||
const vvp_fun_edge::edge_t vvp_edge_none = 0;
|
||||
|
||||
struct vvp_fun_edge_state_s : public waitable_state_s {
|
||||
|
|
@ -975,7 +988,7 @@ void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv)
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(type,"edge") == 0) {
|
||||
if (strcmp(type,"anyedge") == 0) {
|
||||
|
||||
free(type);
|
||||
|
||||
|
|
@ -993,6 +1006,8 @@ void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv)
|
|||
edge_type = vvp_edge_posedge;
|
||||
else if (strcmp(type,"negedge") == 0)
|
||||
edge_type = vvp_edge_negedge;
|
||||
else if (strcmp(type,"edge") == 0)
|
||||
edge_type = vvp_edge_edge;
|
||||
|
||||
assert(argc <= 4);
|
||||
free(type);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_event_H
|
||||
#define IVL_event_H
|
||||
/*
|
||||
* Copyright (c) 2004-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2004-2021 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
|
||||
|
|
@ -166,6 +166,7 @@ class vvp_fun_edge : public vvp_net_fun_t, public waitable_hooks_s {
|
|||
edge_t edge_;
|
||||
};
|
||||
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_edge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_posedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_negedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_none;
|
||||
|
|
|
|||
Loading…
Reference in New Issue