1 /*
2 * Copyright (c) 2008-2010 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 "config.h"
21 # include "compiler.h"
22 # include "pform.h"
23 # include "parse_misc.h"
24 # include "discipline.h"
25
26 map<perm_string,ivl_nature_t> natures;
27 map<perm_string,ivl_discipline_t> disciplines;
28 map<perm_string,ivl_nature_t> access_function_nature;
29
30 static perm_string nature_name = perm_string();
31 static perm_string nature_access = perm_string();
32
pform_start_nature(const char * name)33 void pform_start_nature(const char*name)
34 {
35 nature_name = lex_strings.make(name);
36 }
37
pform_nature_access(const struct vlltype & loc,const char * name)38 void pform_nature_access(const struct vlltype&loc, const char*name)
39 {
40 if (nature_access) {
41 cerr << loc.text << ":" << loc.first_line << ": error: "
42 << "Too many access names for nature "
43 << nature_name << "." << endl;
44 error_count += 1;
45 return;
46 }
47
48 nature_access = lex_strings.make(name);
49 }
50
pform_end_nature(const struct vlltype & loc)51 void pform_end_nature(const struct vlltype&loc)
52 {
53 // The nature access function is required. If it is missing,
54 // then signal an error. For a temporary expedient, we can set
55 // the nature name as the access function, but don't expect it
56 // to work.
57 if (! nature_access) {
58 cerr << loc.text << ":" << loc.first_line << ": error: "
59 << "Missing access name for nature "
60 << nature_name << "." << endl;
61 error_count += 1;
62 nature_access = nature_name;
63 }
64
65 ivl_nature_s*tmp = new ivl_nature_s(nature_name, nature_access);
66 FILE_NAME(tmp, loc);
67
68 natures[nature_name] = tmp;
69
70 // Make sure the access function is not used by multiple
71 // different natures.
72 if (ivl_nature_t dup_access_nat = access_function_nature[nature_access]) {
73 cerr << tmp->get_fileline() << ": error: "
74 << "Access function name " << nature_access
75 << " is already used by nature " << dup_access_nat->name()
76 << " declared at " << dup_access_nat->get_fileline()
77 << "." << endl;
78 error_count += 1;
79 }
80
81 // Map the access function back to the nature so that
82 // expressions that use the access function can find it.
83 access_function_nature[nature_access] = tmp;
84
85 nature_name = perm_string();
86 nature_access = perm_string();
87 }
88
89
90 static perm_string discipline_name;
91 static ivl_dis_domain_t discipline_domain = IVL_DIS_NONE;
92 static ivl_nature_t discipline_potential = 0;
93 static ivl_nature_t discipline_flow = 0;
94
pform_start_discipline(const char * name)95 void pform_start_discipline(const char*name)
96 {
97 discipline_name = lex_strings.make(name);
98 discipline_domain = IVL_DIS_NONE;
99 }
100
pform_discipline_domain(const struct vlltype & loc,ivl_dis_domain_t use_domain)101 void pform_discipline_domain(const struct vlltype&loc, ivl_dis_domain_t use_domain)
102 {
103 assert(use_domain != IVL_DIS_NONE);
104
105 if (discipline_domain != IVL_DIS_NONE) {
106 cerr << loc.text << ":" << loc.first_line << ": error: "
107 << "Too many domain attributes for discipline "
108 << discipline_name << "." << endl;
109 error_count += 1;
110 return;
111 }
112
113 discipline_domain = use_domain;
114 }
115
pform_discipline_potential(const struct vlltype & loc,const char * name)116 void pform_discipline_potential(const struct vlltype&loc, const char*name)
117 {
118 if (discipline_potential) {
119 cerr << loc.text << ":" << loc.first_line << ": error: "
120 << "Too many potential natures for discipline "
121 << discipline_name << "." << endl;
122 error_count += 1;
123 return;
124 }
125
126 perm_string key = lex_strings.make(name);
127 discipline_potential = natures[key];
128
129 if (discipline_potential == 0) {
130 cerr << loc.text << ":" << loc.first_line << ": error: "
131 << "nature " << key << " is not declared." << endl;
132 error_count += 1;
133 return;
134 }
135 }
136
pform_discipline_flow(const struct vlltype & loc,const char * name)137 void pform_discipline_flow(const struct vlltype&loc, const char*name)
138 {
139 if (discipline_flow) {
140 cerr << loc.text << ":" << loc.first_line << ": error: "
141 << "Too many flow natures for discipline "
142 << discipline_name << "." << endl;
143 error_count += 1;
144 return;
145 }
146
147 perm_string key = lex_strings.make(name);
148 discipline_flow = natures[key];
149
150 if (discipline_flow == 0) {
151 cerr << loc.text << ":" << loc.first_line << ": error: "
152 << "nature " << key << " is not declared." << endl;
153 error_count += 1;
154 return;
155 }
156 }
157
pform_end_discipline(const struct vlltype & loc)158 void pform_end_discipline(const struct vlltype&loc)
159 {
160 // If the domain is not otherwise specified, then take it to
161 // be continuous if potential or flow natures are given.
162 if (discipline_domain == IVL_DIS_NONE && (discipline_potential||discipline_flow))
163 discipline_domain = IVL_DIS_CONTINUOUS;
164
165 ivl_discipline_t tmp = new ivl_discipline_s(discipline_name,
166 discipline_domain,
167 discipline_potential,
168 discipline_flow);
169 disciplines[discipline_name] = tmp;
170
171 FILE_NAME(tmp, loc);
172
173 /* Clear the static variables for the next item. */
174 discipline_name = perm_string();
175 discipline_domain = IVL_DIS_NONE;
176 discipline_potential = 0;
177 discipline_flow = 0;
178 }
179
180 /*
181 * The parser uses this function to attach a discipline to a wire. The
182 * wire may be declared by now, or will be declared further later. If
183 * it is already declared, we just attach the discipline. If it is not
184 * declared yet, then this is the declaration and we create the signal
185 * in the current lexical scope.
186 */
pform_attach_discipline(const struct vlltype & loc,ivl_discipline_t discipline,list<perm_string> * names)187 void pform_attach_discipline(const struct vlltype&loc,
188 ivl_discipline_t discipline, list<perm_string>*names)
189 {
190 for (list<perm_string>::iterator cur = names->begin()
191 ; cur != names->end() ; ++ cur ) {
192
193 PWire* cur_net = pform_get_wire_in_scope(*cur);
194 if (cur_net == 0) {
195 /* Not declared yet, declare it now. */
196 pform_makewire(loc, *cur, NetNet::WIRE,
197 NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
198 cur_net = pform_get_wire_in_scope(*cur);
199 assert(cur_net);
200 }
201
202 if (ivl_discipline_t tmp = cur_net->get_discipline()) {
203 cerr << loc.text << ":" << loc.first_line << ": error: "
204 << "discipline " << discipline->name()
205 << " cannot override existing discipline " << tmp->name()
206 << " on net " << cur_net->basename() << endl;
207 error_count += 1;
208
209 } else {
210 cur_net->set_data_type(IVL_VT_REAL);
211 cur_net->set_discipline(discipline);
212 }
213 }
214 }
215