Add support for SV edge

This commit is contained in:
Cary R 2021-01-07 01:22:13 -08:00
parent 8f908a213d
commit 32787bb973
17 changed files with 133 additions and 25 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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