forked from steveicarus/iverilog
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnet_func.cc
128 lines (106 loc) · 3.3 KB
/
net_func.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* Copyright (c) 2002-2021 Stephen Williams ([email protected])
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include "netlist.h"
# include "compiler.h"
# include "PExpr.h"
# include <iostream>
using namespace std;
/*
* To make a NetUserFunc device, make as many pins as there are ports
* in the function. Get the port count from the function definition,
* which accounts for all the inputs, plus one for the phantom output
* that is the result.
*/
NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d,
NetEvWait*trigger__)
: NetNode(s, n, d->func_def()->port_count()+1),
def_(d), trigger_(trigger__)
{
pin(0).set_dir(Link::OUTPUT);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).drive0(IVL_DR_HiZ);
pin(idx).drive1(IVL_DR_HiZ);
}
}
NetUserFunc::~NetUserFunc()
{
}
unsigned NetUserFunc::port_width(unsigned port) const
{
NetFuncDef*fdef = def_->func_def();
/* Port 0 is the return port. */
if (port == 0) {
const NetNet*sig = fdef->return_sig();
assert(sig);
return sig->vector_width();
}
port -= 1;
assert(port < fdef->port_count());
const NetNet*port_sig = fdef->port(port);
return port_sig->vector_width();
}
const NetScope* NetUserFunc::def() const
{
return def_;
}
/*
* This method of the PECallFunction class checks that the parameters
* of the PECallFunction match the function definition. This is used
* during elaboration to validate the parameters before using them.
*/
bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope) const
{
assert(dscope);
if (dscope->type() != NetScope::FUNC) {
cerr << get_fileline() << ": error: Attempt to call scope "
<< scope_path(dscope) << " as a function." << endl;
des->errors += 1;
return false;
}
return true;
}
NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
const struct sfunc_return_type*def,
unsigned ports, NetEvWait*trigger__)
: NetNode(s, n, ports), def_(def), trigger_(trigger__)
{
pin(0).set_dir(Link::OUTPUT); // Q
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).drive0(IVL_DR_HiZ);
pin(idx).drive1(IVL_DR_HiZ);
}
}
NetSysFunc::~NetSysFunc()
{
}
const char*NetSysFunc::func_name() const
{
return def_->name;
}
ivl_variable_type_t NetSysFunc::data_type() const
{
return def_->type;
}
unsigned NetSysFunc::vector_width() const
{
return def_->wid;
}