2008-05-11 21:00:11 +02:00
|
|
|
/*
|
2021-11-04 17:12:04 +01:00
|
|
|
* Copyright (c) 2008-2021 Stephen Williams (steve@icarus.com)
|
2008-05-11 21:00:11 +02: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
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2008-05-11 21:00:11 +02:00
|
|
|
*/
|
|
|
|
|
|
2022-10-12 04:31:35 +02:00
|
|
|
# include <cstdarg>
|
2008-05-11 21:00:11 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
# include "compiler.h"
|
|
|
|
|
# include "pform.h"
|
|
|
|
|
# include "parse_misc.h"
|
|
|
|
|
# include "discipline.h"
|
2023-04-13 22:00:34 +02:00
|
|
|
# include "ivl_assert.h"
|
2008-05-11 21:00:11 +02:00
|
|
|
|
2021-11-04 17:12:04 +01:00
|
|
|
using namespace std;
|
|
|
|
|
|
2008-11-04 06:10:10 +01:00
|
|
|
map<perm_string,ivl_nature_t> natures;
|
2008-11-02 17:10:41 +01:00
|
|
|
map<perm_string,ivl_discipline_t> disciplines;
|
2008-11-04 06:10:10 +01:00
|
|
|
map<perm_string,ivl_nature_t> access_function_nature;
|
2008-05-11 21:00:11 +02:00
|
|
|
|
2010-01-13 21:23:36 +01:00
|
|
|
static perm_string nature_name = perm_string();
|
|
|
|
|
static perm_string nature_access = perm_string();
|
2008-05-12 03:52:27 +02:00
|
|
|
|
|
|
|
|
void pform_start_nature(const char*name)
|
|
|
|
|
{
|
|
|
|
|
nature_name = lex_strings.make(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pform_nature_access(const struct vlltype&loc, const char*name)
|
|
|
|
|
{
|
|
|
|
|
if (nature_access) {
|
|
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "Too many access names for nature "
|
|
|
|
|
<< nature_name << "." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nature_access = lex_strings.make(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pform_end_nature(const struct vlltype&loc)
|
|
|
|
|
{
|
|
|
|
|
// The nature access function is required. If it is missing,
|
|
|
|
|
// then signal an error. For a temporary expedient, we can set
|
|
|
|
|
// the nature name as the access function, but don't expect it
|
|
|
|
|
// to work.
|
|
|
|
|
if (! nature_access) {
|
|
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "Missing access name for nature "
|
|
|
|
|
<< nature_name << "." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
nature_access = nature_name;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-04 06:10:10 +01:00
|
|
|
ivl_nature_s*tmp = new ivl_nature_s(nature_name, nature_access);
|
2008-07-31 03:01:41 +02:00
|
|
|
FILE_NAME(tmp, loc);
|
|
|
|
|
|
2008-05-12 03:52:27 +02:00
|
|
|
natures[nature_name] = tmp;
|
|
|
|
|
|
2008-07-31 03:01:41 +02:00
|
|
|
// Make sure the access function is not used by multiple
|
|
|
|
|
// different natures.
|
2008-11-04 06:10:10 +01:00
|
|
|
if (ivl_nature_t dup_access_nat = access_function_nature[nature_access]) {
|
2008-07-31 03:01:41 +02:00
|
|
|
cerr << tmp->get_fileline() << ": error: "
|
|
|
|
|
<< "Access function name " << nature_access
|
|
|
|
|
<< " is already used by nature " << dup_access_nat->name()
|
|
|
|
|
<< " declared at " << dup_access_nat->get_fileline()
|
|
|
|
|
<< "." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-09 18:30:47 +02:00
|
|
|
// Map the access function back to the nature so that
|
2008-07-31 03:01:41 +02:00
|
|
|
// expressions that use the access function can find it.
|
|
|
|
|
access_function_nature[nature_access] = tmp;
|
2008-05-12 03:52:27 +02:00
|
|
|
|
2010-01-13 21:23:36 +01:00
|
|
|
nature_name = perm_string();
|
|
|
|
|
nature_access = perm_string();
|
2008-05-12 03:52:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-05-11 21:00:11 +02:00
|
|
|
static perm_string discipline_name;
|
2008-11-02 17:10:41 +01:00
|
|
|
static ivl_dis_domain_t discipline_domain = IVL_DIS_NONE;
|
2008-11-04 06:10:10 +01:00
|
|
|
static ivl_nature_t discipline_potential = 0;
|
|
|
|
|
static ivl_nature_t discipline_flow = 0;
|
2008-05-11 21:00:11 +02:00
|
|
|
|
|
|
|
|
void pform_start_discipline(const char*name)
|
|
|
|
|
{
|
|
|
|
|
discipline_name = lex_strings.make(name);
|
2008-11-02 17:10:41 +01:00
|
|
|
discipline_domain = IVL_DIS_NONE;
|
2008-05-11 21:00:11 +02:00
|
|
|
}
|
|
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
void pform_discipline_domain(const struct vlltype&loc, ivl_dis_domain_t use_domain)
|
2008-05-12 03:52:27 +02:00
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(loc, use_domain != IVL_DIS_NONE);
|
2008-05-12 03:52:27 +02:00
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
if (discipline_domain != IVL_DIS_NONE) {
|
2008-05-12 03:52:27 +02:00
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "Too many domain attributes for discipline "
|
|
|
|
|
<< discipline_name << "." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
discipline_domain = use_domain;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pform_discipline_potential(const struct vlltype&loc, const char*name)
|
|
|
|
|
{
|
|
|
|
|
if (discipline_potential) {
|
|
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "Too many potential natures for discipline "
|
|
|
|
|
<< discipline_name << "." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
perm_string key = lex_strings.make(name);
|
|
|
|
|
discipline_potential = natures[key];
|
|
|
|
|
|
|
|
|
|
if (discipline_potential == 0) {
|
|
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "nature " << key << " is not declared." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pform_discipline_flow(const struct vlltype&loc, const char*name)
|
|
|
|
|
{
|
|
|
|
|
if (discipline_flow) {
|
|
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "Too many flow natures for discipline "
|
|
|
|
|
<< discipline_name << "." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
perm_string key = lex_strings.make(name);
|
|
|
|
|
discipline_flow = natures[key];
|
|
|
|
|
|
|
|
|
|
if (discipline_flow == 0) {
|
|
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "nature " << key << " is not declared." << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-11 21:00:11 +02:00
|
|
|
void pform_end_discipline(const struct vlltype&loc)
|
|
|
|
|
{
|
2008-05-12 03:52:27 +02:00
|
|
|
// If the domain is not otherwise specified, then take it to
|
|
|
|
|
// be continuous if potential or flow natures are given.
|
2008-11-02 17:10:41 +01:00
|
|
|
if (discipline_domain == IVL_DIS_NONE && (discipline_potential||discipline_flow))
|
|
|
|
|
discipline_domain = IVL_DIS_CONTINUOUS;
|
2008-05-12 03:52:27 +02:00
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
ivl_discipline_t tmp = new ivl_discipline_s(discipline_name,
|
|
|
|
|
discipline_domain,
|
|
|
|
|
discipline_potential,
|
|
|
|
|
discipline_flow);
|
2008-05-11 21:00:11 +02:00
|
|
|
disciplines[discipline_name] = tmp;
|
|
|
|
|
|
|
|
|
|
FILE_NAME(tmp, loc);
|
|
|
|
|
|
|
|
|
|
/* Clear the static variables for the next item. */
|
2010-01-13 21:23:36 +01:00
|
|
|
discipline_name = perm_string();
|
2008-11-02 17:10:41 +01:00
|
|
|
discipline_domain = IVL_DIS_NONE;
|
2008-05-12 03:52:27 +02:00
|
|
|
discipline_potential = 0;
|
|
|
|
|
discipline_flow = 0;
|
2008-05-11 21:00:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2008-05-12 02:30:33 +02:00
|
|
|
* The parser uses this function to attach a discipline to a wire. The
|
|
|
|
|
* wire may be declared by now, or will be declared further later. If
|
|
|
|
|
* it is already declared, we just attach the discipline. If it is not
|
|
|
|
|
* declared yet, then this is the declaration and we create the signal
|
|
|
|
|
* in the current lexical scope.
|
2008-05-11 21:00:11 +02:00
|
|
|
*/
|
|
|
|
|
void pform_attach_discipline(const struct vlltype&loc,
|
2008-11-02 17:10:41 +01:00
|
|
|
ivl_discipline_t discipline, list<perm_string>*names)
|
2008-05-11 21:00:11 +02:00
|
|
|
{
|
|
|
|
|
for (list<perm_string>::iterator cur = names->begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != names->end() ; ++ cur ) {
|
2008-05-11 21:00:11 +02:00
|
|
|
|
2008-05-12 02:30:33 +02:00
|
|
|
PWire* cur_net = pform_get_wire_in_scope(*cur);
|
|
|
|
|
if (cur_net == 0) {
|
|
|
|
|
/* Not declared yet, declare it now. */
|
2022-04-23 12:22:21 +02:00
|
|
|
cur_net = pform_makewire(loc, *cur, NetNet::WIRE, 0);
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(loc, cur_net);
|
2008-05-12 02:30:33 +02:00
|
|
|
}
|
2008-05-11 21:00:11 +02:00
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
if (ivl_discipline_t tmp = cur_net->get_discipline()) {
|
2008-05-12 02:30:33 +02:00
|
|
|
cerr << loc.text << ":" << loc.first_line << ": error: "
|
|
|
|
|
<< "discipline " << discipline->name()
|
|
|
|
|
<< " cannot override existing discipline " << tmp->name()
|
|
|
|
|
<< " on net " << cur_net->basename() << endl;
|
|
|
|
|
error_count += 1;
|
|
|
|
|
|
|
|
|
|
} else {
|
2022-01-09 00:27:56 +01:00
|
|
|
data_type_t *type = new real_type_t(real_type_t::REAL);
|
|
|
|
|
FILE_NAME(type, loc);
|
|
|
|
|
cur_net->set_data_type(type);
|
2008-05-12 02:30:33 +02:00
|
|
|
cur_net->set_discipline(discipline);
|
|
|
|
|
}
|
2008-05-11 21:00:11 +02:00
|
|
|
}
|
|
|
|
|
}
|