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 { class PEEvent : public PExpr {
public: 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. // Use this constructor to create events based on edges or levels.
PEEvent(edge_t t, PExpr*e); 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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: case NEGEDGE:
o << "negedge "; o << "negedge ";
break; break;
case EDGE:
o << "edge ";
break;
} }
o << setw(ind) << "" << "-> " << event_->name() << "; " << endl; o << setw(ind) << "" << "-> " << event_->name() << "; " << endl;
dump_node_pins(o, ind+4); dump_node_pins(o, ind+4);

View File

@ -4665,6 +4665,11 @@ cerr << endl;
NetEvProbe::NEGEDGE, pins); NetEvProbe::NEGEDGE, pins);
break; break;
case PEEvent::EDGE:
pr = new NetEvProbe(scope, scope->local_symbol(), ev,
NetEvProbe::EDGE, pins);
break;
case PEEvent::ANYEDGE: case PEEvent::ANYEDGE:
pr = new NetEvProbe(scope, scope->local_symbol(), ev, pr = new NetEvProbe(scope, scope->local_symbol(), ev,
NetEvProbe::ANYEDGE, pins); NetEvProbe::ANYEDGE, pins);

View File

@ -41,10 +41,12 @@ ivl_enum_width
ivl_event_any ivl_event_any
ivl_event_basename ivl_event_basename
ivl_event_edg
ivl_event_file ivl_event_file
ivl_event_lineno ivl_event_lineno
ivl_event_name ivl_event_name
ivl_event_nany ivl_event_nany
ivl_event_nedg
ivl_event_neg ivl_event_neg
ivl_event_nneg ivl_event_nneg
ivl_event_npos ivl_event_npos

View File

