Merge branch 'x-ms1'

This commit is contained in:
Stephen Williams 2012-04-02 19:22:31 -07:00
commit 3657b15428
26 changed files with 2219 additions and 1330 deletions

View File

@ -110,9 +110,10 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
netenum.o netstruct.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
pform_disciplines.o pform_dump.o pform_struct_type.o pform_types.o \
pform_disciplines.o pform_dump.o pform_pclass.o pform_struct_type.o \
pform_types.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
Statement.o AStatement.o $M $(FF) $(TT)

View File

@ -28,7 +28,7 @@ list<Module::named_expr_t> Module::user_defparms;
/* n is a permallocated string. */
Module::Module(perm_string n)
: PScope(n)
: PScopeExtra(n)
{
library_flag = false;
is_cell = false;

View File

@ -49,7 +49,7 @@ class NetScope;
* therefore the handle for grasping the described circuit.
*/
class Module : public PScope, public LineInfo {
class Module : public PScopeExtra, public LineInfo {
/* The module ports are in general a vector of port_t
objects. Each port has a name and an ordered list of
@ -112,10 +112,6 @@ class Module : public PScope, public LineInfo {
bool time_from_timescale;
bool timescale_warn_done;
/* Task definitions within this module */
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;
/* The module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;

30
PClass.cc Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "PClass.h"
PClass::PClass(perm_string name, LexicalScope*parent)
: PScopeExtra(name, parent)
{
}
PClass::~PClass()
{
}

40
PClass.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __PClass_H
#define __PClass_H
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "PScope.h"
# include "LineInfo.h"
# include "StringHeap.h"
/*
* SystemVerilog supports class declarations with their own lexical
* scope, etc. The parser arranges for these to be created and
* collected.
*/
class PClass : public PScopeExtra, public LineInfo {
public:
explicit PClass (perm_string name, LexicalScope*parent);
~PClass();
};
#endif

View File

@ -509,6 +509,10 @@ class PEUnary : public PExpr {
unsigned flags) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
public:
inline char get_op() const { return op_; }
inline PExpr*get_expr() const { return expr_; }
private:
NetExpr* elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const;

View File

@ -41,3 +41,18 @@ PWire* LexicalScope::wires_find(perm_string name)
else
return (*cur).second;
}
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
: PScope(n, parent)
{
}
PScopeExtra::PScopeExtra(perm_string n)
: PScope(n)
{
}
PScopeExtra::~PScopeExtra()
{
}

View File

@ -27,8 +27,10 @@
class PEvent;
class PExpr;
class PFunction;
class AProcess;
class PProcess;
class PTask;
class PWire;
class Design;
@ -150,4 +152,21 @@ class PScope : public LexicalScope {
perm_string name_;
};
/*
* Some scopes can carry definitions. These include Modules and PClass
* scopes. These derive from PScopeExtra so that they hold the maps of
* extra definitions.
*/
class PScopeExtra : public PScope {
public:
PScopeExtra(perm_string, LexicalScope*parent);
PScopeExtra(perm_string);
~PScopeExtra();
/* Task definitions within this module */
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;
};
#endif

View File

@ -1,7 +1,7 @@
#ifndef __PTask_H
#define __PTask_H
/*
* Copyright (c) 1999-2008,2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008,2010,2012 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -41,12 +41,14 @@ enum PTaskFuncEnum {
PTF_REALTIME,
PTF_TIME,
PTF_ATOM2,
PTF_ATOM2_S
PTF_ATOM2_S,
PTF_STRING,
PTF_VOID
};
struct PTaskFuncArg {
PTaskFuncEnum type;
vector<PExpr*>*range;
std::list<index_component_t>*range;
};
/*

View File

@ -276,9 +276,8 @@ PForever::~PForever()
}
PForStatement::PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
PExpr*n2, PExpr*e2, Statement*st)
: name1_(n1), expr1_(e1), cond_(cond), name2_(n2), expr2_(e2),
statement_(st)
Statement*step, Statement*st)
: name1_(n1), expr1_(e1), cond_(cond), step_(step), statement_(st)
{
}

View File

@ -196,18 +196,6 @@ class PCallTask : public Statement {
const pform_name_t& path() const;
unsigned nparms() const { return parms_.size(); }
PExpr*&parm(unsigned idx)
{ assert(idx < parms_.size());
return parms_[idx];
}
PExpr* parm(unsigned idx) const
{ assert(idx < parms_.size());
return parms_[idx];
}
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@ -403,7 +391,7 @@ class PForStatement : public Statement {
public:
PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
PExpr*n2, PExpr*e2, Statement*st);
Statement*step, Statement*body);
~PForStatement();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@ -417,8 +405,7 @@ class PForStatement : public Statement {
PExpr*cond_;
PExpr* name2_;
PExpr* expr2_;
Statement*step_;
Statement*statement_;
};

View File

@ -221,6 +221,9 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
case NetNet::PINOUT:
o << " inout";
break;
case NetNet::PREF:
o <<" ref";
break;
}
if (ivl_discipline_t dis = get_discipline())

View File

@ -702,6 +702,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
case NetNet::PINPUT:
case NetNet::POUTPUT:
case NetNet::PINOUT:
case NetNet::PREF:
break;
/* If the name matches, but the signal is not a port,
@ -769,6 +770,9 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
sig = tmp;
break;
case NetNet::PREF:
// For the purposes of module ports, treat ref ports
// just like inout ports.
case NetNet::PINOUT:
ps = new NetTran(scope, scope->local_symbol(), sig->vector_width(),
swid, lidx);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -133,9 +133,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type_t*enum_type)
{
bool rc_flag;
assert(enum_type->range->size() == 2);
NetExpr*msb_ex = elab_and_eval(des, scope, enum_type->range->front(), -1);
NetExpr*lsb_ex = elab_and_eval(des, scope, enum_type->range->back(), -1);
assert(enum_type->range->size() == 1);
index_component_t index = enum_type->range->front();
NetExpr*msb_ex = elab_and_eval(des, scope, index.msb, -1);
NetExpr*lsb_ex = elab_and_eval(des, scope, index.lsb, -1);
long msb = 0;
rc_flag = eval_as_long(msb, msb_ex);

View File

@ -85,6 +85,14 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
PWire*cur = (*wt).second;
NetNet*sig = cur->elaborate_sig(des, scope);
if (sig && (sig->scope() == scope)
&& (sig->port_type() == NetNet::PREF)) {
cerr << cur->get_fileline() << ": sorry: "
<< "Reference ports not supported yet." << endl;
des->errors += 1;
}
/* If the signal is an input and is also declared as a
reg, then report an error. */
@ -468,15 +476,12 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_REG:
case PTF_REG_S:
if (return_type_.range) {
ivl_assert(*this, return_type_.range->size() == 2);
ivl_assert(*this, return_type_.range->size() == 1);
index_component_t index = return_type_.range->front();
NetExpr*me = elab_and_eval(des, scope,
return_type_.range->at(0), -1,
true);
NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
return_type_.range->at(1), -1,
true);
NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
assert(le);
long mnum = 0, lnum = 0;
@ -542,17 +547,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_ATOM2:
case PTF_ATOM2_S:
ivl_assert(*this, return_type_.range != 0);
long use_wid;
{
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1,
true);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1], -1,
true);
assert(le);
ivl_assert(*this, return_type_.range->size() == 1);
index_component_t index = return_type_.range->front();
NetExpr*me = elab_and_eval(des, scope, index.msb, -1, true);
ivl_assert(*this, me);
NetExpr*le = elab_and_eval(des, scope, index.lsb, -1, true);
ivl_assert(*this, le);
long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) {
@ -580,6 +582,15 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ret_sig->data_type(IVL_VT_BOOL);
break;
case PTF_STRING:
cerr << get_fileline() << ": sorry: String functions are not supported yet" << endl;
break;
case PTF_VOID:
// Void functions have no return value, so there is no
// signal to create here.
break;
default:
if (ports_) {
cerr << get_fileline() << ": internal error: I don't know "
@ -797,9 +808,10 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
long use_msb = 0;
long use_lsb = 0;
if (curp->range.get() && ! curp->range->empty()) {
ivl_assert(*curp, curp->range->size() == 2);
PExpr*msb_pex = curp->range->front();
PExpr*lsb_pex = curp->range->back();
ivl_assert(*curp, curp->range->size() == 1);
index_component_t index = curp->range->front();
PExpr*msb_pex = index.msb;
PExpr*lsb_pex = index.lsb;
NetExpr*tmp = elab_and_eval(des, scope, msb_pex, -2, true);
ivl_assert(*curp, tmp);

View File

@ -1069,6 +1069,10 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
ivl_assert(*this, 0);
break;
case NetNet::PREF:
ivl_assert(*this, 0);
break;
default:
ivl_assert(*this, 0);
}
@ -1506,6 +1510,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
} else {
/* Port type must be OUTPUT here. */
ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT);
/* Output from module. Elaborate the port
expression as the l-value of a continuous
@ -1640,6 +1645,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
/* This may not be correct! */
as_signed = prts[0]->get_signed() && sig->get_signed();
break;
case NetNet::PREF:
ivl_assert(*this, 0);
break;
default:
ivl_assert(*this, 0);
}
@ -1786,6 +1794,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
}
break;
case NetNet::PREF:
cerr << get_fileline() << ": sorry: "
<< "Reference ports not supported yet." << endl;
des->errors += 1;
break;
case NetNet::PIMPLICIT:
cerr << get_fileline() << ": internal error: "
<< "Unexpected IMPLICIT port" << endl;
@ -2811,12 +2825,12 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
des->errors += 1;
}
unsigned parm_count = nparms();
unsigned parm_count = parms_.size();
/* Catch the special case that the system task has no
parameters. The "()" string will be parsed as a single
empty parameter, when we really mean no parameters at all. */
if ((nparms() == 1) && (parm(0) == 0))
if ((parm_count== 1) && (parms_[0] == 0))
parm_count = 0;
svector<NetExpr*>eparms (parm_count);
@ -2824,7 +2838,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
perm_string name = peek_tail_name(path_);
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
PExpr*ex = parm(idx);
PExpr*ex = parms_[idx];
if (ex != 0) {
eparms[idx] = elab_sys_task_arg(des, scope, name, idx, ex);
} else {
@ -2916,9 +2930,20 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
}
assert(def);
if (nparms() != def->port_count()) {
unsigned parm_count = parms_.size();
// Handle special case that the definition has no arguments
// but the parser found a simgle nul argument. This is an
// argument of the parser allowing for the possibility of
// default values for argumets: The parser cannot tell the
// difference between "func()" and "func(<default>)".
if (def->port_count() == 0 && parm_count == 1 && parms_[0] == 0)
parm_count = 0;
if (parm_count != def->port_count()) {
cerr << get_fileline() << ": error: Port count mismatch in call to ``"
<< path_ << "''. Got " << nparms()
<< path_ << "''. Got " << parm_count
<< " ports, expecting " << def->port_count() << " ports." << endl;
des->errors += 1;
return 0;
@ -2928,7 +2953,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
/* Handle non-automatic tasks with no parameters specially. There is
no need to make a sequential block to hold the generated code. */
if ((nparms() == 0) && !task->is_auto()) {
if ((parm_count == 0) && !task->is_auto()) {
cur = new NetUTask(task);
cur->set_line(*this);
return cur;
@ -2960,7 +2985,23 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
expression the r-value. We know by definition that the port
is a reg type, so this elaboration is pretty obvious. */
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
if (parms_[idx] == 0 && !gn_system_verilog()) {
cerr << get_fileline() << ": error: "
<< "Missing argument " << (idx+1)
<< " of call to task." << endl;
des->errors += 1;
continue;
}
if (parms_[idx] == 0) {
cerr << get_fileline() << ": sorry: "
<< "Implicit arguments (arg " << (idx+1)
<< ") not supported." << endl;
des->errors += 1;
continue;
}
NetNet*port = def->port(idx);
assert(port->port_type() != NetNet::NOT_A_PORT);
@ -2971,7 +3012,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
unsigned wid = count_lval_width(lv);
ivl_variable_type_t lv_type = lv->expr_type();
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_[idx]);
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_ [idx]);
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
cerr << evt->get_fileline() << ": error: An event '"
<< evt->event()->name() << "' can not be a user "
@ -3001,7 +3042,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
expression that can be a target to a procedural
assignment, including a memory word. */
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
NetNet*port = def->port(idx);
@ -3780,8 +3821,6 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
const PEIdent*id1 = dynamic_cast<const PEIdent*>(name1_);
assert(id1);
const PEIdent*id2 = dynamic_cast<const PEIdent*>(name2_);
assert(id2);
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
top->set_line(*this);
@ -3826,32 +3865,15 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
body->append(tmp);
/* Elaborate the increment assignment statement at the end of
the for loop. This is also a very specific assignment
statement. Put this into the "body" block. */
sig = des->find_signal(scope, id2->path());
if (sig == 0) {
cerr << get_fileline() << ": error: Unable to find variable "
<< id2->path() << " in for-loop increment expression." << endl;
des->errors += 1;
return body;
}
assert(sig);
lv = new NetAssign_(sig);
/* Make the r-value of the increment assignment, and size it
properly. Then use it to build the assignment statement. */
etmp = elaborate_rval_expr(des, scope, lv->expr_type(), lv->lwidth(),
expr2_);
/* Now elaborate the for_step statement. I really should do
some error checking here to make sure the step statement
really does step the variable. */
if (debug_elaborate) {
cerr << get_fileline() << ": debug: FOR increment assign: "
cerr << get_fileline() << ": debug: Elaborate for_step statement "
<< sig->name() << " = " << *etmp << endl;
}
NetAssign*step = new NetAssign(lv, etmp);
step->set_line(*this);
NetProc*step = step_->elaborate(des, scope);
body->append(step);

View File

@ -51,7 +51,7 @@
*/
extern YYLTYPE yylloc;
static char* strdupnew(char const *str)
char* strdupnew(char const *str)
{
return str ? strcpy(new char [strlen(str)+1], str) : 0;
}
@ -191,7 +191,7 @@ TU [munpf]
">>>=" { return K_RSS_EQ; }
"++" { return K_INCR; }
"--" {return K_DECR; }
"'{" { return K_LP; }
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
and ")", but since I know that this is really ( * ), replace it

View File

@ -561,7 +561,7 @@ class NetNet : public NetObj {
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
UNRESOLVED_WIRE };
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
struct range_t {
inline range_t() : msb(0), lsb(0) { }

2763
parse.y

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,8 @@
# include "config.h"
# include "parse_misc.h"
# include <cstdarg>
# include <cstdio>
# include <iostream>
extern const char*vl_file;
@ -42,10 +44,16 @@ void VLerror(const char*msg)
cerr << yylloc.text << ":" << yylloc.first_line << ": " << msg << endl;
}
void VLerror(const YYLTYPE&loc, const char*msg)
void VLerror(const YYLTYPE&loc, const char*msg, ...)
{
va_list ap;
va_start(ap, msg);
fprintf(stderr, "%s:%d: ", loc.text, loc.first_line);
vfprintf(stderr, msg, ap);
fprintf(stderr, "\n");
error_count += 1;
cerr << loc << ": " << msg << endl;
based_size = 0; /* Clear the base information if we have an error. */
}

View File

@ -56,7 +56,7 @@ extern YYLTYPE yylloc;
*/
extern int VLlex();
extern void VLerror(const char*msg);
extern void VLerror(const YYLTYPE&loc, const char*msg);
extern void VLerror(const YYLTYPE&loc, const char*msg, ...) __attribute__((format(printf,2,3)));
#define yywarn VLwarn
extern void VLwarn(const YYLTYPE&loc, const char*msg);
@ -95,4 +95,6 @@ extern verinum*make_unsized_binary(const char*txt);
extern verinum*make_unsized_octal(const char*txt);
extern verinum*make_unsized_hex(const char*txt);
extern char* strdupnew(char const *str);
#endif

303
pform.cc
View File

@ -23,6 +23,7 @@
# include "pform.h"
# include "parse_misc.h"
# include "parse_api.h"
# include "PClass.h"
# include "PEvent.h"
# include "PUdp.h"
# include "PGenerate.h"
@ -267,12 +268,30 @@ void pform_pop_scope()
lexical_scope = lexical_scope->parent_scope();
}
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
{
PClass*class_scope = new PClass(name, lexical_scope);
FILE_NAME(class_scope, loc);
lexical_scope = class_scope;
return class_scope;
}
PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
{
perm_string task_name = lex_strings.make(name);
PTask*task = new PTask(task_name, lexical_scope, is_auto);
FILE_NAME(task, loc);
LexicalScope*scope = lexical_scope;
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
while (scope && !scopex) {
scope = scope->parent_scope();
scopex = dynamic_cast<PScopeExtra*> (scope);
}
assert(scopex);
if (pform_cur_generate) {
// Check if the task is already in the dictionary.
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
@ -286,15 +305,15 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
pform_cur_generate->tasks[task->pscope_name()] = task;
} else {
// Check if the task is already in the dictionary.
if (pform_cur_module->tasks.find(task->pscope_name()) !=
pform_cur_module->tasks.end()) {
if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate "
"definition for task '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
pform_cur_module->tasks[task->pscope_name()] = task;
scopex->tasks[task->pscope_name()] = task;
}
lexical_scope = task;
return task;
@ -307,6 +326,15 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
FILE_NAME(func, loc);
LexicalScope*scope = lexical_scope;
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
while (scope && !scopex) {
scope = scope->parent_scope();
scopex = dynamic_cast<PScopeExtra*> (scope);
}
assert(scopex);
if (pform_cur_generate) {
// Check if the function is already in the dictionary.
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
@ -320,14 +348,13 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
pform_cur_generate->funcs[func->pscope_name()] = func;
} else {
// Check if the function is already in the dictionary.
if (pform_cur_module->funcs.find(func->pscope_name()) !=
pform_cur_module->funcs.end()) {
if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate "
"definition for function '" << name << "' in '"
<< pform_cur_module->mod_name() << "'." << endl;
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
pform_cur_module->funcs[func->pscope_name()] = func;
scopex->funcs[func->pscope_name()] = func;
}
lexical_scope = func;
@ -416,11 +443,16 @@ data_type_t* pform_test_type_identifier(const char*txt)
return 0;
perm_string name = lex_strings.make(txt);
map<perm_string,data_type_t*>::iterator cur = lexical_scope->typedefs.find(name);
if (cur != lexical_scope->typedefs.end())
return cur->second;
else
return 0;
map<perm_string,data_type_t*>::iterator cur;
LexicalScope*cur_scope = lexical_scope;
do {
cur = cur_scope->typedefs.find(name);
if (cur != cur_scope->typedefs.end())
return cur->second;
cur_scope = cur_scope->parent_scope();
} while (cur_scope);
return 0;
}
static void pform_put_behavior_in_scope(PProcess*pp)
@ -1480,16 +1512,15 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
delete init_expr;
}
static void ranges_from_list(list<PWire::range_t>&rlist, const list<PExpr*>*range)
static void ranges_from_list(list<PWire::range_t>&rlist,
const list<index_component_t>*range)
{
// There must be an even number of expressions in the
// range. The parser will assure that for us.
assert(range->size()%2 == 0);
list<PExpr*>::const_iterator rcur = range->begin();
while (rcur != range->end()) {
// Convert a list of index_component_t to PWire::range_t.
for (list<index_component_t>::const_iterator rcur = range->begin()
; rcur != range->end() ; ++rcur) {
PWire::range_t rng;
rng.msb = *rcur; ++rcur;
rng.lsb = *rcur; ++rcur;
rng.msb = rcur->msb;
rng.lsb = rcur->lsb;
rlist.push_back(rng);
}
}
@ -1500,7 +1531,7 @@ static void ranges_from_list(list<PWire::range_t>&rlist, const list<PExpr*>*rang
* and the name that I receive only has the tail component.
*/
static void pform_set_net_range(perm_string name,
const list<PExpr*>*range,
const list<index_component_t>*range,
bool signed_flag,
ivl_variable_type_t dt,
PWSRType rt)
@ -1527,13 +1558,11 @@ static void pform_set_net_range(perm_string name,
cur->set_data_type(dt);
}
void pform_set_net_range(list<perm_string>*names,
list<PExpr*>*range,
bool signed_flag,
ivl_variable_type_t dt)
static void pform_set_net_range(list<perm_string>*names,
list<index_component_t>*range,
bool signed_flag,
ivl_variable_type_t dt)
{
assert((range == 0) || (range->size()%2 == 0));
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
@ -1601,8 +1630,8 @@ static void pform_makegate(PGBuiltin::Type type,
perm_string dev_name = lex_strings.make(info.name);
PGBuiltin*cur = new PGBuiltin(type, dev_name, info.parms, delay);
if (info.range[0])
cur->set_range(info.range[0], info.range[1]);
if (info.range.msb)
cur->set_range(info.range.msb, info.range.lsb);
// The pform_makegates() that calls me will take care of
// deleting the attr pointer, so tell the
@ -1741,7 +1770,7 @@ void pform_make_modgates(perm_string type,
if (cur.parms_by_name) {
pform_make_modgate(type, cur_name, overrides,
cur.parms_by_name,
cur.range[0], cur.range[1],
cur.range.msb, cur.range.lsb,
cur.file, cur.lineno);
} else if (cur.parms) {
@ -1755,14 +1784,14 @@ void pform_make_modgates(perm_string type,
}
pform_make_modgate(type, cur_name, overrides,
cur.parms,
cur.range[0], cur.range[1],
cur.range.msb, cur.range.lsb,
cur.file, cur.lineno);
} else {
list<PExpr*>*wires = new list<PExpr*>;
pform_make_modgate(type, cur_name, overrides,
wires,
cur.range[0], cur.range[1],
cur.range.msb, cur.range.lsb,
cur.file, cur.lineno);
}
}
@ -1835,8 +1864,8 @@ void pform_make_pgassign_list(list<PExpr*>*alist,
void pform_make_reginit(const struct vlltype&li,
perm_string name, PExpr*expr)
{
if (! pform_at_module_level()) {
VLerror(li, "variable declaration assignments are only "
if (! pform_at_module_level() && !gn_system_verilog()) {
VLerror(li, "error: variable declaration assignments are only "
"allowed at the module level.");
delete expr;
return;
@ -1875,7 +1904,7 @@ void pform_module_define_port(const struct vlltype&li,
NetNet::Type type,
ivl_variable_type_t data_type,
bool signed_flag,
list<PExpr*>*range,
list<index_component_t>*range,
list<named_pexpr_t>*attr)
{
PWire*cur = pform_get_wire_in_scope(name);
@ -2009,7 +2038,7 @@ void pform_makewire(const vlltype&li, perm_string name,
* pform_makewire above.
*/
void pform_makewire(const vlltype&li,
list<PExpr*>*range,
list<index_component_t>*range,
bool signed_flag,
list<perm_string>*names,
NetNet::Type type,
@ -2036,7 +2065,7 @@ void pform_makewire(const vlltype&li,
* This form makes nets with delays and continuous assignments.
*/
void pform_makewire(const vlltype&li,
list<PExpr*>*range,
list<index_component_t>*range,
bool signed_flag,
list<PExpr*>*delay,
str_pair_t str,
@ -2071,39 +2100,6 @@ void pform_makewire(const vlltype&li,
}
}
void pform_set_port_type(perm_string name, NetNet::PortType pt,
const char*file, unsigned lineno)
{
PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
FILE_NAME(cur, file, lineno);
pform_put_wire_in_scope(name, cur);
}
switch (cur->get_port_type()) {
case NetNet::PIMPLICIT:
if (! cur->set_port_type(pt))
VLerror("error setting port direction.");
break;
case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " is not in the port list."
<< endl;
error_count += 1;
break;
default:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " already has a port declaration."
<< endl;
error_count += 1;
break;
}
}
/*
* This function is called by the parser to create task ports. The
* resulting wire (which should be a register) is put into a list to
@ -2143,15 +2139,15 @@ void pform_set_port_type(perm_string name, NetNet::PortType pt,
* constraints as those of tasks, so this works fine. Functions have
* no output or inout ports.
*/
svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
ivl_variable_type_t vtype,
bool signed_flag,
list<PExpr*>*range,
list<index_component_t>*range,
list<perm_string>*names,
const char* file,
unsigned lineno,
bool isint)
{
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
assert(names);
svector<PWire*>*res = new svector<PWire*>(0);
for (list<perm_string>::iterator cur = names->begin()
@ -2166,7 +2162,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
curw->set_port_type(pt);
} else {
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
FILE_NAME(curw, file, lineno);
FILE_NAME(curw, loc);
pform_put_wire_in_scope(name, curw);
}
@ -2191,6 +2187,71 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
return res;
}
svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
data_type_t*vtype,
list<perm_string>*names)
{
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
list<index_component_t>*range_tmp = make_range_from_width(atype->type_code);
return pform_make_task_ports(loc, pt, IVL_VT_BOOL,
atype->signed_flag,
range_tmp, names);
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, vec_type->base_type,
vec_type->signed_flag,
copy_range(vec_type->pdims.get()),
names);
}
if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, IVL_VT_REAL,
true, 0, names);
}
VLerror(loc, "sorry: Given type not supported here.");
return 0;
}
/*
* The parser calls this in the rule that matches increment/decrement
* statements. The rule that does the matching creates a PEUnary with
* all the information we need, but here we convert that expression to
* a compressed assignment statement.
*/
PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*exp)
{
PEUnary*expu = dynamic_cast<PEUnary*> (exp);
ivl_assert(*exp, expu != 0);
char use_op = 0;
switch (expu->get_op()) {
case 'i':
case 'I':
use_op = '+';
break;
case 'd':
case 'D':
use_op = '-';
break;
default:
ivl_assert(*exp, 0);
break;
}
PExpr*lval = expu->get_expr();
PExpr*rval = new PENumber(new verinum((uint64_t)1, 1));
FILE_NAME(rval, loc);
PAssign*tmp = new PAssign(lval, use_op, rval);
FILE_NAME(tmp, loc);
delete exp;
return tmp;
}
void pform_set_attrib(perm_string name, perm_string key, char*value)
{
if (PWire*cur = lexical_scope->wires_find(name)) {
@ -2259,7 +2320,7 @@ LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
void pform_set_parameter(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type,
bool signed_flag, list<PExpr*>*range, PExpr*expr,
bool signed_flag, list<index_component_t>*range, PExpr*expr,
LexicalScope::range_t*value_range)
{
LexicalScope*scope = lexical_scope;
@ -2294,11 +2355,12 @@ void pform_set_parameter(const struct vlltype&loc,
parm.type = type;
if (range) {
assert(range->size() == 2);
assert(range->front());
assert(range->back());
parm.msb = range->front();
parm.lsb = range->back();
assert(range->size() == 1);
index_component_t index = range->front();
assert(index.msb);
assert(index.lsb);
parm.msb = index.msb;
parm.lsb = index.lsb;
} else {
parm.msb = 0;
parm.lsb = 0;
@ -2312,7 +2374,7 @@ void pform_set_parameter(const struct vlltype&loc,
void pform_set_localparam(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type,
bool signed_flag, list<PExpr*>*range, PExpr*expr)
bool signed_flag, list<index_component_t>*range, PExpr*expr)
{
LexicalScope*scope = lexical_scope;
@ -2342,11 +2404,12 @@ void pform_set_localparam(const struct vlltype&loc,
parm.type = type;
if (range) {
assert(range->size() == 2);
assert(range->front());
assert(range->back());
parm.msb = range->front();
parm.lsb = range->back();
assert(range->size() == 1);
index_component_t index = range->front();
assert(index.msb);
assert(index.lsb);
parm.msb = index.msb;
parm.lsb = index.lsb;
} else {
parm.msb = 0;
parm.lsb = 0;
@ -2443,12 +2506,48 @@ extern void pform_module_specify_path(PSpecPath*obj)
pform_cur_module->specify_paths.push_back(obj);
}
static void pform_set_port_type(perm_string name, NetNet::PortType pt,
const char*file, unsigned lineno)
{
PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
FILE_NAME(cur, file, lineno);
pform_put_wire_in_scope(name, cur);
}
switch (cur->get_port_type()) {
case NetNet::PIMPLICIT:
if (! cur->set_port_type(pt))
VLerror("error setting port direction.");
break;
case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " is not in the port list."
<< endl;
error_count += 1;
break;
default:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " already has a port declaration."
<< endl;
error_count += 1;
break;
}
}
void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names,
list<PExpr*>*range,
list<index_component_t>*range,
bool signed_flag,
NetNet::PortType pt)
{
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
@ -2539,6 +2638,11 @@ void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>
*/
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names)
{
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names);
return;
}
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
pform_set_struct_type(struct_type, names);
return;
@ -2549,6 +2653,23 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
return;
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
pform_set_net_range(names, vec_type->pdims.get(),
vec_type->signed_flag,
vec_type->base_type);
return;
}
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
pform_set_net_range(names, 0, true, IVL_VT_REAL);
return;
}
if (/*class_type_t*class_type =*/ dynamic_cast<class_type_t*> (data_type)) {
VLerror(li, "sorry: Class types not supported.");
return;
}
assert(0);
}
@ -2562,7 +2683,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
cur->set_signed(enum_type->signed_flag);
assert(enum_type->range.get() != 0);
assert(enum_type->range->size() == 2);
assert(enum_type->range->size() == 1);
list<PWire::range_t>rlist;
ranges_from_list(rlist, enum_type->range.get());
cur->set_range(rlist, SR_NET);
@ -2576,7 +2697,7 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
assert(enum_type->base_type==IVL_VT_LOGIC || enum_type->base_type==IVL_VT_BOOL);
assert(enum_type->range.get() != 0);
assert(enum_type->range->size() == 2);
assert(enum_type->range->size() == 1);
// Add the file and line information to the enumeration type.
FILE_NAME(&(enum_type->li), li);

55
pform.h
View File

@ -58,6 +58,7 @@
class PGate;
class PExpr;
class PSpecPath;
class PClass;
struct vlltype;
/*
@ -101,22 +102,23 @@ struct net_decl_assign_t {
/* The lgate is gate instantiation information. */
struct lgate {
lgate(int =0)
inline lgate(int =0)
: parms(0), parms_by_name(0), file(NULL), lineno(0)
{ range[0] = 0;
range[1] = 0;
}
{ }
string name;
list<PExpr*>*parms;
list<named_pexpr_t>*parms_by_name;
PExpr*range[2];
index_component_t range;
const char* file;
unsigned lineno;
};
extern std::list<index_component_t>* make_range_from_width(uint64_t wid);
extern std::list<index_component_t>* copy_range(std::list<index_component_t>* orig);
/* Use this function to transform the parted form of the attribute
list to the attribute map that is used later. */
extern void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
@ -158,7 +160,7 @@ extern void pform_module_define_port(const struct vlltype&li,
NetNet::Type type,
ivl_variable_type_t data_type,
bool signed_flag,
list<PExpr*>*range,
list<index_component_t>*range,
list<named_pexpr_t>*attr);
extern Module::port_t* pform_module_port_reference(perm_string name,
@ -167,6 +169,10 @@ extern Module::port_t* pform_module_port_reference(perm_string name,
extern void pform_endmodule(const char*, bool inside_celldefine,
Module::UCDriveType uc_drive_def);
extern void pform_start_class_declaration(const struct vlltype&loc,
class_type_t*type);
extern void pform_end_class_declaration(void);
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
svector<PWire*>*decl, list<string>*table,
Statement*init,
@ -186,6 +192,7 @@ extern void pform_make_udp(perm_string name,
*/
extern void pform_pop_scope();
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
bool is_auto);
extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name,
@ -238,7 +245,7 @@ extern void pform_makewire(const struct vlltype&li, perm_string name,
/* This form handles simple declarations */
extern void pform_makewire(const struct vlltype&li,
list<PExpr*>*range,
list<index_component_t>*range,
bool signed_flag,
list<perm_string>*names,
NetNet::Type type,
@ -255,7 +262,7 @@ extern void pform_makewire(const struct vlltype&li,
/* This form handles assignment declarations. */
extern void pform_makewire(const struct vlltype&li,
list<PExpr*>*range,
list<index_component_t>*range,
bool signed_flag,
list<PExpr*>*delay,
str_pair_t str,
@ -278,16 +285,11 @@ extern void pform_make_reginit(const struct vlltype&li,
it. The second form takes a single name. */
extern void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names,
list<PExpr*>*range,
list<index_component_t>*range,
bool signed_flag,
NetNet::PortType);
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno);
extern void pform_set_net_range(list<perm_string>*names,
list<PExpr*>*,
bool signed_flag,
ivl_variable_type_t);
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
extern void pform_set_reg_integer(list<perm_string>*names);
extern void pform_set_reg_time(list<perm_string>*names);
@ -317,13 +319,13 @@ extern void pform_set_parameter(const struct vlltype&loc,
perm_string name,
ivl_variable_type_t type,
bool signed_flag,
list<PExpr*>*range,
list<index_component_t>*range,
PExpr*expr, LexicalScope::range_t*value_range);
extern void pform_set_localparam(const struct vlltype&loc,
perm_string name,
ivl_variable_type_t type,
bool signed_flag,
list<PExpr*>*range,
list<index_component_t>*range,
PExpr*expr);
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
@ -383,15 +385,26 @@ extern void pform_make_pgassign_list(list<PExpr*>*alist,
/* Given a port type and a list of names, make a list of wires that
can be used as task port information. */
extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
ivl_variable_type_t vtype,
bool signed_flag,
list<PExpr*>*range,
list<index_component_t>*range,
list<perm_string>*names,
const char* file,
unsigned lineno,
bool isint = false);
extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
NetNet::PortType pt,
data_type_t*vtype,
list<perm_string>*names);
/*
* The parser uses this function to convert a unary
* increment/decrement expression to the equivilent compressed
* assignment statement.
*/
extern PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc,
PExpr*exp);
/*
* These are functions that the outside-the-parser code uses the do

View File

@ -336,6 +336,9 @@ void PWire::dump(ostream&out, unsigned ind) const
case NetNet::PINOUT:
out << " inout";
break;
case NetNet::PREF:
out << " ref";
break;
case NetNet::NOT_A_PORT:
break;
}
@ -574,7 +577,10 @@ void PAssign::dump(ostream&out, unsigned ind) const
if (delay_) out << "#" << *delay_ << " ";
if (count_) out << "repeat(" << *count_ << ") ";
if (event_) out << *event_ << " ";
out << *rval() << ";" << " /* " << get_fileline() << " */" << endl;
PExpr*rexpr = rval();
if (rexpr) out << *rval() << ";";
else out << "<no rval>;";
out << " /* " << get_fileline() << " */" << endl;
}
void PAssignNB::dump(ostream&out, unsigned ind) const
@ -774,8 +780,8 @@ void PForever::dump(ostream&out, unsigned ind) const
void PForStatement::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "for (" << *name1_ << " = " << *expr1_
<< "; " << *cond_ << "; " << *name2_ << " = " << *expr2_ <<
")" << endl;
<< "; " << *cond_ << "; <for_step>)" << endl;
step_->dump(out, ind+6);
statement_->dump(out, ind+3);
}
@ -809,7 +815,13 @@ void PFunction::dump(ostream&out, unsigned ind) const
out << "int unsigned ";
break;
case PTF_ATOM2_S:
cout << "int signed ";
out << "int signed ";
break;
case PTF_STRING:
out << "string ";
break;
case PTF_VOID:
out << "void ";
break;
}
@ -860,6 +872,10 @@ void PTask::dump(ostream&out, unsigned ind) const
out << pscope_name() << ";" << endl;
if (ports_)
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
if ((*ports_)[idx] == 0) {
out << setw(ind) << "" << "ERROR PORT" << endl;
continue;
}
out << setw(ind) << "";
switch ((*ports_)[idx]->get_port_type()) {
case NetNet::PINPUT:
@ -871,6 +887,12 @@ void PTask::dump(ostream&out, unsigned ind) const
case NetNet::PINOUT:
out << "inout ";
break;
case NetNet::PIMPLICIT:
out << "PIMPLICIT";
break;
case NetNet::NOT_A_PORT:
out << "NOT_A_PORT";
break;
default:
assert(0);
break;

37
pform_pclass.cc Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "pform.h"
# include "PClass.h"
static PClass*pform_cur_class = 0;
void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type)
{
PClass*class_scope = pform_push_class_scope(loc, type->name);
assert(pform_cur_class == 0);
pform_cur_class = class_scope;
}
void pform_end_class_declaration(void)
{
assert(pform_cur_class);
pform_cur_class = 0;
pform_pop_scope();
}

View File

@ -1,7 +1,7 @@
#ifndef __pform_types_H
#define __pform_types_H
/*
* Copyright (c) 2007-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-2012 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -84,14 +84,14 @@ struct data_type_t : public LineInfo {
struct enum_type_t : public data_type_t {
ivl_variable_type_t base_type;
bool signed_flag;
std::auto_ptr< list<PExpr*> > range;
std::auto_ptr< list<index_component_t> > range;
std::auto_ptr< list<named_pexpr_t> > names;
LineInfo li;
};
struct struct_member_t : public LineInfo {
ivl_variable_type_t type;
std::auto_ptr< list<PExpr*> > range;
std::auto_ptr< list<index_component_t> > range;
std::auto_ptr< list<decl_assignment_t*> > names;
};
@ -100,6 +100,34 @@ struct struct_type_t : public data_type_t {
std::auto_ptr< list<struct_member_t*> > members;
};
struct atom2_type_t : public data_type_t {
inline explicit atom2_type_t(int tc, bool flag)
: type_code(tc), signed_flag(flag) { }
int type_code;
bool signed_flag;
};
struct vector_type_t : public data_type_t {
inline explicit vector_type_t(ivl_variable_type_t bt, bool sf,
std::list<index_component_t>*pd)
: base_type(bt), signed_flag(sf), pdims(pd) { }
ivl_variable_type_t base_type;
bool signed_flag;
std::auto_ptr< list<index_component_t> > pdims;
};
struct real_type_t : public data_type_t {
inline explicit real_type_t(int tc) : type_code(tc) { }
int type_code;
};
struct class_type_t : public data_type_t {
inline explicit class_type_t(perm_string n)
: name(n) { }
perm_string name;
};
/*
* The pform_name_t is the general form for a hierarchical
* identifier. It is an ordered list of name components. Each name