From 7166aea1d72f92a1597c5ee402a93852d78375f1 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 11 May 2008 18:52:27 -0700 Subject: [PATCH] Attach natures to disciplines Pform parse enough of the natures that they can be mapped and the disciplines can bind to them. Since Verilog-AMS expects natures to be declared before use, we can do the binding early. --- discipline.cc | 14 +++++- discipline.h | 30 +++++++++-- main.cc | 5 ++ parse.y | 11 +++-- pform.h | 13 ++++- pform_disciplines.cc | 115 ++++++++++++++++++++++++++++++++++++++++++- pform_dump.cc | 13 ++++- 7 files changed, 189 insertions(+), 12 deletions(-) diff --git a/discipline.cc b/discipline.cc index 42b77352d..7294a65e3 100644 --- a/discipline.cc +++ b/discipline.cc @@ -19,8 +19,18 @@ # include "discipline.h" -discipline_t::discipline_t(perm_string name, ddomain_t domain) -: name_(name), domain_(domain) +nature_t::nature_t(perm_string name, perm_string access) +: name_(name), access_(access) +{ +} + +nature_t::~nature_t() +{ +} + +discipline_t::discipline_t(perm_string name, ddomain_t domain, + nature_t*pot, nature_t*flow) +: name_(name), domain_(domain), potential_(pot), flow_(flow) { } diff --git a/discipline.h b/discipline.h index e43365834..30932d49d 100644 --- a/discipline.h +++ b/discipline.h @@ -33,19 +33,43 @@ typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t; extern std::ostream& operator << (std::ostream&, ddomain_t); +class nature_t : public LineInfo { + public: + explicit nature_t(perm_string name, perm_string access); + ~nature_t(); + + perm_string name() const { return name_; } + // Identifier for the access function for this nature + perm_string access() const { return access_; } + + private: + perm_string name_; + perm_string access_; +}; + class discipline_t : public LineInfo { public: - explicit discipline_t (perm_string name, ddomain_t dom); + explicit discipline_t (perm_string name, ddomain_t dom, + nature_t*pot, nature_t*flow); ~discipline_t(); - perm_string name() const { return name_; } - ddomain_t domain() const { return domain_; } + perm_string name() const { return name_; } + ddomain_t domain() const { return domain_; } + const nature_t*potential() const { return potential_; } + const nature_t*flow() const { return flow_; } private: perm_string name_; ddomain_t domain_; + nature_t*potential_; + nature_t*flow_; + + private: // not implemented + discipline_t(const discipline_t&); + discipline_t& operator = (const discipline_t&); }; +extern map natures; extern map disciplines; #endif diff --git a/main.cc b/main.cc index 5027b9de1..679e321dc 100644 --- a/main.cc +++ b/main.cc @@ -684,6 +684,11 @@ int main(int argc, char*argv[]) if (pf_path) { ofstream out (pf_path); + out << "PFORM DUMP NATURES:" << endl; + for (map::iterator cur = natures.begin() + ; cur != natures.end() ; cur ++ ) { + pform_dump(out, (*cur).second); + } out << "PFORM DUMP DISCIPLINES:" << endl; for (map::iterator cur = disciplines.begin() ; cur != disciplines.end() ; cur ++ ) { diff --git a/parse.y b/parse.y index db9428cdd..93a83143d 100644 --- a/parse.y +++ b/parse.y @@ -686,18 +686,21 @@ discipline_items discipline_item : K_domain K_discrete ';' + { pform_discipline_domain(@1, DD_DISCRETE); } | K_domain K_continuous ';' + { pform_discipline_domain(@1, DD_CONTINUOUS); } | K_potential IDENTIFIER ';' - { delete[] $2; } + { pform_discipline_potential(@1, $2); delete[] $2; } | K_flow IDENTIFIER ';' - { delete[] $2; } + { pform_discipline_flow(@1, $2); delete[] $2; } ; nature_declaration : K_nature IDENTIFIER ';' + { pform_start_nature($2); } nature_items K_endnature - { delete[] $2; } + { pform_end_nature(@1); delete[] $2; } ; nature_items @@ -710,7 +713,7 @@ nature_item { delete[] $3; } | K_abstol '=' expression ';' | K_access '=' IDENTIFIER ';' - { delete[] $3; } + { pform_nature_access(@1, $3); delete[] $3; } | K_idt_nature '=' IDENTIFIER ';' { delete[] $3; } | K_ddt_nature '=' IDENTIFIER ';' diff --git a/pform.h b/pform.h index cb3f48543..3e971ecee 100644 --- a/pform.h +++ b/pform.h @@ -30,6 +30,7 @@ # include "PUdp.h" # include "PWire.h" # include "verinum.h" +# include "discipline.h" # include # include # include @@ -364,12 +365,22 @@ extern void pform_error_nested_modules(); */ class discipline_t; +extern void pform_start_nature(const char*name); +extern void pform_end_nature(const struct vlltype&loc); + +extern void pform_nature_access(const struct vlltype&loc, const char*name); + extern void pform_start_discipline(const char*name); extern void pform_end_discipline(const struct vlltype&loc); +extern void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain); +extern void pform_discipline_potential(const struct vlltype&loc, const char*name); +extern void pform_discipline_flow(const struct vlltype&loc, const char*name); + extern void pform_attach_discipline(const struct vlltype&loc, discipline_t*discipline, list*names); -extern void pform_dump(ostream&out, discipline_t*); +extern void pform_dump(ostream&out, const nature_t*); +extern void pform_dump(ostream&out, const discipline_t*); #endif diff --git a/pform_disciplines.cc b/pform_disciplines.cc index f55f52b9c..be07665d8 100644 --- a/pform_disciplines.cc +++ b/pform_disciplines.cc @@ -23,10 +23,58 @@ # include "parse_misc.h" # include "discipline.h" +map natures; map disciplines; +static perm_string nature_name = perm_string::perm_string(); +static perm_string nature_access = perm_string::perm_string(); + +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; + } + + nature_t*tmp = new nature_t(nature_name, nature_access); + natures[nature_name] = tmp; + + FILE_NAME(tmp, loc); + + nature_name = perm_string::perm_string(); + nature_access = perm_string::perm_string(); +} + + static perm_string discipline_name; static ddomain_t discipline_domain = DD_NONE; +static nature_t* discipline_potential = 0; +static nature_t* discipline_flow = 0; void pform_start_discipline(const char*name) { @@ -34,9 +82,72 @@ void pform_start_discipline(const char*name) discipline_domain = DD_NONE; } +void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain) +{ + assert(use_domain != DD_NONE); + + if (discipline_domain != DD_NONE) { + 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; + } +} + void pform_end_discipline(const struct vlltype&loc) { - discipline_t*tmp = new discipline_t(discipline_name, discipline_domain); + // If the domain is not otherwise specified, then take it to + // be continuous if potential or flow natures are given. + if (discipline_domain == DD_NONE && discipline_potential||discipline_flow) + discipline_domain = DD_CONTINUOUS; + + discipline_t*tmp = new discipline_t(discipline_name, discipline_domain, + discipline_potential, discipline_flow); disciplines[discipline_name] = tmp; FILE_NAME(tmp, loc); @@ -44,6 +155,8 @@ void pform_end_discipline(const struct vlltype&loc) /* Clear the static variables for the next item. */ discipline_name = perm_string::perm_string(); discipline_domain = DD_NONE; + discipline_potential = 0; + discipline_flow = 0; } /* diff --git a/pform_dump.cc b/pform_dump.cc index 7f5ea9418..da55b307f 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1149,9 +1149,20 @@ void PUdp::dump(ostream&out) const out << "endprimitive" << endl; } -void pform_dump(std::ostream&out, discipline_t*dis) +void pform_dump(std::ostream&out, const nature_t*nat) +{ + out << "nature " << nat->name() << endl; + out << " access " << nat->access() << ";" << endl; + out << "endnature" << endl; +} + +void pform_dump(std::ostream&out, const discipline_t*dis) { out << "discipline " << dis->name() << endl; out << " domain " << dis->domain() << ";" << endl; + if (const nature_t*tmp = dis->potential()) + out << " potential " << tmp->name() << ";" << endl; + if (const nature_t*tmp = dis->flow()) + out << " flow " << tmp->name() << ";" << endl; out << "enddiscipline" << endl; }