Merge branch 'master' into verilog-ams
[sverilog.git] / pform_disciplines.cc
blob82f78708b375aaa478123338ec85ac5f18b2f79f
1 /*
2 * Copyright (c) 2008 Stephen Williams (steve@icarus.com)
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 # include "config.h"
21 # include "compiler.h"
22 # include "pform.h"
23 # include "parse_misc.h"
24 # include "discipline.h"
26 map<perm_string,nature_t*> natures;
27 map<perm_string,discipline_t*> disciplines;
29 static perm_string nature_name = perm_string::perm_string();
30 static perm_string nature_access = perm_string::perm_string();
32 void pform_start_nature(const char*name)
34 nature_name = lex_strings.make(name);
37 void pform_nature_access(const struct vlltype&loc, const char*name)
39 if (nature_access) {
40 cerr << loc.text << ":" << loc.first_line << ": error: "
41 << "Too many access names for nature "
42 << nature_name << "." << endl;
43 error_count += 1;
44 return;
47 nature_access = lex_strings.make(name);
50 void pform_end_nature(const struct vlltype&loc)
52 // The nature access function is required. If it is missing,
53 // then signal an error. For a temporary expedient, we can set
54 // the nature name as the access function, but don't expect it
55 // to work.
56 if (! nature_access) {
57 cerr << loc.text << ":" << loc.first_line << ": error: "
58 << "Missing access name for nature "
59 << nature_name << "." << endl;
60 error_count += 1;
61 nature_access = nature_name;
64 nature_t*tmp = new nature_t(nature_name, nature_access);
65 natures[nature_name] = tmp;
67 FILE_NAME(tmp, loc);
69 nature_name = perm_string::perm_string();
70 nature_access = perm_string::perm_string();
74 static perm_string discipline_name;
75 static ddomain_t discipline_domain = DD_NONE;
76 static nature_t* discipline_potential = 0;
77 static nature_t* discipline_flow = 0;
79 void pform_start_discipline(const char*name)
81 discipline_name = lex_strings.make(name);
82 discipline_domain = DD_NONE;
85 void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain)
87 assert(use_domain != DD_NONE);
89 if (discipline_domain != DD_NONE) {
90 cerr << loc.text << ":" << loc.first_line << ": error: "
91 << "Too many domain attributes for discipline "
92 << discipline_name << "." << endl;
93 error_count += 1;
94 return;
97 discipline_domain = use_domain;
100 void pform_discipline_potential(const struct vlltype&loc, const char*name)
102 if (discipline_potential) {
103 cerr << loc.text << ":" << loc.first_line << ": error: "
104 << "Too many potential natures for discipline "
105 << discipline_name << "." << endl;
106 error_count += 1;
107 return;
110 perm_string key = lex_strings.make(name);
111 discipline_potential = natures[key];
113 if (discipline_potential == 0) {
114 cerr << loc.text << ":" << loc.first_line << ": error: "
115 << "nature " << key << " is not declared." << endl;
116 error_count += 1;
117 return;
121 void pform_discipline_flow(const struct vlltype&loc, const char*name)
123 if (discipline_flow) {
124 cerr << loc.text << ":" << loc.first_line << ": error: "
125 << "Too many flow natures for discipline "
126 << discipline_name << "." << endl;
127 error_count += 1;
128 return;
131 perm_string key = lex_strings.make(name);
132 discipline_flow = natures[key];
134 if (discipline_flow == 0) {
135 cerr << loc.text << ":" << loc.first_line << ": error: "
136 << "nature " << key << " is not declared." << endl;
137 error_count += 1;
138 return;
142 void pform_end_discipline(const struct vlltype&loc)
144 // If the domain is not otherwise specified, then take it to
145 // be continuous if potential or flow natures are given.
146 if (discipline_domain == DD_NONE && (discipline_potential||discipline_flow))
147 discipline_domain = DD_CONTINUOUS;
149 discipline_t*tmp = new discipline_t(discipline_name, discipline_domain,
150 discipline_potential, discipline_flow);
151 disciplines[discipline_name] = tmp;
153 FILE_NAME(tmp, loc);
155 /* Clear the static variables for the next item. */
156 discipline_name = perm_string::perm_string();
157 discipline_domain = DD_NONE;
158 discipline_potential = 0;
159 discipline_flow = 0;
163 * The parser uses this function to attach a discipline to a wire. The
164 * wire may be declared by now, or will be declared further later. If
165 * it is already declared, we just attach the discipline. If it is not
166 * declared yet, then this is the declaration and we create the signal
167 * in the current lexical scope.
169 void pform_attach_discipline(const struct vlltype&loc,
170 discipline_t*discipline, list<perm_string>*names)
172 for (list<perm_string>::iterator cur = names->begin()
173 ; cur != names->end() ; cur ++ ) {
175 PWire* cur_net = pform_get_wire_in_scope(*cur);
176 if (cur_net == 0) {
177 /* Not declared yet, declare it now. */
178 pform_makewire(loc, *cur, NetNet::WIRE,
179 NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
180 cur_net = pform_get_wire_in_scope(*cur);
181 assert(cur_net);
184 if (discipline_t*tmp = cur_net->get_discipline()) {
185 cerr << loc.text << ":" << loc.first_line << ": error: "
186 << "discipline " << discipline->name()
187 << " cannot override existing discipline " << tmp->name()
188 << " on net " << cur_net->basename() << endl;
189 error_count += 1;
191 } else {
192 cur_net->set_discipline(discipline);