1 /*
2 * Copyright (c) 2002-2017 Stephen Williams (steve@icarus.com)
3 *
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 # include "compile.h"
21 # include "vpi_priv.h"
22 # include <cstdio>
23 # include <cstdlib>
24 # include <cstring>
25 # include <cassert>
26 # include "ivl_alloc.h"
27
__vpiNamedEvent(__vpiScope * sc,const char * nam)28 inline __vpiNamedEvent::__vpiNamedEvent(__vpiScope*sc, const char*nam)
29 {
30 scope_ = sc;
31 name_ = vpip_name_string(nam);
32 callbacks_ = 0;
33 }
34
~__vpiNamedEvent()35 __vpiNamedEvent::~__vpiNamedEvent()
36 {
37 while (callbacks_) {
38 struct __vpiCallback *tmp = callbacks_->next;
39 delete callbacks_;
40 callbacks_ = tmp;
41 }
42 }
43
get_type_code(void) const44 int __vpiNamedEvent::get_type_code(void) const
45 { return vpiNamedEvent; }
46
vpi_get(int code)47 int __vpiNamedEvent::vpi_get(int code)
48 {
49 switch (code) {
50
51 case vpiAutomatic:
52 return scope_->is_automatic()? 1 : 0;
53 }
54
55 return 0;
56 }
57
vpi_get_str(int code)58 char* __vpiNamedEvent::vpi_get_str(int code)
59 {
60 if (code == vpiFile) { // Not implemented for now!
61 return simple_set_rbuf_str(file_names[0]);
62 }
63 return generic_get_str(code, scope_, name_, NULL);
64 }
65
vpi_put_value(p_vpi_value,int)66 vpiHandle __vpiNamedEvent::vpi_put_value(p_vpi_value, int)
67 {
68 // p_vpi_value may be NULL, and an event doesn't care
69 // what the value is
70 vvp_vector4_t val;
71 vvp_net_ptr_t dest(funct, 0);
72 vvp_send_vec4(dest, val, vthread_get_wt_context());
73
74 return this;
75 }
76
vpi_handle(int code)77 vpiHandle __vpiNamedEvent::vpi_handle(int code)
78 {
79 switch (code) {
80 case vpiScope:
81 return scope_;
82
83 case vpiModule:
84 return vpip_module(scope_);
85 }
86
87 return 0;
88 }
89
90
vpip_make_named_event(const char * name,vvp_net_t * funct)91 vpiHandle vpip_make_named_event(const char*name, vvp_net_t*funct)
92 {
93 __vpiNamedEvent*obj = new __vpiNamedEvent(vpip_peek_current_scope(), name);
94
95 obj->funct = funct;
96
97 return obj;
98 }
99
100 /*
101 * This function runs the callbacks for a named event. All the
102 * callbacks are listed in the callback member of the event handle,
103 * this function scans that list.
104 *
105 * This also handles the case where the callback has been removed. The
106 * vpi_remove_cb doesn't actually remove any callbacks, it marks them
107 * as canceled by clearing the cb_rtn function. This function reaps
108 * those marked handles when it scans the list.
109 *
110 * We can not use vpi_free_object() here since it does not really
111 * delete the callback.
112 */
run_vpi_callbacks()113 void __vpiNamedEvent::run_vpi_callbacks()
114 {
115 struct __vpiCallback*next = callbacks_;
116 struct __vpiCallback*prev = 0;
117 while (next) {
118 struct __vpiCallback*cur = next;
119 next = cur->next;
120
121 if (cur->cb_data.cb_rtn != 0) {
122 callback_execute(cur);
123 prev = cur;
124
125 } else if (prev == 0) {
126 callbacks_ = next;
127 cur->next = 0;
128 delete cur;
129
130 } else {
131 assert(prev->next == cur);
132 prev->next = next;
133 cur->next = 0;
134 delete cur;
135 }
136 }
137 }
138