iverilog/Statement.h

601 lines
17 KiB
C
Raw Normal View History

#ifndef IVL_Statement_H
#define IVL_Statement_H
1998-11-04 00:28:49 +01:00
/*
* Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)
1998-11-04 00:28:49 +01: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.
1998-11-04 00:28:49 +01:00
*/
# include <string>
# include <vector>
# include <list>
# include "ivl_target.h"
1999-04-29 04:16:26 +02:00
# include "svector.h"
2004-02-20 19:53:33 +01:00
# include "StringHeap.h"
# include "PDelays.h"
1999-04-29 04:16:26 +02:00
# include "PExpr.h"
# include "PScope.h"
# include "HName.h"
# include "LineInfo.h"
1998-11-04 00:28:49 +01:00
class PExpr;
class PChainConstructor;
2013-04-09 03:12:54 +02:00
class PPackage;
1998-11-04 00:28:49 +01:00
class Statement;
1999-09-22 04:00:48 +02:00
class PEventStatement;
2000-03-11 04:25:51 +01:00
class Design;
class NetAssign_;
class NetCAssign;
class NetDeassign;
class NetForce;
2000-03-11 04:25:51 +01:00
class NetScope;
1998-11-04 00:28:49 +01:00
/*
* The PProcess is the root of a behavioral process. Each process gets
* one of these, which contains its type (initial, always, or final)
* and a pointer to the single statement that is the process. A module
* may have several concurrent processes.
1998-11-04 00:28:49 +01:00
*/
class PProcess : public LineInfo {
1998-11-04 00:28:49 +01:00
public:
PProcess(ivl_process_type_t t, Statement*st)
1998-11-04 00:28:49 +01:00
: type_(t), statement_(st) { }
virtual ~PProcess();
bool elaborate(Design*des, NetScope*scope) const;
ivl_process_type_t type() const { return type_; }
1998-11-04 00:28:49 +01:00
Statement*statement() { return statement_; }
2004-02-20 19:53:33 +01:00
map<perm_string,PExpr*> attributes;
1998-11-04 00:28:49 +01:00
virtual void dump(ostream&out, unsigned ind) const;
private:
ivl_process_type_t type_;
1998-11-04 00:28:49 +01:00
Statement*statement_;
};
/*
* The PProcess is a process, the Statement is the actual action. In
* fact, the Statement class is abstract and represents all the
* possible kinds of statements that exist in Verilog.
*/
class Statement : virtual public LineInfo {
1998-11-04 00:28:49 +01:00
public:
Statement() { }
virtual ~Statement() =0;
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
map<perm_string,PExpr*> attributes;
1998-11-04 00:28:49 +01:00
};
/*
* Assignment statements of the various forms are handled by this
* type. The rvalue is an expression. The lvalue needs to be figured
* out by the parser as much as possible.
*/
class PAssign_ : public Statement {
1998-11-04 00:28:49 +01:00
public:
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant);
1999-07-12 02:59:36 +02:00
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
virtual ~PAssign_() =0;
1999-07-12 02:59:36 +02:00
const PExpr* lval() const { return lval_; }
PExpr* rval() const { return rval_; }
1998-11-04 00:28:49 +01:00
protected:
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
ivl_variable_type_t lv_type,
unsigned lv_width,
bool force_unsigned =false) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
1998-11-04 00:28:49 +01:00
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
ivl_variable_type_t type) const;
PExpr* delay_;
1999-09-22 04:00:48 +02:00
PEventStatement*event_;
PExpr* count_;
1998-11-04 00:28:49 +01:00
private:
PExpr* lval_;
PExpr* rval_;
bool is_constant_;
};
class PAssign : public PAssign_ {
public:
// lval - assignment l-value
// ex - assignment r-value
// op - compressed assignment operator (i.e. '+', '-', ...)
// de - delayed assignment delay expression
explicit PAssign(PExpr*lval, PExpr*ex);
explicit PAssign(PExpr*lval, char op, PExpr*ex);
1999-07-12 02:59:36 +02:00
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
~PAssign();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
NetProc* elaborate_compressed_(Design*des, NetScope*scope) const;
char op_;
1998-11-04 00:28:49 +01:00
};
class PAssignNB : public PAssign_ {
public:
explicit PAssignNB(PExpr*lval, PExpr*ex);
1999-09-02 03:59:27 +02:00
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
~PAssignNB();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
Design*des, NetScope*scope) const;
};
1998-11-04 00:28:49 +01:00
/*
* A block statement is an ordered list of statements that make up the
* block. The block can be sequential or parallel, which only affects
* how the block is interpreted. The parser collects the list of
* statements before constructing this object, so it knows a priori
* what is contained.
*/
class PBlock : public PScope, public Statement, public PNamedItem {
1998-11-04 00:28:49 +01:00
public:
enum BL_TYPE { BL_SEQ, BL_PAR, BL_JOIN_NONE, BL_JOIN_ANY };
1998-11-04 00:28:49 +01:00
// If the block has a name, it is a scope and also has a parent.
explicit PBlock(perm_string n, LexicalScope*parent, BL_TYPE t);
// If it doesn't have a name, it's not a scope
explicit PBlock(BL_TYPE t);
1998-11-04 00:28:49 +01:00
~PBlock();
BL_TYPE bl_type() const { return bl_type_; }
bool var_init_needs_explicit_lifetime() const;
// This is only used if this block is the statement list for a
// constructor. We look for a PChainConstructor as the first
// statement, and if it is there, extract it.
PChainConstructor*extract_chain_constructor();
// If the bl_type() is BL_PAR, it is possible to replace it
// with JOIN_NONE or JOIN_ANY. This is to help the parser.
void set_join_type(BL_TYPE);
void set_statement(const std::vector<Statement*>&st);
1998-11-04 00:28:49 +01:00
// Copy the statement from that block to the front of this
// block.
void push_statement_front(Statement*that);
1998-11-04 00:28:49 +01:00
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
1998-11-04 00:28:49 +01:00
SymbolType symbol_type() const;
1998-11-04 00:28:49 +01:00
private:
BL_TYPE bl_type_;
std::vector<Statement*>list_;
1998-11-04 00:28:49 +01:00
};
class PCallTask : public Statement {
public:
2013-04-09 03:12:54 +02:00
explicit PCallTask(PPackage*pkg, const pform_name_t&n, const list<PExpr*>&parms);
explicit PCallTask(const pform_name_t&n, const list<PExpr*>&parms);
explicit PCallTask(perm_string n, const list<PExpr*>&parms);
~PCallTask();
1998-11-04 00:28:49 +01:00
const pform_name_t& path() const;
1998-11-04 00:28:49 +01:00
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
1998-11-04 00:28:49 +01:00
private:
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
1999-07-03 04:12:51 +02:00
NetProc*elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag = false) const;
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
NetProc*elaborate_void_function_(Design*des, NetScope*scope,
NetFuncDef*def) const;
2012-07-17 03:15:29 +02:00
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
NetScope*task, NetExpr*use_this) const;
NetProc*elaborate_sys_task_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
2013-04-09 03:12:54 +02:00
PPackage*package_;
pform_name_t path_;
vector<PExpr*> parms_;
1998-11-04 00:28:49 +01:00
};
class PCase : public Statement {
public:
struct Item {
list<PExpr*>expr;
Statement*stat;
};
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, svector<Item*>*);
~PCase();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
ivl_case_quality_t quality_;
1999-09-29 20:36:02 +02:00
NetCase::TYPE type_;
PExpr*expr_;
svector<Item*>*items_;
private: // not implemented
PCase(const PCase&);
PCase& operator= (const PCase&);
};
class PCAssign : public Statement {
public:
explicit PCAssign(PExpr*l, PExpr*r);
~PCAssign();
virtual NetCAssign* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
PExpr*expr_;
};
/*
* This represents the syntax "super.new(...)". This is not really an
* executable statement, but the elaborator will handle these
* specially and will remove them from the statement stream. If any
*/
class PChainConstructor : public Statement {
public:
explicit PChainConstructor(const list<PExpr*>&parms);
~PChainConstructor();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
inline const std::vector<PExpr*>& chain_args(void) const
{ return parms_; }
private:
std::vector<PExpr*> parms_;
};
class PCondit : public Statement {
public:
PCondit(PExpr*ex, Statement*i, Statement*e);
~PCondit();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*expr_;
Statement*if_;
Statement*else_;
private: // not implemented
PCondit(const PCondit&);
PCondit& operator= (const PCondit&);
};
class PDeassign : public Statement {
public:
explicit PDeassign(PExpr*l);
~PDeassign();
virtual NetDeassign* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
};
1998-11-04 00:28:49 +01:00
class PDelayStatement : public Statement {
public:
PDelayStatement(PExpr*d, Statement*st);
~PDelayStatement();
1998-11-04 00:28:49 +01:00
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
1998-11-04 00:28:49 +01:00
private:
PExpr*delay_;
Statement*statement_;
};
2000-07-26 07:08:07 +02:00
/*
2003-01-30 17:23:07 +01:00
* This represents the parsing of a disable <scope> statement.
2000-07-26 07:08:07 +02:00
*/
class PDisable : public Statement {
public:
explicit PDisable(const pform_name_t&sc);
2000-07-26 07:08:07 +02:00
~PDisable();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-07-26 07:08:07 +02:00
private:
pform_name_t scope_;
2000-07-26 07:08:07 +02:00
};
2013-09-17 05:01:06 +02:00
class PDoWhile : public Statement {
public:
PDoWhile(PExpr*ex, Statement*st);
~PDoWhile();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*cond_;
Statement*statement_;
};
2000-04-01 21:31:57 +02:00
/*
* The event statement represents the event delay in behavioral
* code. It comes from such things as:
*
* @name <statement>;
* @(expr) <statement>;
* @* <statement>;
2000-04-01 21:31:57 +02:00
*/
1998-11-04 00:28:49 +01:00
class PEventStatement : public Statement {
public:
2000-04-01 21:31:57 +02:00
explicit PEventStatement(const svector<PEEvent*>&ee);
explicit PEventStatement(PEEvent*ee);
// Make an @* statement or make a special @* version with the items
2019-09-30 01:57:09 +02:00
// from functions added and outputs removed for always_comb/latch.
explicit PEventStatement(bool always_sens = false);
1999-04-29 04:16:26 +02:00
2000-04-01 21:31:57 +02:00
~PEventStatement();
1998-11-04 00:28:49 +01:00
void set_statement(Statement*st);
1998-11-04 00:28:49 +01:00
virtual void dump(ostream&out, unsigned ind) const;
// Call this with a NULL statement only. It is used to print
// the event expression for inter-assignment event controls.
virtual void dump_inline(ostream&out) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
1998-11-04 00:28:49 +01:00
bool has_aa_term(Design*des, NetScope*scope);
1999-09-22 04:00:48 +02:00
// This method is used to elaborate, but attach a previously
// elaborated statement to the event.
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
1999-09-22 04:00:48 +02:00
NetProc* elaborate_wait(Design*des, NetScope*scope, NetProc*st) const;
NetProc* elaborate_wait_fork(Design*des, NetScope*scope) const;
1998-11-04 00:28:49 +01:00
private:
1999-04-29 04:16:26 +02:00
svector<PEEvent*>expr_;
1998-11-04 00:28:49 +01:00
Statement*statement_;
2019-09-30 01:57:09 +02:00
bool always_sens_;
1998-11-04 00:28:49 +01:00
};
ostream& operator << (ostream&o, const PEventStatement&obj);
2000-04-22 06:20:19 +02:00
class PForce : public Statement {
public:
explicit PForce(PExpr*l, PExpr*r);
~PForce();
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
2000-04-22 06:20:19 +02:00
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
PExpr*expr_;
};
class PForeach : public Statement {
public:
explicit PForeach(perm_string var, const std::list<perm_string>&ix, Statement*stmt);
~PForeach();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
const std::vector<netrange_t>&dims) const;
private:
perm_string array_var_;
std::vector<perm_string> index_vars_;
Statement*statement_;
};
class PForever : public Statement {
public:
explicit PForever(Statement*s);
~PForever();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
Statement*statement_;
};
class PForStatement : public Statement {
public:
PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
Statement*step, Statement*body);
~PForStatement();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr* name1_;
PExpr* expr1_;
PExpr*cond_;
Statement*step_;
Statement*statement_;
};
1998-11-04 00:28:49 +01:00
class PNoop : public Statement {
public:
PNoop() { }
2005-12-05 22:21:18 +01:00
~PNoop() { }
1998-11-04 00:28:49 +01:00
};
class PRepeat : public Statement {
public:
explicit PRepeat(PExpr*expr, Statement*s);
~PRepeat();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*expr_;
Statement*statement_;
};
2000-04-22 06:20:19 +02:00
class PRelease : public Statement {
public:
explicit PRelease(PExpr*l);
~PRelease();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-04-22 06:20:19 +02:00
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
};
class PReturn : public Statement {
public:
explicit PReturn(PExpr*e);
~PReturn();
NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
private:
PExpr*expr_;
};
2000-04-01 21:31:57 +02:00
/*
* The PTrigger statement sends a trigger to a named event. Take the
* name here.
*/
class PTrigger : public Statement {
public:
explicit PTrigger(PPackage*pkg, const pform_name_t&ev);
2000-04-01 21:31:57 +02:00
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-04-01 21:31:57 +02:00
virtual void dump(ostream&out, unsigned ind) const;
private:
PPackage*package_;
pform_name_t event_;
2000-04-01 21:31:57 +02:00
};
1998-11-11 04:13:04 +01:00
class PWhile : public Statement {
public:
2013-09-17 05:01:06 +02:00
PWhile(PExpr*ex, Statement*st);
1998-11-11 04:13:04 +01:00
~PWhile();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
2000-03-11 04:25:51 +01:00
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
1998-11-11 04:13:04 +01:00
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*cond_;
Statement*statement_;
};
#endif /* IVL_Statement_H */