644 lines
20 KiB
C++
644 lines
20 KiB
C++
#ifndef IVL_Statement_H
|
|
#define IVL_Statement_H
|
|
/*
|
|
* Copyright (c) 1998-2025 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
# include <string>
|
|
# include <vector>
|
|
# include <list>
|
|
# include "ivl_target.h"
|
|
# include "StringHeap.h"
|
|
# include "PDelays.h"
|
|
# include "PExpr.h"
|
|
# include "PScope.h"
|
|
# include "HName.h"
|
|
# include "LineInfo.h"
|
|
class PExpr;
|
|
class PChainConstructor;
|
|
class PPackage;
|
|
class Statement;
|
|
class PEventStatement;
|
|
class Design;
|
|
class NetAssign_;
|
|
class NetCAssign;
|
|
class NetDeassign;
|
|
class NetForce;
|
|
class NetScope;
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
class PProcess : public LineInfo {
|
|
|
|
public:
|
|
PProcess(ivl_process_type_t t, Statement*st)
|
|
: type_(t), statement_(st) { }
|
|
|
|
virtual ~PProcess() override;
|
|
|
|
bool elaborate(Design*des, NetScope*scope) const;
|
|
|
|
ivl_process_type_t type() const { return type_; }
|
|
Statement*statement() { return statement_; }
|
|
|
|
std::map<perm_string,PExpr*> attributes;
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const;
|
|
|
|
private:
|
|
ivl_process_type_t type_;
|
|
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 {
|
|
|
|
public:
|
|
Statement() { }
|
|
virtual ~Statement() override =0;
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const;
|
|
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;
|
|
|
|
std::map<perm_string,PExpr*> attributes;
|
|
};
|
|
|
|
/*
|
|
* 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 {
|
|
public:
|
|
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant,
|
|
bool is_init = false);
|
|
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
|
|
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
|
virtual ~PAssign_() override =0;
|
|
|
|
const PExpr* lval() const { return lval_; }
|
|
PExpr* rval() const { return rval_; }
|
|
|
|
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;
|
|
|
|
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
|
|
ivl_variable_type_t type) const;
|
|
|
|
PExpr* delay_;
|
|
PEventStatement*event_;
|
|
PExpr* count_;
|
|
|
|
private:
|
|
PExpr* lval_;
|
|
PExpr* rval_;
|
|
bool is_constant_;
|
|
// Whether the assignment is a variable initializer expression
|
|
bool is_init_ = false;
|
|
};
|
|
|
|
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);
|
|
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, bool is_init);
|
|
~PAssign() override;
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
|
|
private:
|
|
NetProc* elaborate_compressed_(Design*des, NetScope*scope) const;
|
|
char op_;
|
|
};
|
|
|
|
class PAssignNB : public PAssign_ {
|
|
|
|
public:
|
|
explicit PAssignNB(PExpr*lval, PExpr*ex);
|
|
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
|
|
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
|
~PAssignNB() override;
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
|
|
private:
|
|
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
|
|
Design*des, NetScope*scope) const;
|
|
};
|
|
|
|
/*
|
|
* 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 {
|
|
|
|
public:
|
|
enum BL_TYPE { BL_SEQ, BL_PAR, BL_JOIN_NONE, BL_JOIN_ANY };
|
|
|
|
// 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);
|
|
~PBlock() override;
|
|
|
|
BL_TYPE bl_type() const { return bl_type_; }
|
|
|
|
bool var_init_needs_explicit_lifetime() const override;
|
|
|
|
// 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);
|
|
|
|
// Copy the statement from that block to the front of this
|
|
// block.
|
|
void push_statement_front(Statement*that);
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
|
|
SymbolType symbol_type() const override;
|
|
|
|
private:
|
|
BL_TYPE bl_type_;
|
|
std::vector<Statement*>list_;
|
|
};
|
|
|
|
class PBreak : public Statement {
|
|
public:
|
|
void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
};
|
|
|
|
class PCallTask : public Statement {
|
|
|
|
public:
|
|
explicit PCallTask(PPackage *pkg, const pform_name_t &n, const std::list<named_pexpr_t> &parms);
|
|
explicit PCallTask(const pform_name_t &n, const std::list<named_pexpr_t> &parms);
|
|
explicit PCallTask(perm_string n, const std::list<named_pexpr_t> &parms);
|
|
~PCallTask() override;
|
|
|
|
const pform_name_t& path() const;
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
|
|
bool elaborate_elab(Design*des, NetScope*scope) const;
|
|
|
|
void void_cast() { void_cast_ = true; }
|
|
|
|
private:
|
|
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
|
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
|
|
|
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;
|
|
NetProc *elaborate_non_void_function_(Design *des, NetScope *scope) const;
|
|
|
|
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 std::vector<perm_string> &parm_names = {}) const;
|
|
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
|
|
NetNet*net,
|
|
perm_string method_name,
|
|
const char *sys_task_name,
|
|
const std::vector<perm_string> &parm_names) const;
|
|
NetProc*elaborate_method_func_(NetScope*scope,
|
|
NetNet*net,
|
|
ivl_type_t type,
|
|
perm_string method_name,
|
|
const char*sys_task_name) const;
|
|
bool test_task_calls_ok_(Design*des, const NetScope*scope) const;
|
|
|
|
PPackage*package_;
|
|
pform_name_t path_;
|
|
std::vector<named_pexpr_t> parms_;
|
|
bool void_cast_ = false;
|
|
};
|
|
|
|
class PCase : public Statement {
|
|
|
|
public:
|
|
struct Item {
|
|
std::list<PExpr*>expr;
|
|
Statement*stat;
|
|
};
|
|
|
|
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, std::vector<Item*>*);
|
|
~PCase() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
ivl_case_quality_t quality_;
|
|
NetCase::TYPE type_;
|
|
PExpr*expr_;
|
|
|
|
std::vector<Item*>*items_;
|
|
|
|
private: // not implemented
|
|
PCase(const PCase&);
|
|
PCase& operator= (const PCase&);
|
|
};
|
|
|
|
class PCAssign : public Statement {
|
|
|
|
public:
|
|
explicit PCAssign(PExpr*l, PExpr*r);
|
|
~PCAssign() override;
|
|
|
|
virtual NetCAssign* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
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 std::list<named_pexpr_t> &parms);
|
|
explicit PChainConstructor(const std::vector<named_pexpr_t> &parms);
|
|
~PChainConstructor() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
inline const std::vector<named_pexpr_t>& chain_args(void) const
|
|
{ return parms_; }
|
|
|
|
private:
|
|
std::vector<named_pexpr_t> parms_;
|
|
};
|
|
|
|
class PCondit : public Statement {
|
|
|
|
public:
|
|
PCondit(PExpr*ex, Statement*i, Statement*e);
|
|
~PCondit() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*expr_;
|
|
Statement*if_;
|
|
Statement*else_;
|
|
|
|
private: // not implemented
|
|
PCondit(const PCondit&);
|
|
PCondit& operator= (const PCondit&);
|
|
};
|
|
|
|
class PContinue : public Statement {
|
|
|
|
public:
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
};
|
|
|
|
class PDeassign : public Statement {
|
|
|
|
public:
|
|
explicit PDeassign(PExpr*l);
|
|
~PDeassign() override;
|
|
|
|
virtual NetDeassign* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*lval_;
|
|
};
|
|
|
|
class PDelayStatement : public Statement {
|
|
|
|
public:
|
|
PDelayStatement(PExpr*d, Statement*st);
|
|
~PDelayStatement() override;
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
|
|
private:
|
|
PExpr*delay_;
|
|
Statement*statement_;
|
|
};
|
|
|
|
|
|
/*
|
|
* This represents the parsing of a disable <scope> statement.
|
|
*/
|
|
class PDisable : public Statement {
|
|
|
|
public:
|
|
explicit PDisable(const pform_name_t&sc);
|
|
~PDisable() override;
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
|
|
private:
|
|
pform_name_t scope_;
|
|
};
|
|
|
|
class PDoWhile : public Statement {
|
|
|
|
public:
|
|
PDoWhile(PExpr*ex, Statement*st);
|
|
~PDoWhile() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*cond_;
|
|
Statement*statement_;
|
|
};
|
|
|
|
/*
|
|
* The event statement represents the event delay in behavioral
|
|
* code. It comes from such things as:
|
|
*
|
|
* @name <statement>;
|
|
* @(expr) <statement>;
|
|
* @* <statement>;
|
|
*/
|
|
class PEventStatement : public Statement {
|
|
|
|
public:
|
|
|
|
explicit PEventStatement(const std::vector<PEEvent*>&ee);
|
|
explicit PEventStatement(PEEvent*ee);
|
|
// Make an @* statement or make a special @* version with the items
|
|
// from functions added and outputs removed for always_comb/latch.
|
|
explicit PEventStatement(bool always_sens = false);
|
|
|
|
~PEventStatement() override;
|
|
|
|
void set_statement(Statement*st);
|
|
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
// Call this with a NULL statement only. It is used to print
|
|
// the event expression for inter-assignment event controls.
|
|
virtual void dump_inline(std::ostream&out) const;
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
|
|
bool has_aa_term(Design*des, NetScope*scope);
|
|
|
|
// 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;
|
|
|
|
NetProc* elaborate_wait(Design*des, NetScope*scope, NetProc*st) const;
|
|
NetProc* elaborate_wait_fork(Design*des, const NetScope*scope) const;
|
|
|
|
private:
|
|
std::vector<PEEvent*>expr_;
|
|
Statement*statement_;
|
|
bool always_sens_;
|
|
};
|
|
|
|
std::ostream& operator << (std::ostream&o, const PEventStatement&obj);
|
|
|
|
class PForce : public Statement {
|
|
|
|
public:
|
|
explicit PForce(PExpr*l, PExpr*r);
|
|
~PForce() override;
|
|
|
|
virtual NetForce* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*lval_;
|
|
PExpr*expr_;
|
|
};
|
|
|
|
class PForeach : public Statement {
|
|
public:
|
|
explicit PForeach(perm_string var, const std::list<perm_string>&ix, Statement*stmt);
|
|
~PForeach() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
|
|
const netranges_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() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
Statement*statement_;
|
|
};
|
|
|
|
class PForStatement : public Statement {
|
|
|
|
public:
|
|
PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
|
|
Statement*step, Statement*body);
|
|
~PForStatement() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr* name1_;
|
|
PExpr* expr1_;
|
|
|
|
PExpr*cond_;
|
|
|
|
Statement*step_;
|
|
|
|
Statement*statement_;
|
|
};
|
|
|
|
class PNoop : public Statement {
|
|
|
|
public:
|
|
PNoop() { }
|
|
~PNoop() override { }
|
|
};
|
|
|
|
class PRepeat : public Statement {
|
|
public:
|
|
explicit PRepeat(PExpr*expr, Statement*s);
|
|
~PRepeat() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*expr_;
|
|
Statement*statement_;
|
|
};
|
|
|
|
class PRelease : public Statement {
|
|
|
|
public:
|
|
explicit PRelease(PExpr*l);
|
|
~PRelease() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*lval_;
|
|
};
|
|
|
|
class PReturn : public Statement {
|
|
|
|
public:
|
|
explicit PReturn(PExpr*e);
|
|
~PReturn() override;
|
|
|
|
NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*expr_;
|
|
};
|
|
|
|
/*
|
|
* 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, unsigned lexical_pos);
|
|
~PTrigger() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
pform_scoped_name_t event_;
|
|
unsigned lexical_pos_;
|
|
};
|
|
|
|
class PNBTrigger : public Statement {
|
|
public:
|
|
explicit PNBTrigger(const pform_name_t&ev, unsigned lexical_pos, PExpr*dly);
|
|
~PNBTrigger() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
pform_name_t event_;
|
|
unsigned lexical_pos_;
|
|
PExpr*dly_;
|
|
};
|
|
|
|
class PWhile : public Statement {
|
|
|
|
public:
|
|
PWhile(PExpr*ex, Statement*st);
|
|
~PWhile() override;
|
|
|
|
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
|
|
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
|
|
virtual void dump(std::ostream&out, unsigned ind) const override;
|
|
|
|
private:
|
|
PExpr*cond_;
|
|
Statement*statement_;
|
|
};
|
|
|
|
#endif /* IVL_Statement_H */
|