2001-11-06 04:07:21 +01:00
|
|
|
/*
|
2008-09-11 04:37:11 +02:00
|
|
|
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
|
2001-11-06 04:07:21 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "event.h"
|
|
|
|
|
# include "compile.h"
|
|
|
|
|
# include "vthread.h"
|
|
|
|
|
# include "schedule.h"
|
2002-05-19 07:18:16 +02:00
|
|
|
# include "vpi_priv.h"
|
2001-11-06 04:07:21 +01:00
|
|
|
|
|
|
|
|
# include <string.h>
|
|
|
|
|
# include <assert.h>
|
2001-11-16 05:22:27 +01:00
|
|
|
# include <stdlib.h>
|
2001-11-06 04:07:21 +01:00
|
|
|
#ifdef HAVE_MALLOC_H
|
|
|
|
|
# include <malloc.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-11-22 07:10:05 +01:00
|
|
|
# include <iostream>
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
void waitable_hooks_s::run_waiting_threads_(unsigned context_idx)
|
2004-12-18 19:52:44 +01:00
|
|
|
{
|
2008-09-11 04:37:11 +02:00
|
|
|
// Run the non-blocking event controls.
|
|
|
|
|
last = &event_ctls;
|
|
|
|
|
for (evctl*cur = event_ctls; cur != 0;) {
|
|
|
|
|
if (cur->dec_and_run()) {
|
|
|
|
|
evctl*nxt = cur->next;
|
|
|
|
|
delete cur;
|
|
|
|
|
cur = nxt;
|
|
|
|
|
*last = cur;
|
|
|
|
|
} else {
|
|
|
|
|
last = &(cur->next);
|
|
|
|
|
cur = cur->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
vthread_t tmp;
|
|
|
|
|
if (context_idx) {
|
|
|
|
|
waitable_state_s*state = static_cast<waitable_state_s*>
|
|
|
|
|
(vthread_get_wt_context_item(context_idx));
|
|
|
|
|
tmp = state->threads;
|
|
|
|
|
state->threads = 0;
|
|
|
|
|
} else {
|
|
|
|
|
tmp = threads;
|
|
|
|
|
threads = 0;
|
|
|
|
|
}
|
|
|
|
|
if (tmp) vthread_schedule_list(tmp);
|
2004-12-18 19:52:44 +01:00
|
|
|
}
|
|
|
|
|
|
2008-09-11 04:37:11 +02:00
|
|
|
evctl::evctl(unsigned long ecount)
|
|
|
|
|
{
|
|
|
|
|
ecount_ = ecount;
|
|
|
|
|
next = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-18 01:47:20 +02:00
|
|
|
bool evctl::dec_and_run()
|
|
|
|
|
{
|
|
|
|
|
assert(ecount_ != 0);
|
|
|
|
|
|
|
|
|
|
ecount_ -= 1;
|
|
|
|
|
if (ecount_ == 0) run_run();
|
|
|
|
|
|
|
|
|
|
return ecount_ == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-11 04:37:11 +02:00
|
|
|
evctl_real::evctl_real(struct __vpiHandle*handle, double value,
|
|
|
|
|
unsigned long ecount)
|
|
|
|
|
:evctl(ecount)
|
|
|
|
|
{
|
|
|
|
|
handle_ = handle;
|
|
|
|
|
value_ = value;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-18 01:47:20 +02:00
|
|
|
void evctl_real::run_run()
|
2008-09-11 04:37:11 +02:00
|
|
|
{
|
2008-09-18 01:47:20 +02:00
|
|
|
t_vpi_value val;
|
2008-09-11 04:37:11 +02:00
|
|
|
|
2008-09-18 01:47:20 +02:00
|
|
|
val.format = vpiRealVal;
|
|
|
|
|
val.value.real = value_;
|
|
|
|
|
vpi_put_value(handle_, &val, 0, vpiNoDelay);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void schedule_evctl(struct __vpiHandle*handle, double value,
|
|
|
|
|
vvp_net_t*event, unsigned long ecount)
|
|
|
|
|
{
|
|
|
|
|
// Get the functor we are going to wait on.
|
|
|
|
|
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
|
|
|
|
|
assert(ep);
|
|
|
|
|
// Now add this call to the end of the event list.
|
|
|
|
|
*(ep->last) = new evctl_real(handle, value, ecount);
|
|
|
|
|
ep->last = &((*(ep->last))->next);
|
|
|
|
|
}
|
2008-09-11 04:37:11 +02:00
|
|
|
|
2008-09-18 01:47:20 +02:00
|
|
|
evctl_vector::evctl_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
|
|
|
|
unsigned off, unsigned wid, unsigned long ecount)
|
|
|
|
|
:evctl(ecount), value_(value)
|
|
|
|
|
{
|
|
|
|
|
ptr_ = ptr;
|
|
|
|
|
off_ = off;
|
|
|
|
|
wid_ = wid;
|
|
|
|
|
}
|
2008-09-11 04:37:11 +02:00
|
|
|
|
2008-09-18 01:47:20 +02:00
|
|
|
void evctl_vector::run_run()
|
|
|
|
|
{
|
|
|
|
|
if (wid_ != 0) {
|
|
|
|
|
vvp_send_vec4_pv(ptr_, value_, off_, value_.size(), wid_);
|
|
|
|
|
} else {
|
|
|
|
|
vvp_send_vec4(ptr_, value_);
|
2008-09-11 04:37:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-18 01:47:20 +02:00
|
|
|
void schedule_evctl(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
|
|
|
|
unsigned offset, unsigned wid,
|
2008-09-11 04:37:11 +02:00
|
|
|
vvp_net_t*event, unsigned long ecount)
|
|
|
|
|
{
|
|
|
|
|
// Get the functor we are going to wait on.
|
|
|
|
|
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
|
|
|
|
|
assert(ep);
|
|
|
|
|
// Now add this call to the end of the event list.
|
2008-09-18 01:47:20 +02:00
|
|
|
*(ep->last) = new evctl_vector(ptr, value, offset, wid, ecount);
|
2008-09-11 04:37:11 +02:00
|
|
|
ep->last = &((*(ep->last))->next);
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-18 22:44:54 +02:00
|
|
|
evctl_array::evctl_array(vvp_array_t memory, unsigned index,
|
|
|
|
|
const vvp_vector4_t&value, unsigned off,
|
|
|
|
|
unsigned long ecount)
|
|
|
|
|
:evctl(ecount), value_(value)
|
|
|
|
|
{
|
|
|
|
|
mem_ = memory;
|
|
|
|
|
idx_ = index;
|
|
|
|
|
off_ = off;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void evctl_array::run_run()
|
|
|
|
|
{
|
|
|
|
|
array_set_word(mem_, idx_, off_, value_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void schedule_evctl(vvp_array_t memory, unsigned index,
|
|
|
|
|
const vvp_vector4_t&value, unsigned offset,
|
|
|
|
|
vvp_net_t*event, unsigned long ecount)
|
|
|
|
|
{
|
|
|
|
|
// Get the functor we are going to wait on.
|
|
|
|
|
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
|
|
|
|
|
assert(ep);
|
|
|
|
|
// Now add this call to the end of the event list.
|
|
|
|
|
*(ep->last) = new evctl_array(memory, index, value, offset, ecount);
|
|
|
|
|
ep->last = &((*(ep->last))->next);
|
|
|
|
|
}
|
2008-09-18 01:47:20 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
|
2002-05-19 07:18:16 +02:00
|
|
|
{
|
2004-12-11 03:31:25 +01:00
|
|
|
return 1 << ((from << 2) | to);
|
2001-11-06 04:07:21 +01:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
const vvp_fun_edge::edge_t vvp_edge_posedge
|
|
|
|
|
= VVP_EDGE(BIT4_0,BIT4_1)
|
|
|
|
|
| VVP_EDGE(BIT4_0,BIT4_X)
|
|
|
|
|
| VVP_EDGE(BIT4_0,BIT4_Z)
|
|
|
|
|
| VVP_EDGE(BIT4_X,BIT4_1)
|
|
|
|
|
| VVP_EDGE(BIT4_Z,BIT4_1)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
const vvp_fun_edge::edge_t vvp_edge_negedge
|
|
|
|
|
= VVP_EDGE(BIT4_1,BIT4_0)
|
|
|
|
|
| VVP_EDGE(BIT4_1,BIT4_X)
|
|
|
|
|
| VVP_EDGE(BIT4_1,BIT4_Z)
|
|
|
|
|
| VVP_EDGE(BIT4_X,BIT4_0)
|
|
|
|
|
| VVP_EDGE(BIT4_Z,BIT4_0)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
const vvp_fun_edge::edge_t vvp_edge_none = 0;
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
struct vvp_fun_edge_state_s : public waitable_state_s {
|
|
|
|
|
vvp_fun_edge_state_s() : bit(BIT4_X) {}
|
|
|
|
|
|
|
|
|
|
vvp_bit4_t bit;
|
|
|
|
|
};
|
|
|
|
|
|
2006-11-22 07:10:05 +01:00
|
|
|
vvp_fun_edge::vvp_fun_edge(edge_t e, bool debug_flag)
|
|
|
|
|
: edge_(e), debug_(debug_flag)
|
2002-07-17 20:30:01 +02:00
|
|
|
{
|
2004-12-30 00:45:13 +01:00
|
|
|
bits_[0] = BIT4_X;
|
|
|
|
|
bits_[1] = BIT4_X;
|
|
|
|
|
bits_[2] = BIT4_X;
|
|
|
|
|
bits_[3] = BIT4_X;
|
2002-07-17 20:30:01 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_fun_edge::~vvp_fun_edge()
|
2002-05-19 07:18:16 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
void vvp_fun_edge::alloc_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
vvp_set_context_item(context, context_idx, new vvp_fun_edge_state_s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_fun_edge::reset_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
|
|
|
|
(vvp_get_context_item(context, context_idx));
|
|
|
|
|
state->threads = 0;
|
|
|
|
|
state->bit = BIT4_X;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
2002-05-19 07:18:16 +02:00
|
|
|
{
|
2008-09-27 01:54:13 +02:00
|
|
|
vvp_bit4_t*old_bit;
|
|
|
|
|
if (context_idx) {
|
|
|
|
|
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
|
|
|
|
(vthread_get_wt_context_item(context_idx));
|
|
|
|
|
old_bit = &state->bit;
|
|
|
|
|
} else {
|
|
|
|
|
old_bit = &bits_[port.port()];
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/* See what kind of edge this represents. */
|
2008-09-27 01:54:13 +02:00
|
|
|
edge_t mask = VVP_EDGE(*old_bit, bit.value(0));
|
2002-05-19 07:18:16 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/* Save the current input for the next time around. */
|
2008-09-27 01:54:13 +02:00
|
|
|
*old_bit = bit.value(0);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2004-12-18 19:52:44 +01:00
|
|
|
if ((edge_ == vvp_edge_none) || (edge_ & mask)) {
|
2008-09-27 01:54:13 +02:00
|
|
|
run_waiting_threads_(context_idx);
|
2004-12-18 19:52:44 +01:00
|
|
|
|
|
|
|
|
vvp_net_t*net = port.ptr();
|
|
|
|
|
vvp_send_vec4(net->out, bit);
|
2002-05-19 07:18:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-30 00:45:13 +01:00
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
struct vvp_fun_anyedge_state_s : public waitable_state_s {
|
|
|
|
|
vvp_fun_anyedge_state_s() : bitsr(0.0) {}
|
|
|
|
|
|
|
|
|
|
vvp_vector4_t bits;
|
|
|
|
|
double bitsr;
|
|
|
|
|
};
|
|
|
|
|
|
2006-11-22 07:10:05 +01:00
|
|
|
vvp_fun_anyedge::vvp_fun_anyedge(bool debug_flag)
|
|
|
|
|
: debug_(debug_flag)
|
2004-12-30 00:45:13 +01:00
|
|
|
{
|
2006-12-09 20:06:53 +01:00
|
|
|
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
|
|
|
|
bitsr_[idx] = 0.0;
|
2004-12-30 00:45:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_fun_anyedge::~vvp_fun_anyedge()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
void vvp_fun_anyedge::alloc_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
vvp_set_context_item(context, context_idx, new vvp_fun_anyedge_state_s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_fun_anyedge::reset_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
|
|
|
|
(vvp_get_context_item(context, context_idx));
|
|
|
|
|
state->threads = 0;
|
|
|
|
|
state->bits.set_to_x();
|
|
|
|
|
state->bitsr = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void vvp_fun_anyedge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
2004-12-30 00:45:13 +01:00
|
|
|
{
|
|
|
|
|
bool flag = false;
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
vvp_vector4_t*old_bits;
|
|
|
|
|
if (context_idx) {
|
|
|
|
|
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
|
|
|
|
(vthread_get_wt_context_item(context_idx));
|
|
|
|
|
old_bits = &state->bits;
|
|
|
|
|
} else {
|
|
|
|
|
old_bits = &bits_[port.port()];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (old_bits->size() != bit.size()) {
|
2004-12-30 00:45:13 +01:00
|
|
|
flag = true;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1) {
|
2008-09-27 01:54:13 +02:00
|
|
|
if (old_bits->value(idx) != bit.value(idx)) {
|
2004-12-30 00:45:13 +01:00
|
|
|
flag = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flag) {
|
2008-09-27 01:54:13 +02:00
|
|
|
*old_bits = bit;
|
|
|
|
|
run_waiting_threads_(context_idx);
|
2004-12-30 00:45:13 +01:00
|
|
|
vvp_net_t*net = port.ptr();
|
|
|
|
|
vvp_send_vec4(net->out, bit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-09 20:06:53 +01:00
|
|
|
void vvp_fun_anyedge::recv_real(vvp_net_ptr_t port, double bit)
|
|
|
|
|
{
|
2008-09-27 01:54:13 +02:00
|
|
|
double*old_bits;
|
|
|
|
|
if (context_idx) {
|
|
|
|
|
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
|
|
|
|
(vthread_get_wt_context_item(context_idx));
|
|
|
|
|
old_bits = &state->bitsr;
|
|
|
|
|
} else {
|
|
|
|
|
old_bits = &bitsr_[port.port()];
|
2006-12-09 20:06:53 +01:00
|
|
|
}
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
if (*old_bits != bit) {
|
|
|
|
|
*old_bits = bit;
|
|
|
|
|
run_waiting_threads_(context_idx);
|
2006-12-09 20:06:53 +01:00
|
|
|
vvp_net_t*net = port.ptr();
|
|
|
|
|
vvp_send_vec4(net->out, vvp_vector4_t());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-25 07:44:51 +02:00
|
|
|
vvp_fun_event_or::vvp_fun_event_or()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_fun_event_or::~vvp_fun_event_or()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
void vvp_fun_event_or::alloc_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
vvp_set_context_item(context, context_idx, new waitable_state_s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_fun_event_or::reset_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
waitable_state_s*state = static_cast<waitable_state_s*>
|
|
|
|
|
(vvp_get_context_item(context, context_idx));
|
|
|
|
|
state->threads = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void vvp_fun_event_or::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
2005-05-25 07:44:51 +02:00
|
|
|
{
|
2008-09-27 01:54:13 +02:00
|
|
|
run_waiting_threads_(context_idx);
|
2005-05-25 07:44:51 +02:00
|
|
|
vvp_net_t*net = port.ptr();
|
|
|
|
|
vvp_send_vec4(net->out, bit);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-18 19:52:44 +01:00
|
|
|
vvp_named_event::vvp_named_event(struct __vpiHandle*h)
|
|
|
|
|
{
|
|
|
|
|
handle_ = h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vvp_named_event::~vvp_named_event()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
void vvp_named_event::alloc_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
vvp_set_context_item(context, context_idx, new waitable_state_s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvp_named_event::reset_instance(vvp_context_t context)
|
|
|
|
|
{
|
|
|
|
|
waitable_state_s*state = static_cast<waitable_state_s*>
|
|
|
|
|
(vvp_get_context_item(context, context_idx));
|
|
|
|
|
state->threads = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void vvp_named_event::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
2004-12-18 19:52:44 +01:00
|
|
|
{
|
2008-09-27 01:54:13 +02:00
|
|
|
run_waiting_threads_(context_idx);
|
2004-12-18 19:52:44 +01:00
|
|
|
vvp_net_t*net = port.ptr();
|
|
|
|
|
vvp_send_vec4(net->out, bit);
|
2006-02-21 05:57:26 +01:00
|
|
|
|
|
|
|
|
vpip_run_named_event_callbacks(handle_);
|
2004-12-18 19:52:44 +01:00
|
|
|
}
|
|
|
|
|
|
2001-11-06 04:07:21 +01:00
|
|
|
/*
|
|
|
|
|
** Create an event functor
|
2006-11-22 07:10:05 +01:00
|
|
|
** edge: compile_event(label, type, argc, argv, debug_flag)
|
|
|
|
|
** or: compile_event(label, NULL, argc, argv, debug_flag)
|
2002-05-18 04:34:11 +02:00
|
|
|
**
|
|
|
|
|
** Named events are handled elsewhere.
|
2001-11-06 04:07:21 +01:00
|
|
|
*/
|
|
|
|
|
|
2005-05-25 07:44:51 +02:00
|
|
|
static void compile_event_or(char*label, unsigned argc, struct symb_s*argv);
|
|
|
|
|
|
2001-11-06 04:07:21 +01:00
|
|
|
void compile_event(char*label, char*type,
|
2006-11-22 07:10:05 +01:00
|
|
|
unsigned argc, struct symb_s*argv,
|
|
|
|
|
bool debug_flag)
|
2001-11-06 04:07:21 +01:00
|
|
|
{
|
2004-12-30 00:45:13 +01:00
|
|
|
vvp_net_fun_t*fun = 0;
|
2001-11-06 04:07:21 +01:00
|
|
|
|
2005-05-25 07:44:51 +02:00
|
|
|
if (type == 0) {
|
|
|
|
|
compile_event_or(label, argc, argv);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strcmp(type,"edge") == 0) {
|
2001-11-06 04:07:21 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
free(type);
|
2008-09-27 01:54:13 +02:00
|
|
|
vvp_fun_anyedge*event_fun = new vvp_fun_anyedge(debug_flag);
|
|
|
|
|
vpip_add_item_to_current_scope(event_fun);
|
|
|
|
|
fun = event_fun;
|
2004-12-30 00:45:13 +01:00
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
vvp_fun_edge::edge_t edge = vvp_edge_none;
|
2001-11-06 04:07:21 +01:00
|
|
|
|
2005-05-25 07:44:51 +02:00
|
|
|
if (strcmp(type,"posedge") == 0)
|
|
|
|
|
edge = vvp_edge_posedge;
|
|
|
|
|
else if (strcmp(type,"negedge") == 0)
|
|
|
|
|
edge = vvp_edge_negedge;
|
2004-12-30 00:45:13 +01:00
|
|
|
|
2005-05-25 07:44:51 +02:00
|
|
|
assert(argc <= 4);
|
|
|
|
|
free(type);
|
2004-12-30 00:45:13 +01:00
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
vvp_fun_edge*event_fun = new vvp_fun_edge(edge, debug_flag);
|
|
|
|
|
vpip_add_item_to_current_scope(event_fun);
|
|
|
|
|
fun = event_fun;
|
2004-12-30 00:45:13 +01:00
|
|
|
}
|
2001-11-06 04:07:21 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_net_t* ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = fun;
|
2001-11-06 04:07:21 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
define_functor_symbol(label, ptr);
|
2001-11-06 04:07:21 +01:00
|
|
|
free(label);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
inputs_connect(ptr, argc, argv);
|
2001-11-06 04:07:21 +01:00
|
|
|
}
|
|
|
|
|
|
2005-05-25 07:44:51 +02:00
|
|
|
static void compile_event_or(char*label, unsigned argc, struct symb_s*argv)
|
|
|
|
|
{
|
2008-09-27 01:54:13 +02:00
|
|
|
vvp_fun_event_or*fun = new vvp_fun_event_or;
|
2005-05-25 07:44:51 +02:00
|
|
|
vvp_net_t* ptr = new vvp_net_t;
|
|
|
|
|
ptr->fun = fun;
|
|
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
vpip_add_item_to_current_scope(fun);
|
2005-05-25 07:44:51 +02:00
|
|
|
define_functor_symbol(label, ptr);
|
|
|
|
|
free(label);
|
|
|
|
|
|
|
|
|
|
/* This is a very special case. Point all the source inputs to
|
|
|
|
|
the same input. It doesn't matter that the streams get
|
|
|
|
|
tangled because data values are irrelevant. */
|
|
|
|
|
for (unsigned idx = 0 ; idx < argc ; idx += 1) {
|
|
|
|
|
input_connect(ptr, 0, argv[idx].text);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-18 04:34:11 +02:00
|
|
|
/*
|
|
|
|
|
* This handles the compile of named events. This functor has no
|
|
|
|
|
* inputs, it is only accessed by behavioral trigger statements, which
|
|
|
|
|
* in vvp are %set instructions.
|
|
|
|
|
*/
|
|
|
|
|
void compile_named_event(char*label, char*name)
|
|
|
|
|
{
|
2004-12-18 19:52:44 +01:00
|
|
|
vvp_net_t*ptr = new vvp_net_t;
|
2003-04-23 05:09:25 +02:00
|
|
|
|
2004-12-18 19:52:44 +01:00
|
|
|
vpiHandle obj = vpip_make_named_event(name, ptr);
|
2008-09-27 01:54:13 +02:00
|
|
|
vvp_named_event*fun = new vvp_named_event(obj);
|
|
|
|
|
ptr->fun = fun;
|
2002-05-18 04:34:11 +02:00
|
|
|
|
2008-09-27 01:54:13 +02:00
|
|
|
vpip_add_item_to_current_scope(fun);
|
2004-12-18 19:52:44 +01:00
|
|
|
define_functor_symbol(label, ptr);
|
2003-04-23 05:09:25 +02:00
|
|
|
compile_vpi_symbol(label, obj);
|
|
|
|
|
vpip_attach_to_current_scope(obj);
|
2002-05-18 04:34:11 +02:00
|
|
|
|
|
|
|
|
free(label);
|
2002-07-05 19:14:15 +02:00
|
|
|
free(name);
|
2002-05-18 04:34:11 +02:00
|
|
|
}
|