@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_H #ifndef IVL_ivl_target_H
#define 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 unsigned ivl_event_nany(ivl_event_t net);
extern ivl_nexus_t ivl_event_any(ivl_event_t net, unsigned idx); 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 unsigned ivl_event_nneg(ivl_event_t net);
extern ivl_nexus_t ivl_event_neg(ivl_event_t net, unsigned idx); 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; friend class NetEvent;
public: public:
enum edge_t { ANYEDGE, POSEDGE, NEGEDGE }; enum edge_t { ANYEDGE, POSEDGE, NEGEDGE, EDGE };
explicit NetEvProbe(NetScope*s, perm_string n, explicit NetEvProbe(NetScope*s, perm_string n,
NetEvent*tgt, edge_t t, unsigned p); 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) * Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -3430,6 +3430,13 @@ event_expression
(*tl)[0] = tmp; (*tl)[0] = tmp;
$$ = tl; $$ = 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 | expression
{ PEEvent*tmp = new PEEvent(PEEvent::ANYEDGE, $1); { PEEvent*tmp = new PEEvent(PEEvent::ANYEDGE, $1);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);

View File

@ -406,6 +406,9 @@ void PEEvent::dump(ostream&out) const
case PEEvent::NEGEDGE: case PEEvent::NEGEDGE:
out << "negedge "; out << "negedge ";
break; break;
case PEEvent::EDGE:
out << "edge ";
break;
case PEEvent::POSITIVE: case PEEvent::POSITIVE:
out << "positive "; out << "positive ";
break; 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 CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * 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]; 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) extern "C" unsigned ivl_event_nneg(ivl_event_t net)
{ {
assert(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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 iany = 0;
unsigned ineg = ev_tmp->nany; unsigned ineg = ev_tmp->nany;
unsigned ipos = ineg + ev_tmp->nneg; unsigned ipos = ineg + ev_tmp->nneg;
unsigned iedg = ipos + ev_tmp->npos;
for (unsigned idx = 0; idx < ev->nprobe(); idx += 1) { for (unsigned idx = 0; idx < ev->nprobe(); idx += 1) {
const NetEvProbe*pr = ev->probe(idx); const NetEvProbe*pr = ev->probe(idx);
@ -388,6 +389,10 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
base = ipos; base = ipos;
ipos += pr->pin_count(); ipos += pr->pin_count();
break; break;
case NetEvProbe::EDGE:
base = iedg;
iedg += pr->pin_count();
break;
} }
for (unsigned bit = 0; bit < pr->pin_count(); for (unsigned bit = 0; bit < pr->pin_count();
@ -895,6 +900,7 @@ bool dll_target::proc_wait(const NetEvWait*net)
unsigned iany = 0; unsigned iany = 0;
unsigned ineg = ev_tmp->nany; unsigned ineg = ev_tmp->nany;
unsigned ipos = ineg + ev_tmp->nneg; unsigned ipos = ineg + ev_tmp->nneg;
unsigned iedg = ipos + ev_tmp->npos;
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) { for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
const NetEvProbe*pr = ev->probe(idx); const NetEvProbe*pr = ev->probe(idx);
@ -913,6 +919,10 @@ bool dll_target::proc_wait(const NetEvWait*net)
base = ipos; base = ipos;
ipos += pr->pin_count(); ipos += pr->pin_count();
break; break;
case NetEvProbe::EDGE:
base = iedg;
iedg += pr->pin_count();
break;
} }
for (unsigned bit = 0; bit < pr->pin_count(); bit += 1) { 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->nany = 0;
obj->nneg = 0; obj->nneg = 0;
obj->npos = 0; obj->npos = 0;
obj->nedg = 0;
if (net->nprobe() >= 1) { if (net->nprobe() >= 1) {
@ -929,6 +930,9 @@ void dll_target::event(const NetEvent*net)
case NetEvProbe::POSEDGE: case NetEvProbe::POSEDGE:
obj->npos += pr->pin_count(); obj->npos += pr->pin_count();
break; break;
case NetEvProbe::EDGE:
obj->nedg += pr->pin_count();
break;
} }
} }

View File

@ -1,7 +1,7 @@
#ifndef IVL_t_dll_H #ifndef IVL_t_dll_H
#define 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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; ivl_scope_t scope;
perm_string file; perm_string file;
unsigned lineno; unsigned lineno;
unsigned nany, nneg, npos; unsigned nany, nneg, npos, nedg;
ivl_nexus_t*pins; 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 * 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 * 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); 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. */ /* We have a named event if there were no edge events. */
if (!had_edge) { if (!had_edge) {
ivl_scope_t ev_scope = ivl_event_scope(event); 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 nany = ivl_event_nany(obj);
unsigned nneg = ivl_event_nneg(obj); unsigned nneg = ivl_event_nneg(obj);
unsigned npos = ivl_event_npos(obj); unsigned npos = ivl_event_npos(obj);
unsigned nedg = ivl_event_nedg(obj);
unsigned cnt = 0; unsigned cnt = 0;
@ -1166,6 +1167,9 @@ static void draw_event_in_scope(ivl_event_t obj)
if (npos > 0) if (npos > 0)
cnt += (npos+ntmp-1) / ntmp; cnt += (npos+ntmp-1) / ntmp;
if (nedg > 0)
cnt += (nedg+ntmp-1) / ntmp;
if (cnt == 0) { if (cnt == 0) {
/* If none are needed, then this is a named event. The /* If none are needed, then this is a named event. The
code needed is easy. */ 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])); 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) for (sub = idx ; sub < top ; sub += 1)
fprintf(vvp_out, ", %s", tmp[sub-idx]); 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"); 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); assert(ecnt == cnt);
fprintf(vvp_out, "E_%p .event/or", obj); 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"); fprintf(vvp_out, ";\n");
} else { } else {
unsigned num_input_strings = nany + nneg + npos; unsigned num_input_strings = nany + nneg + npos + nedg;
unsigned idx; unsigned idx;
const char*edge = 0; const char*edge = 0;
assert(num_input_strings <= ntmp); assert(num_input_strings <= ntmp);
if (nany > 0) { if (nany > 0) {
assert((nneg + npos) == 0); assert((nneg + npos + nedg) == 0);
edge = "edge"; edge = "anyedge";
for (idx = 0 ; idx < nany ; idx += 1) { for (idx = 0 ; idx < nany ; idx += 1) {
ivl_nexus_t nex = ivl_event_any(obj, idx); 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) { } else if (nneg > 0) {
assert((nany + npos) == 0); assert((nany + npos + nedg) == 0);
edge = "negedge"; edge = "negedge";
for (idx = 0 ; idx < nneg ; idx += 1) { 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])); strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0]));
} }
} else { } else if (npos > 0) {
assert((nany + nneg) == 0); assert((nany + nneg + nedg) == 0);
edge = "posedge"; edge = "posedge";
for (idx = 0 ; idx < npos ; idx += 1) { for (idx = 0 ; idx < npos ; idx += 1) {
ivl_nexus_t nex = ivl_event_pos(obj, idx); ivl_nexus_t nex = ivl_event_pos(obj, idx);
strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0])); 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); 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. <symbols_list> is a set of inputs that can trigger the event.
The <type> describes the conditions needed to trigger the event. It The <type> describes the conditions needed to trigger the event. It
may be posedge, negedge or edge. If the type is instead a "name" may be posedge, negedge, edge or anyedge. If the type is instead a
string, then this is a named event which receives events by the %set "name" string, then this is a named event which receives events by
instruction instead of from the output of a functor. the %set instruction instead of from the output of a functor.
If the event has inputs (a requirement unless it is a named event) 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 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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) | 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; const vvp_fun_edge::edge_t vvp_edge_none = 0;
struct vvp_fun_edge_state_s : public waitable_state_s { 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; return;
} }
if (strcmp(type,"edge") == 0) { if (strcmp(type,"anyedge") == 0) {
free(type); free(type);
@ -993,6 +1006,8 @@ void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv)
edge_type = vvp_edge_posedge; edge_type = vvp_edge_posedge;
else if (strcmp(type,"negedge") == 0) else if (strcmp(type,"negedge") == 0)
edge_type = vvp_edge_negedge; edge_type = vvp_edge_negedge;
else if (strcmp(type,"edge") == 0)
edge_type = vvp_edge_edge;
assert(argc <= 4); assert(argc <= 4);
free(type); free(type);

View File

@ -1,7 +1,7 @@
#ifndef IVL_event_H #ifndef IVL_event_H
#define 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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_; 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_posedge;
extern const vvp_fun_edge::edge_t vvp_edge_negedge; extern const vvp_fun_edge::edge_t vvp_edge_negedge;
extern const vvp_fun_edge::edge_t vvp_edge_none; extern const vvp_fun_edge::edge_t vvp_edge_none;