yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
AST::AstNode Struct Reference

#include <ast.h>

+ Collaboration diagram for AST::AstNode:

Data Structures

struct  varinfo_t
 

Public Types

enum  mem2reg_flags {
  MEM2REG_FL_ALL = 0x00000001, MEM2REG_FL_ASYNC = 0x00000002, MEM2REG_FL_INIT = 0x00000004, MEM2REG_FL_FORCED = 0x00000100,
  MEM2REG_FL_SET_INIT = 0x00000200, MEM2REG_FL_SET_ELSE = 0x00000400, MEM2REG_FL_SET_ASYNC = 0x00000800, MEM2REG_FL_EQ2 = 0x00001000,
  MEM2REG_FL_CMPLX_LHS = 0x00002000, MEM2REG_FL_EQ1 = 0x01000000
}
 

Public Member Functions

bool get_bool_attribute (RTLIL::IdString id)
 
 AstNode (AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
 
AstNodeclone ()
 
void cloneInto (AstNode *other)
 
void delete_children ()
 
 ~AstNode ()
 
bool simplify (bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
 
AstNodereadmem (bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr)
 
void expand_genblock (std::string index_var, std::string prefix, std::map< std::string, std::string > &name_map)
 
void replace_ids (const std::string &prefix, const std::map< std::string, std::string > &rules)
 
void mem2reg_as_needed_pass1 (std::map< AstNode *, std::set< std::string >> &mem2reg_places, std::map< AstNode *, uint32_t > &mem2reg_flags, std::map< AstNode *, uint32_t > &proc_flags, uint32_t &status_flags)
 
void mem2reg_as_needed_pass2 (std::set< AstNode * > &mem2reg_set, AstNode *mod, AstNode *block)
 
bool mem2reg_check (std::set< AstNode * > &mem2reg_set)
 
void meminfo (int &mem_width, int &mem_size, int &addr_bits)
 
bool has_const_only_constructs (bool &recommend_const_eval)
 
void replace_variables (std::map< std::string, varinfo_t > &variables, AstNode *fcall)
 
AstNodeeval_const_function (AstNode *fcall)
 
void dumpAst (FILE *f, std::string indent)
 
void dumpVlog (FILE *f, std::string indent)
 
void detectSignWidthWorker (int &width_hint, bool &sign_hint, bool *found_real=NULL)
 
void detectSignWidth (int &width_hint, bool &sign_hint, bool *found_real=NULL)
 
RTLIL::SigSpec genRTLIL (int width_hint=-1, bool sign_hint=false)
 
RTLIL::SigSpec genWidthRTLIL (int width, const std::map< RTLIL::SigBit, RTLIL::SigBit > *new_subst_ptr=NULL)
 
bool operator== (const AstNode &other) const
 
bool operator!= (const AstNode &other) const
 
bool contains (const AstNode *other) const
 
RTLIL::Const bitsAsConst (int width, bool is_signed)
 
RTLIL::Const bitsAsConst (int width=-1)
 
RTLIL::Const asAttrConst ()
 
RTLIL::Const asParaConst ()
 
uint64_t asInt (bool is_signed)
 
bool bits_only_01 ()
 
bool asBool ()
 
int isConst ()
 
double asReal (bool is_signed)
 
RTLIL::Const realAsConst (int width)
 

Static Public Member Functions

static AstNodemkconst_int (uint32_t v, bool is_signed, int width=32)
 
static AstNodemkconst_bits (const std::vector< RTLIL::State > &v, bool is_signed)
 
static AstNodemkconst_str (const std::vector< RTLIL::State > &v)
 
static AstNodemkconst_str (const std::string &str)
 

Data Fields

AstNodeType type
 
std::vector< AstNode * > children
 
std::map< RTLIL::IdString,
AstNode * > 
attributes
 
std::string str
 
std::vector< RTLIL::Statebits
 
bool is_input
 
bool is_output
 
bool is_reg
 
bool is_signed
 
bool is_string
 
bool range_valid
 
bool range_swapped
 
int port_id
 
int range_left
 
int range_right
 
uint32_t integer
 
double realvalue
 
std::vector< int > multirange_dimensions
 
AstNodeid2ast
 
bool basic_prep
 
std::string filename
 
int linenum
 

Detailed Description

Definition at line 143 of file ast.h.

Member Enumeration Documentation

Enumerator
MEM2REG_FL_ALL 
MEM2REG_FL_ASYNC 
MEM2REG_FL_INIT 
MEM2REG_FL_FORCED 
MEM2REG_FL_SET_INIT 
MEM2REG_FL_SET_ELSE 
MEM2REG_FL_SET_ASYNC 
MEM2REG_FL_EQ2 
MEM2REG_FL_CMPLX_LHS 
MEM2REG_FL_EQ1 

Definition at line 185 of file ast.h.

186  {
187  /* status flags */
188  MEM2REG_FL_ALL = 0x00000001,
189  MEM2REG_FL_ASYNC = 0x00000002,
190  MEM2REG_FL_INIT = 0x00000004,
191 
192  /* candidate flags */
193  MEM2REG_FL_FORCED = 0x00000100,
194  MEM2REG_FL_SET_INIT = 0x00000200,
195  MEM2REG_FL_SET_ELSE = 0x00000400,
196  MEM2REG_FL_SET_ASYNC = 0x00000800,
197  MEM2REG_FL_EQ2 = 0x00001000,
198  MEM2REG_FL_CMPLX_LHS = 0x00002000,
199 
200  /* proc flags */
201  MEM2REG_FL_EQ1 = 0x01000000,
202  };

Constructor & Destructor Documentation

AstNode::AstNode ( AstNodeType  type = AST_NONE,
AstNode child1 = NULL,
AstNode child2 = NULL 
)

Definition at line 181 of file ast.cc.

182 {
183  this->type = type;
185  linenum = get_line_num();
186  is_input = false;
187  is_output = false;
188  is_reg = false;
189  is_signed = false;
190  is_string = false;
191  range_valid = false;
192  range_swapped = false;
193  port_id = 0;
194  range_left = -1;
195  range_right = 0;
196  integer = 0;
197  realvalue = 0;
198  id2ast = NULL;
199  basic_prep = false;
200 
201  if (child1)
202  children.push_back(child1);
203  if (child2)
204  children.push_back(child2);
205 }
bool range_valid
Definition: ast.h:158
AstNode * id2ast
Definition: ast.h:167
bool range_swapped
Definition: ast.h:158
int(* get_line_num)()
Definition: ast.cc:51
int range_right
Definition: ast.h:159
bool is_reg
Definition: ast.h:158
double realvalue
Definition: ast.h:161
AstNodeType type
Definition: ast.h:146
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
std::string current_filename
Definition: ast.cc:49
#define NULL
std::string filename
Definition: ast.h:175
bool is_signed
Definition: ast.h:158
std::vector< AstNode * > children
Definition: ast.h:149
bool is_string
Definition: ast.h:158
int linenum
Definition: ast.h:176
bool basic_prep
Definition: ast.h:170
bool is_output
Definition: ast.h:158
int port_id
Definition: ast.h:159
bool is_input
Definition: ast.h:158
AstNode::~AstNode ( )

Definition at line 243 of file ast.cc.

244 {
245  delete_children();
246 }
void delete_children()
Definition: ast.cc:231

Member Function Documentation

RTLIL::Const AstNode::asAttrConst ( )

Definition at line 761 of file ast.cc.

762 {
764 
765  RTLIL::Const val;
766  val.bits = bits;
767 
768  if (is_string) {
770  log_assert(val.decode_string() == str);
771  }
772 
773  return val;
774 }
int flags
Definition: rtlil.h:437
std::string decode_string() const
Definition: rtlil.cc:131
#define log_assert(_assert_expr_)
Definition: log.h:85
AstNodeType type
Definition: ast.h:146
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
std::string str
Definition: ast.h:156
std::vector< RTLIL::State > bits
Definition: ast.h:157
bool is_string
Definition: ast.h:158

+ Here is the call graph for this function:

bool AstNode::asBool ( )

Definition at line 784 of file ast.cc.

785 {
787  for (auto &bit : bits)
788  if (bit == RTLIL::State::S1)
789  return true;
790  return false;
791 }
#define log_assert(_assert_expr_)
Definition: log.h:85
AstNodeType type
Definition: ast.h:146
std::vector< RTLIL::State > bits
Definition: ast.h:157

+ Here is the caller graph for this function:

uint64_t AstNode::asInt ( bool  is_signed)

Definition at line 802 of file ast.cc.

803 {
804  if (type == AST_CONSTANT)
805  {
807  uint64_t ret = 0;
808 
809  for (int i = 0; i < 64; i++)
810  if (v.bits.at(i) == RTLIL::State::S1)
811  ret |= uint64_t(1) << i;
812 
813  return ret;
814  }
815 
816  if (type == AST_REALVALUE)
817  return realvalue;
818 
819  log_abort();
820 }
RTLIL::Const bitsAsConst(int width, bool is_signed)
Definition: ast.cc:741
#define log_abort()
Definition: log.h:84
double realvalue
Definition: ast.h:161
AstNodeType type
Definition: ast.h:146
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
bool is_signed
Definition: ast.h:158

+ Here is the caller graph for this function:

RTLIL::Const AstNode::asParaConst ( )

Definition at line 776 of file ast.cc.

777 {
778  RTLIL::Const val = asAttrConst();
779  if (is_signed)
781  return val;
782 }
int flags
Definition: rtlil.h:437
bool is_signed
Definition: ast.h:158
RTLIL::Const asAttrConst()
Definition: ast.cc:761
double AstNode::asReal ( bool  is_signed)

Definition at line 822 of file ast.cc.

823 {
824  if (type == AST_CONSTANT)
825  {
826  RTLIL::Const val(bits);
827 
828  bool is_negative = is_signed && val.bits.back() == RTLIL::State::S1;
829  if (is_negative)
830  val = const_neg(val, val, false, false, val.bits.size());
831 
832  double v = 0;
833  for (size_t i = 0; i < val.bits.size(); i++)
834  // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
835  // the net or the variable shall be treated as zero upon conversion.
836  if (val.bits.at(i) == RTLIL::State::S1)
837  v += exp2(i);
838  if (is_negative)
839  v *= -1;
840 
841  return v;
842  }
843 
844  if (type == AST_REALVALUE)
845  return realvalue;
846 
847  log_abort();
848 }
#define log_abort()
Definition: log.h:84
double realvalue
Definition: ast.h:161
AstNodeType type
Definition: ast.h:146
bool is_signed
Definition: ast.h:158
RTLIL::Const const_neg(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:570
std::vector< RTLIL::State > bits
Definition: ast.h:157

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool AstNode::bits_only_01 ( )

Definition at line 733 of file ast.cc.

734 {
735  for (auto bit : bits)
736  if (bit != RTLIL::S0 && bit != RTLIL::S1)
737  return false;
738  return true;
739 }
std::vector< RTLIL::State > bits
Definition: ast.h:157
RTLIL::Const AstNode::bitsAsConst ( int  width,
bool  is_signed 
)

Definition at line 741 of file ast.cc.

742 {
743  std::vector<RTLIL::State> bits = this->bits;
744  if (width >= 0 && width < int(bits.size()))
745  bits.resize(width);
746  if (width >= 0 && width > int(bits.size())) {
748  if (is_signed && !bits.empty())
749  extbit = bits.back();
750  while (width > int(bits.size()))
751  bits.push_back(extbit);
752  }
753  return RTLIL::Const(bits);
754 }
bool is_signed
Definition: ast.h:158
State
Definition: rtlil.h:29
std::vector< RTLIL::State > bits
Definition: ast.h:157

+ Here is the caller graph for this function:

RTLIL::Const AstNode::bitsAsConst ( int  width = -1)

Definition at line 756 of file ast.cc.

757 {
758  return bitsAsConst(width, is_signed);
759 }
RTLIL::Const bitsAsConst(int width, bool is_signed)
Definition: ast.cc:741
bool is_signed
Definition: ast.h:158
AstNode * AstNode::clone ( )

Definition at line 208 of file ast.cc.

209 {
210  AstNode *that = new AstNode;
211  *that = *this;
212  for (auto &it : that->children)
213  it = it->clone();
214  for (auto &it : that->attributes)
215  it.second = it.second->clone();
216  return that;
217 }
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
AstNode * clone()
Definition: ast.cc:208
std::vector< AstNode * > children
Definition: ast.h:149

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void AstNode::cloneInto ( AstNode other)

Definition at line 220 of file ast.cc.

221 {
222  AstNode *tmp = clone();
223  other->delete_children();
224  *other = *tmp;
225  tmp->children.clear();
226  tmp->attributes.clear();
227  delete tmp;
228 }
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
AstNode * clone()
Definition: ast.cc:208
std::vector< AstNode * > children
Definition: ast.h:149
void delete_children()
Definition: ast.cc:231

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool AstNode::contains ( const AstNode other) const

Definition at line 661 of file ast.cc.

662 {
663  if (this == other)
664  return true;
665  for (auto child : children)
666  if (child->contains(other))
667  return true;
668  return false;
669 }
std::vector< AstNode * > children
Definition: ast.h:149
void AstNode::delete_children ( )

Definition at line 231 of file ast.cc.

232 {
233  for (auto &it : children)
234  delete it;
235  children.clear();
236 
237  for (auto &it : attributes)
238  delete it.second;
239  attributes.clear();
240 }
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
std::vector< AstNode * > children
Definition: ast.h:149

+ Here is the caller graph for this function:

void AstNode::detectSignWidth ( int &  width_hint,
bool &  sign_hint,
bool *  found_real = NULL 
)

Definition at line 746 of file genrtlil.cc.

747 {
748  width_hint = -1;
749  sign_hint = true;
750  if (found_real)
751  *found_real = false;
752  detectSignWidthWorker(width_hint, sign_hint, found_real);
753 }
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real=NULL)
Definition: genrtlil.cc:534

+ Here is the caller graph for this function:

void AstNode::detectSignWidthWorker ( int &  width_hint,
bool &  sign_hint,
bool *  found_real = NULL 
)

Definition at line 534 of file genrtlil.cc.

535 {
536  std::string type_name;
537  bool sub_sign_hint = true;
538  int sub_width_hint = -1;
539  int this_width = 0;
540  AstNode *range = NULL;
541  AstNode *id_ast = NULL;
542 
543  bool local_found_real = false;
544  if (found_real == NULL)
545  found_real = &local_found_real;
546 
547  switch (type)
548  {
549  case AST_CONSTANT:
550  width_hint = std::max(width_hint, int(bits.size()));
551  if (!is_signed)
552  sign_hint = false;
553  break;
554 
555  case AST_REALVALUE:
556  *found_real = true;
557  width_hint = std::max(width_hint, 32);
558  break;
559 
560  case AST_IDENTIFIER:
561  id_ast = id2ast;
562  if (id_ast == NULL && current_scope.count(str))
563  id_ast = current_scope.at(str);
564  if (!id_ast)
565  log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
566  if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) {
567  if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
568  this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
569  } else
570  if (id_ast->children[0]->type == AST_CONSTANT) {
571  this_width = id_ast->children[0]->bits.size();
572  } else
573  log_error("Failed to detect width for parameter %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
574  if (children.size() != 0)
575  range = children[0];
576  } else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
577  if (!id_ast->range_valid) {
578  if (id_ast->type == AST_AUTOWIRE)
579  this_width = 1;
580  else {
581  // current_ast_mod->dumpAst(NULL, "mod> ");
582  // log("---\n");
583  // id_ast->dumpAst(NULL, "decl> ");
584  // dumpAst(NULL, "ref> ");
585  log_error("Failed to detect with of signal access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
586  }
587  } else {
588  this_width = id_ast->range_left - id_ast->range_right + 1;
589  if (children.size() != 0)
590  range = children[0];
591  }
592  } else if (id_ast->type == AST_GENVAR) {
593  this_width = 32;
594  } else if (id_ast->type == AST_MEMORY) {
595  if (!id_ast->children[0]->range_valid)
596  log_error("Failed to detect with of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
597  this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
598  } else
599  log_error("Failed to detect width for identifier %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
600  if (range) {
601  if (range->children.size() == 1)
602  this_width = 1;
603  else if (!range->range_valid) {
604  AstNode *left_at_zero_ast = children[0]->children[0]->clone();
605  AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : left_at_zero_ast->clone();
606  while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
607  while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
608  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
609  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
610  str.c_str(), filename.c_str(), linenum);
611  this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
612  delete left_at_zero_ast;
613  delete right_at_zero_ast;
614  } else
615  this_width = range->range_left - range->range_right + 1;
616  sign_hint = false;
617  }
618  width_hint = std::max(width_hint, this_width);
619  if (!id_ast->is_signed)
620  sign_hint = false;
621  break;
622 
623  case AST_TO_BITS:
624  while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { }
625  if (children[0]->type != AST_CONSTANT)
626  log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
627  children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
628  width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int());
629  break;
630 
631  case AST_TO_SIGNED:
632  children.at(0)->detectSignWidthWorker(width_hint, sub_sign_hint);
633  break;
634 
635  case AST_TO_UNSIGNED:
636  children.at(0)->detectSignWidthWorker(width_hint, sub_sign_hint);
637  sign_hint = false;
638  break;
639 
640  case AST_CONCAT:
641  for (auto child : children) {
642  sub_width_hint = 0;
643  sub_sign_hint = true;
644  child->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
645  this_width += sub_width_hint;
646  }
647  width_hint = std::max(width_hint, this_width);
648  sign_hint = false;
649  break;
650 
651  case AST_REPLICATE:
652  while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
653  if (children[0]->type != AST_CONSTANT)
654  log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
655  children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
656  width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint);
657  sign_hint = false;
658  break;
659 
660  case AST_NEG:
661  case AST_BIT_NOT:
662  case AST_POS:
663  children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);
664  break;
665 
666  case AST_BIT_AND:
667  case AST_BIT_OR:
668  case AST_BIT_XOR:
669  case AST_BIT_XNOR:
670  for (auto child : children)
671  child->detectSignWidthWorker(width_hint, sign_hint, found_real);
672  break;
673 
674  case AST_REDUCE_AND:
675  case AST_REDUCE_OR:
676  case AST_REDUCE_XOR:
677  case AST_REDUCE_XNOR:
678  case AST_REDUCE_BOOL:
679  width_hint = std::max(width_hint, 1);
680  sign_hint = false;
681  break;
682 
683  case AST_SHIFT_LEFT:
684  case AST_SHIFT_RIGHT:
685  case AST_SHIFT_SLEFT:
686  case AST_SHIFT_SRIGHT:
687  case AST_POW:
688  children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);
689  break;
690 
691  case AST_LT:
692  case AST_LE:
693  case AST_EQ:
694  case AST_NE:
695  case AST_EQX:
696  case AST_NEX:
697  case AST_GE:
698  case AST_GT:
699  width_hint = std::max(width_hint, 1);
700  sign_hint = false;
701  break;
702 
703  case AST_ADD:
704  case AST_SUB:
705  case AST_MUL:
706  case AST_DIV:
707  case AST_MOD:
708  for (auto child : children)
709  child->detectSignWidthWorker(width_hint, sign_hint, found_real);
710  break;
711 
712  case AST_LOGIC_AND:
713  case AST_LOGIC_OR:
714  case AST_LOGIC_NOT:
715  width_hint = std::max(width_hint, 1);
716  sign_hint = false;
717  break;
718 
719  case AST_TERNARY:
720  children.at(1)->detectSignWidthWorker(width_hint, sign_hint, found_real);
721  children.at(2)->detectSignWidthWorker(width_hint, sign_hint, found_real);
722  break;
723 
724  case AST_MEMRD:
725  if (!id2ast->is_signed)
726  sign_hint = false;
727  if (!id2ast->children[0]->range_valid)
728  log_error("Failed to detect with of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
729  this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1;
730  width_hint = std::max(width_hint, this_width);
731  break;
732 
733  // everything should have been handled above -> print error if not.
734  default:
735  for (auto f : log_files)
736  current_ast->dumpAst(f, "verilog-ast> ");
737  log_error("Don't know how to detect sign and width for %s node at %s:%d!\n",
738  type2str(type).c_str(), filename.c_str(), linenum);
739  }
740 
741  if (*found_real)
742  sign_hint = true;
743 }
std::map< std::string, AstNode * > current_scope
Definition: ast.cc:58
RTLIL::Const bitsAsConst(int width, bool is_signed)
Definition: ast.cc:741
bool range_valid
Definition: ast.h:158
void dumpAst(FILE *f, std::string indent)
Definition: ast.cc:250
void log_error(const char *format,...)
Definition: log.cc:204
AstNode * id2ast
Definition: ast.h:167
AstNode * current_ast
Definition: ast.cc:57
std::string type2str(AstNodeType type)
Definition: ast.cc:66
YOSYS_NAMESPACE_BEGIN std::vector< FILE * > log_files
Definition: log.cc:37
int range_right
Definition: ast.h:159
AstNodeType type
Definition: ast.h:146
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
AstNode * clone()
Definition: ast.cc:208
#define NULL
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
std::string filename
Definition: ast.h:175
bool is_signed
Definition: ast.h:158
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
std::vector< RTLIL::State > bits
Definition: ast.h:157
int linenum
Definition: ast.h:176

+ Here is the call graph for this function:

void AstNode::dumpAst ( FILE *  f,
std::string  indent 
)

Definition at line 250 of file ast.cc.

251 {
252  if (f == NULL) {
253  for (auto f : log_files)
254  dumpAst(f, indent);
255  return;
256  }
257 
258  std::string type_name = type2str(type);
259  fprintf(f, "%s%s <%s:%d>", indent.c_str(), type_name.c_str(), filename.c_str(), linenum);
260 
261  if (id2ast)
262  fprintf(f, " [%p -> %p]", this, id2ast);
263  else
264  fprintf(f, " [%p]", this);
265 
266  if (!str.empty())
267  fprintf(f, " str='%s'", str.c_str());
268  if (!bits.empty()) {
269  fprintf(f, " bits='");
270  for (size_t i = bits.size(); i > 0; i--)
271  fprintf(f, "%c", bits[i-1] == RTLIL::S0 ? '0' :
272  bits[i-1] == RTLIL::S1 ? '1' :
273  bits[i-1] == RTLIL::Sx ? 'x' :
274  bits[i-1] == RTLIL::Sz ? 'z' : '?');
275  fprintf(f, "'(%d)", GetSize(bits));
276  }
277  if (is_input)
278  fprintf(f, " input");
279  if (is_output)
280  fprintf(f, " output");
281  if (is_reg)
282  fprintf(f, " reg");
283  if (is_signed)
284  fprintf(f, " signed");
285  if (port_id > 0)
286  fprintf(f, " port=%d", port_id);
287  if (range_valid || range_left != -1 || range_right != 0)
288  fprintf(f, " %srange=[%d:%d]%s", range_swapped ? "swapped_" : "", range_left, range_right, range_valid ? "" : "!");
289  if (integer != 0)
290  fprintf(f, " int=%u", (int)integer);
291  if (realvalue != 0)
292  fprintf(f, " real=%e", realvalue);
293  if (!multirange_dimensions.empty()) {
294  fprintf(f, " multirange=[");
295  for (int v : multirange_dimensions)
296  fprintf(f, " %d", v);
297  fprintf(f, " ]");
298  }
299  fprintf(f, "\n");
300 
301  for (auto &it : attributes) {
302  fprintf(f, "%s ATTR %s:\n", indent.c_str(), it.first.c_str());
303  it.second->dumpAst(f, indent + " ");
304  }
305 
306  for (size_t i = 0; i < children.size(); i++)
307  children[i]->dumpAst(f, indent + " ");
308 }
bool range_valid
Definition: ast.h:158
void dumpAst(FILE *f, std::string indent)
Definition: ast.cc:250
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
AstNode * id2ast
Definition: ast.h:167
bool range_swapped
Definition: ast.h:158
std::string type2str(AstNodeType type)
Definition: ast.cc:66
YOSYS_NAMESPACE_BEGIN std::vector< FILE * > log_files
Definition: log.cc:37
int range_right
Definition: ast.h:159
bool is_reg
Definition: ast.h:158
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
double realvalue
Definition: ast.h:161
AstNodeType type
Definition: ast.h:146
std::vector< int > multirange_dimensions
Definition: ast.h:164
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
#define NULL
std::string filename
Definition: ast.h:175
bool is_signed
Definition: ast.h:158
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
std::vector< RTLIL::State > bits
Definition: ast.h:157
int linenum
Definition: ast.h:176
bool is_output
Definition: ast.h:158
int port_id
Definition: ast.h:159
bool is_input
Definition: ast.h:158

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void AstNode::dumpVlog ( FILE *  f,
std::string  indent 
)

Definition at line 327 of file ast.cc.

328 {
329  bool first = true;
330  std::string txt;
331  std::vector<AstNode*> rem_children1, rem_children2;
332 
333  if (f == NULL) {
334  for (auto f : log_files)
335  dumpVlog(f, indent);
336  return;
337  }
338 
339  for (auto &it : attributes) {
340  fprintf(f, "%s" "(* %s = ", indent.c_str(), id2vl(it.first.str()).c_str());
341  it.second->dumpVlog(f, "");
342  fprintf(f, " *)%s", indent.empty() ? "" : "\n");
343  }
344 
345  switch (type)
346  {
347  case AST_MODULE:
348  fprintf(f, "%s" "module %s(", indent.c_str(), id2vl(str).c_str());
349  for (auto child : children)
350  if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
351  fprintf(f, "%s%s", first ? "" : ", ", id2vl(child->str).c_str());
352  first = false;
353  }
354  fprintf(f, ");\n");
355 
356  for (auto child : children)
357  if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_DEFPARAM)
358  child->dumpVlog(f, indent + " ");
359  else
360  rem_children1.push_back(child);
361 
362  for (auto child : rem_children1)
363  if (child->type == AST_WIRE || child->type == AST_AUTOWIRE || child->type == AST_MEMORY)
364  child->dumpVlog(f, indent + " ");
365  else
366  rem_children2.push_back(child);
367  rem_children1.clear();
368 
369  for (auto child : rem_children2)
370  if (child->type == AST_TASK || child->type == AST_FUNCTION)
371  child->dumpVlog(f, indent + " ");
372  else
373  rem_children1.push_back(child);
374  rem_children2.clear();
375 
376  for (auto child : rem_children1)
377  child->dumpVlog(f, indent + " ");
378  rem_children1.clear();
379 
380  fprintf(f, "%s" "endmodule\n", indent.c_str());
381  break;
382 
383  case AST_WIRE:
384  if (is_input && is_output)
385  fprintf(f, "%s" "inout", indent.c_str());
386  else if (is_input)
387  fprintf(f, "%s" "input", indent.c_str());
388  else if (is_output)
389  fprintf(f, "%s" "output", indent.c_str());
390  else if (!is_reg)
391  fprintf(f, "%s" "wire", indent.c_str());
392  if (is_reg)
393  fprintf(f, "%s" "reg", (is_input || is_output) ? " " : indent.c_str());
394  if (is_signed)
395  fprintf(f, " signed");
396  for (auto child : children) {
397  fprintf(f, " ");
398  child->dumpVlog(f, "");
399  }
400  fprintf(f, " %s", id2vl(str).c_str());
401  fprintf(f, ";\n");
402  break;
403 
404  case AST_MEMORY:
405  fprintf(f, "%s" "memory", indent.c_str());
406  if (is_signed)
407  fprintf(f, " signed");
408  for (auto child : children) {
409  fprintf(f, " ");
410  child->dumpVlog(f, "");
411  if (first)
412  fprintf(f, " %s", id2vl(str).c_str());
413  first = false;
414  }
415  fprintf(f, ";\n");
416  break;
417 
418  case AST_RANGE:
419  if (range_valid)
420  fprintf(f, "[%d:%d]", range_left, range_right);
421  else {
422  for (auto child : children) {
423  fprintf(f, "%c", first ? '[' : ':');
424  child->dumpVlog(f, "");
425  first = false;
426  }
427  fprintf(f, "]");
428  }
429  break;
430 
431  case AST_ALWAYS:
432  fprintf(f, "%s" "always @(", indent.c_str());
433  for (auto child : children) {
434  if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
435  continue;
436  if (!first)
437  fprintf(f, ", ");
438  child->dumpVlog(f, "");
439  first = false;
440  }
441  fprintf(f, ")\n");
442  for (auto child : children) {
443  if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
444  child->dumpVlog(f, indent + " ");
445  }
446  break;
447 
448  case AST_INITIAL:
449  fprintf(f, "%s" "initial\n", indent.c_str());
450  for (auto child : children) {
451  if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
452  child->dumpVlog(f, indent + " ");
453  }
454  break;
455 
456  case AST_POSEDGE:
457  case AST_NEGEDGE:
458  case AST_EDGE:
459  if (type == AST_POSEDGE)
460  fprintf(f, "posedge ");
461  if (type == AST_NEGEDGE)
462  fprintf(f, "negedge ");
463  for (auto child : children)
464  child->dumpVlog(f, "");
465  break;
466 
467  case AST_IDENTIFIER:
468  fprintf(f, "%s", id2vl(str).c_str());
469  for (auto child : children)
470  child->dumpVlog(f, "");
471  break;
472 
473  case AST_CONSTANT:
474  if (!str.empty())
475  fprintf(f, "\"%s\"", str.c_str());
476  else if (bits.size() == 32)
477  fprintf(f, "%d", RTLIL::Const(bits).as_int());
478  else
479  fprintf(f, "%d'b %s", GetSize(bits), RTLIL::Const(bits).as_string().c_str());
480  break;
481 
482  case AST_REALVALUE:
483  fprintf(f, "%e", realvalue);
484  break;
485 
486  case AST_BLOCK:
487  if (children.size() == 1) {
488  children[0]->dumpVlog(f, indent);
489  } else {
490  fprintf(f, "%s" "begin\n", indent.c_str());
491  for (auto child : children)
492  child->dumpVlog(f, indent + " ");
493  fprintf(f, "%s" "end\n", indent.c_str());
494  }
495  break;
496 
497  case AST_CASE:
498  fprintf(f, "%s" "case (", indent.c_str());
499  children[0]->dumpVlog(f, "");
500  fprintf(f, ")\n");
501  for (size_t i = 1; i < children.size(); i++) {
502  AstNode *child = children[i];
503  child->dumpVlog(f, indent + " ");
504  }
505  fprintf(f, "%s" "endcase\n", indent.c_str());
506  break;
507 
508  case AST_COND:
509  for (auto child : children) {
510  if (child->type == AST_BLOCK) {
511  fprintf(f, ":\n");
512  child->dumpVlog(f, indent + " ");
513  first = true;
514  } else {
515  fprintf(f, "%s", first ? indent.c_str() : ", ");
516  if (child->type == AST_DEFAULT)
517  fprintf(f, "default");
518  else
519  child->dumpVlog(f, "");
520  first = false;
521  }
522  }
523  break;
524 
525  case AST_ASSIGN_EQ:
526  case AST_ASSIGN_LE:
527  fprintf(f, "%s", indent.c_str());
528  children[0]->dumpVlog(f, "");
529  fprintf(f, " %s ", type == AST_ASSIGN_EQ ? "=" : "<=");
530  children[1]->dumpVlog(f, "");
531  fprintf(f, ";\n");
532  break;
533 
534  case AST_CONCAT:
535  fprintf(f, "{");
536  for (auto child : children) {
537  if (!first)
538  fprintf(f, ", ");
539  child->dumpVlog(f, "");
540  first = false;
541  }
542  fprintf(f, "}");
543  break;
544 
545  case AST_REPLICATE:
546  fprintf(f, "{");
547  children[0]->dumpVlog(f, "");
548  fprintf(f, "{");
549  children[1]->dumpVlog(f, "");
550  fprintf(f, "}}");
551  break;
552 
553  if (0) { case AST_BIT_NOT: txt = "~"; }
554  if (0) { case AST_REDUCE_AND: txt = "&"; }
555  if (0) { case AST_REDUCE_OR: txt = "|"; }
556  if (0) { case AST_REDUCE_XOR: txt = "^"; }
557  if (0) { case AST_REDUCE_XNOR: txt = "~^"; }
558  if (0) { case AST_REDUCE_BOOL: txt = "|"; }
559  if (0) { case AST_POS: txt = "+"; }
560  if (0) { case AST_NEG: txt = "-"; }
561  if (0) { case AST_LOGIC_NOT: txt = "!"; }
562  fprintf(f, "%s(", txt.c_str());
563  children[0]->dumpVlog(f, "");
564  fprintf(f, ")");
565  break;
566 
567  if (0) { case AST_BIT_AND: txt = "&"; }
568  if (0) { case AST_BIT_OR: txt = "|"; }
569  if (0) { case AST_BIT_XOR: txt = "^"; }
570  if (0) { case AST_BIT_XNOR: txt = "~^"; }
571  if (0) { case AST_SHIFT_LEFT: txt = "<<"; }
572  if (0) { case AST_SHIFT_RIGHT: txt = ">>"; }
573  if (0) { case AST_SHIFT_SLEFT: txt = "<<<"; }
574  if (0) { case AST_SHIFT_SRIGHT: txt = ">>>"; }
575  if (0) { case AST_LT: txt = "<"; }
576  if (0) { case AST_LE: txt = "<="; }
577  if (0) { case AST_EQ: txt = "=="; }
578  if (0) { case AST_NE: txt = "!="; }
579  if (0) { case AST_EQX: txt = "==="; }
580  if (0) { case AST_NEX: txt = "!=="; }
581  if (0) { case AST_GE: txt = ">="; }
582  if (0) { case AST_GT: txt = ">"; }
583  if (0) { case AST_ADD: txt = "+"; }
584  if (0) { case AST_SUB: txt = "-"; }
585  if (0) { case AST_MUL: txt = "*"; }
586  if (0) { case AST_DIV: txt = "/"; }
587  if (0) { case AST_MOD: txt = "%"; }
588  if (0) { case AST_POW: txt = "**"; }
589  if (0) { case AST_LOGIC_AND: txt = "&&"; }
590  if (0) { case AST_LOGIC_OR: txt = "||"; }
591  fprintf(f, "(");
592  children[0]->dumpVlog(f, "");
593  fprintf(f, ")%s(", txt.c_str());
594  children[1]->dumpVlog(f, "");
595  fprintf(f, ")");
596  break;
597 
598  case AST_TERNARY:
599  fprintf(f, "(");
600  children[0]->dumpVlog(f, "");
601  fprintf(f, ") ? (");
602  children[1]->dumpVlog(f, "");
603  fprintf(f, ") : (");
604  children[2]->dumpVlog(f, "");
605  fprintf(f, ")");
606  break;
607 
608  default:
609  std::string type_name = type2str(type);
610  fprintf(f, "%s" "/** %s **/%s", indent.c_str(), type_name.c_str(), indent.empty() ? "" : "\n");
611  // dumpAst(f, indent, NULL);
612  }
613 }
bool range_valid
Definition: ast.h:158
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
void dumpVlog(FILE *f, std::string indent)
Definition: ast.cc:327
std::string type2str(AstNodeType type)
Definition: ast.cc:66
YOSYS_NAMESPACE_BEGIN std::vector< FILE * > log_files
Definition: log.cc:37
int range_right
Definition: ast.h:159
bool is_reg
Definition: ast.h:158
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
double realvalue
Definition: ast.h:161
static std::string id2vl(std::string txt)
Definition: ast.cc:311
AstNodeType type
Definition: ast.h:146
int as_int(bool is_signed=false) const
Definition: rtlil.cc:104
int range_left
Definition: ast.h:159
#define NULL
bool is_signed
Definition: ast.h:158
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
std::vector< RTLIL::State > bits
Definition: ast.h:157
bool is_output
Definition: ast.h:158
bool is_input
Definition: ast.h:158

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

AstNode * AstNode::eval_const_function ( AstNode fcall)

Definition at line 2541 of file simplify.cc.

2542 {
2543  std::map<std::string, AstNode*> backup_scope;
2544  std::map<std::string, AstNode::varinfo_t> variables;
2545  bool delete_temp_block = false;
2546  AstNode *block = NULL;
2547 
2548  size_t argidx = 0;
2549  for (auto child : children)
2550  {
2551  if (child->type == AST_BLOCK)
2552  {
2553  log_assert(block == NULL);
2554  block = child;
2555  continue;
2556  }
2557 
2558  if (child->type == AST_WIRE)
2559  {
2560  while (child->simplify(true, false, false, 1, -1, false, true)) { }
2561  if (!child->range_valid)
2562  log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n",
2563  child->str.c_str(), child->filename.c_str(), child->linenum, fcall->filename.c_str(), fcall->linenum);
2564  variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
2565  variables[child->str].offset = std::min(child->range_left, child->range_right);
2566  variables[child->str].is_signed = child->is_signed;
2567  if (child->is_input && argidx < fcall->children.size())
2568  variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
2569  backup_scope[child->str] = current_scope[child->str];
2570  current_scope[child->str] = child;
2571  continue;
2572  }
2573 
2574  log_assert(block == NULL);
2575  delete_temp_block = true;
2576  block = new AstNode(AST_BLOCK);
2577  block->children.push_back(child->clone());
2578  }
2579 
2580  log_assert(block != NULL);
2581  log_assert(variables.count(str) != 0);
2582 
2583  while (!block->children.empty())
2584  {
2585  AstNode *stmt = block->children.front();
2586 
2587 #if 0
2588  log("-----------------------------------\n");
2589  for (auto &it : variables)
2590  log("%20s %40s\n", it.first.c_str(), log_signal(it.second.val));
2591  stmt->dumpAst(NULL, "stmt> ");
2592 #endif
2593 
2594  if (stmt->type == AST_ASSIGN_EQ)
2595  {
2596  stmt->children.at(1)->replace_variables(variables, fcall);
2597  while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
2598 
2599  if (stmt->type != AST_ASSIGN_EQ)
2600  continue;
2601 
2602  if (stmt->children.at(1)->type != AST_CONSTANT)
2603  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
2604  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2605 
2606  if (stmt->children.at(0)->type != AST_IDENTIFIER)
2607  log_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
2608  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2609 
2610  if (!variables.count(stmt->children.at(0)->str))
2611  log_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
2612  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2613 
2614  if (stmt->children.at(0)->children.empty()) {
2615  variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
2616  } else {
2617  AstNode *range = stmt->children.at(0)->children.at(0);
2618  if (!range->range_valid)
2619  log_error("Non-constant range in %s:%d (called from %s:%d).\n",
2620  range->filename.c_str(), range->linenum, fcall->filename.c_str(), fcall->linenum);
2621  int offset = std::min(range->range_left, range->range_right);
2622  int width = std::abs(range->range_left - range->range_right) + 1;
2623  varinfo_t &v = variables[stmt->children.at(0)->str];
2624  RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());
2625  for (int i = 0; i < width; i++)
2626  v.val.bits.at(i+offset-v.offset) = r.bits.at(i);
2627  }
2628 
2629  delete block->children.front();
2630  block->children.erase(block->children.begin());
2631  continue;
2632  }
2633 
2634  if (stmt->type == AST_FOR)
2635  {
2636  block->children.insert(block->children.begin(), stmt->children.at(0));
2637  stmt->children.at(3)->children.push_back(stmt->children.at(2));
2638  stmt->children.erase(stmt->children.begin() + 2);
2639  stmt->children.erase(stmt->children.begin());
2640  stmt->type = AST_WHILE;
2641  continue;
2642  }
2643 
2644  if (stmt->type == AST_WHILE)
2645  {
2646  AstNode *cond = stmt->children.at(0)->clone();
2647  cond->replace_variables(variables, fcall);
2648  while (cond->simplify(true, false, false, 1, -1, false, true)) { }
2649 
2650  if (cond->type != AST_CONSTANT)
2651  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2652  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2653 
2654  if (cond->asBool()) {
2655  block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
2656  } else {
2657  delete block->children.front();
2658  block->children.erase(block->children.begin());
2659  }
2660 
2661  delete cond;
2662  continue;
2663  }
2664 
2665  if (stmt->type == AST_REPEAT)
2666  {
2667  AstNode *num = stmt->children.at(0)->clone();
2668  num->replace_variables(variables, fcall);
2669  while (num->simplify(true, false, false, 1, -1, false, true)) { }
2670 
2671  if (num->type != AST_CONSTANT)
2672  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2673  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2674 
2675  block->children.erase(block->children.begin());
2676  for (int i = 0; i < num->bitsAsConst().as_int(); i++)
2677  block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
2678 
2679  delete stmt;
2680  delete num;
2681  continue;
2682  }
2683 
2684  if (stmt->type == AST_CASE)
2685  {
2686  AstNode *expr = stmt->children.at(0)->clone();
2687  expr->replace_variables(variables, fcall);
2688  while (expr->simplify(true, false, false, 1, -1, false, true)) { }
2689 
2690  AstNode *sel_case = NULL;
2691  for (size_t i = 1; i < stmt->children.size(); i++)
2692  {
2693  bool found_match = false;
2694  log_assert(stmt->children.at(i)->type == AST_COND);
2695 
2696  if (stmt->children.at(i)->children.front()->type == AST_DEFAULT) {
2697  sel_case = stmt->children.at(i)->children.back();
2698  continue;
2699  }
2700 
2701  for (size_t j = 0; j+1 < stmt->children.at(i)->children.size() && !found_match; j++)
2702  {
2703  AstNode *cond = stmt->children.at(i)->children.at(j)->clone();
2704  cond->replace_variables(variables, fcall);
2705 
2706  cond = new AstNode(AST_EQ, expr->clone(), cond);
2707  while (cond->simplify(true, false, false, 1, -1, false, true)) { }
2708 
2709  if (cond->type != AST_CONSTANT)
2710  log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
2711  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2712 
2713  found_match = cond->asBool();
2714  delete cond;
2715  }
2716 
2717  if (found_match) {
2718  sel_case = stmt->children.at(i)->children.back();
2719  break;
2720  }
2721  }
2722 
2723  block->children.erase(block->children.begin());
2724  if (sel_case)
2725  block->children.insert(block->children.begin(), sel_case->clone());
2726  delete stmt;
2727  delete expr;
2728  continue;
2729  }
2730 
2731  if (stmt->type == AST_BLOCK)
2732  {
2733  block->children.erase(block->children.begin());
2734  block->children.insert(block->children.begin(), stmt->children.begin(), stmt->children.end());
2735  stmt->children.clear();
2736  delete stmt;
2737  continue;
2738  }
2739 
2740  log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
2741  stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
2742  log_abort();
2743  }
2744 
2745  if (delete_temp_block)
2746  delete block;
2747 
2748  for (auto &it : backup_scope)
2749  if (it.second == NULL)
2750  current_scope.erase(it.first);
2751  else
2752  current_scope[it.first] = it.second;
2753 
2754  return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
2755 }
std::map< std::string, AstNode * > current_scope
Definition: ast.cc:58
RTLIL::Const bitsAsConst(int width, bool is_signed)
Definition: ast.cc:741
bool range_valid
Definition: ast.h:158
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
Definition: ast.cc:688
void dumpAst(FILE *f, std::string indent)
Definition: ast.cc:250
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
void log_error(const char *format,...)
Definition: log.cc:204
#define log_abort()
Definition: log.h:84
int range_right
Definition: ast.h:159
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
#define log_assert(_assert_expr_)
Definition: log.h:85
list variables
Definition: fsm/generate.py:47
AstNodeType type
Definition: ast.h:146
int as_int(bool is_signed=false) const
Definition: rtlil.cc:104
int range_left
Definition: ast.h:159
AstNode * clone()
Definition: ast.cc:208
#define NULL
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
std::string filename
Definition: ast.h:175
void log(const char *format,...)
Definition: log.cc:180
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
int linenum
Definition: ast.h:176
void replace_variables(std::map< std::string, varinfo_t > &variables, AstNode *fcall)
Definition: simplify.cc:2511
bool asBool()
Definition: ast.cc:784

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void AstNode::expand_genblock ( std::string  index_var,
std::string  prefix,
std::map< std::string, std::string > &  name_map 
)

Definition at line 2113 of file simplify.cc.

2114 {
2115  if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) {
2116  current_scope[index_var]->children[0]->cloneInto(this);
2117  return;
2118  }
2119 
2120  if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0)
2121  str = name_map[str];
2122 
2123  std::map<std::string, std::string> backup_name_map;
2124 
2125  for (size_t i = 0; i < children.size(); i++) {
2126  AstNode *child = children[i];
2127  if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
2128  child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) {
2129  if (backup_name_map.size() == 0)
2130  backup_name_map = name_map;
2131  std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
2132  size_t pos = child->str.rfind('.');
2133  if (pos == std::string::npos)
2134  pos = child->str[0] == '\\' ? 1 : 0;
2135  else
2136  pos = pos + 1;
2137  new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
2138  if (new_name[0] != '$' && new_name[0] != '\\')
2139  new_name = prefix[0] + new_name;
2140  name_map[child->str] = new_name;
2141  if (child->type == AST_FUNCTION)
2142  replace_result_wire_name_in_function(child, child->str, new_name);
2143  else
2144  child->str = new_name;
2145  current_scope[new_name] = child;
2146  }
2147  }
2148 
2149  for (size_t i = 0; i < children.size(); i++) {
2150  AstNode *child = children[i];
2151  if (child->type != AST_FUNCTION && child->type != AST_TASK && child->type != AST_PREFIX)
2152  child->expand_genblock(index_var, prefix, name_map);
2153  }
2154 
2155  if (backup_name_map.size() > 0)
2156  name_map.swap(backup_name_map);
2157 }
std::map< std::string, AstNode * > current_scope
Definition: ast.cc:58
static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
Definition: simplify.cc:2027
AstNodeType type
Definition: ast.h:146
void expand_genblock(std::string index_var, std::string prefix, std::map< std::string, std::string > &name_map)
Definition: simplify.cc:2113
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

RTLIL::SigSpec AstNode::genRTLIL ( int  width_hint = -1,
bool  sign_hint = false 
)

Definition at line 762 of file genrtlil.cc.

763 {
764  // in the following big switch() statement there are some uses of
765  // Clifford's Device (http://www.clifford.at/cfun/cliffdev/). In this
766  // cases this variable is used to hold the type of the cell that should
767  // be instanciated for this type of AST node.
768  std::string type_name;
769 
772 
773  switch (type)
774  {
775  // simply ignore this nodes.
776  // they are eighter leftovers from simplify() or are referenced by other nodes
777  // and are only accessed here thru this references
778  case AST_TASK:
779  case AST_FUNCTION:
780  case AST_DPI_FUNCTION:
781  case AST_AUTOWIRE:
782  case AST_LOCALPARAM:
783  case AST_DEFPARAM:
784  case AST_GENVAR:
785  case AST_GENFOR:
786  case AST_GENBLOCK:
787  case AST_GENIF:
788  case AST_GENCASE:
789  break;
790 
791  // remember the parameter, needed for example in techmap
792  case AST_PARAMETER:
794  break;
795 
796  // create an RTLIL::Wire for an AST_WIRE node
797  case AST_WIRE: {
798  if (current_module->wires_.count(str) != 0)
799  log_error("Re-definition of signal `%s' at %s:%d!\n",
800  str.c_str(), filename.c_str(), linenum);
801  if (!range_valid)
802  log_error("Signal `%s' with non-constant width at %s:%d!\n",
803  str.c_str(), filename.c_str(), linenum);
804 
805  log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
806 
808  wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
809  wire->start_offset = range_right;
810  wire->port_id = port_id;
811  wire->port_input = is_input;
812  wire->port_output = is_output;
813  wire->upto = range_swapped;
814 
815  for (auto &attr : attributes) {
816  if (attr.second->type != AST_CONSTANT)
817  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
818  attr.first.c_str(), filename.c_str(), linenum);
819  wire->attributes[attr.first] = attr.second->asAttrConst();
820  }
821  }
822  break;
823 
824  // create an RTLIL::Memory for an AST_MEMORY node
825  case AST_MEMORY: {
826  if (current_module->memories.count(str) != 0)
827  log_error("Re-definition of memory `%s' at %s:%d!\n",
828  str.c_str(), filename.c_str(), linenum);
829 
830  log_assert(children.size() >= 2);
833 
834  if (!children[0]->range_valid || !children[1]->range_valid)
835  log_error("Memory `%s' with non-constant width or size at %s:%d!\n",
836  str.c_str(), filename.c_str(), linenum);
837 
838  RTLIL::Memory *memory = new RTLIL::Memory;
839  memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
840  memory->name = str;
841  memory->width = children[0]->range_left - children[0]->range_right + 1;
842  memory->start_offset = children[0]->range_right;
843  memory->size = children[1]->range_left - children[1]->range_right;
844  current_module->memories[memory->name] = memory;
845 
846  if (memory->size < 0)
847  memory->size *= -1;
848  memory->size += std::min(children[1]->range_left, children[1]->range_right) + 1;
849 
850  for (auto &attr : attributes) {
851  if (attr.second->type != AST_CONSTANT)
852  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
853  attr.first.c_str(), filename.c_str(), linenum);
854  memory->attributes[attr.first] = attr.second->asAttrConst();
855  }
856  }
857  break;
858 
859  // simply return the corresponding RTLIL::SigSpec for an AST_CONSTANT node
860  case AST_CONSTANT:
861  {
862  if (width_hint < 0)
863  detectSignWidth(width_hint, sign_hint);
864 
865  is_signed = sign_hint;
866  return RTLIL::SigSpec(bitsAsConst());
867  }
868 
869  case AST_REALVALUE:
870  {
871  RTLIL::SigSpec sig = realAsConst(width_hint);
872  log_warning("converting real value %e to binary %s at %s:%d.\n",
873  realvalue, log_signal(sig), filename.c_str(), linenum);
874  return sig;
875  }
876 
877  // simply return the corresponding RTLIL::SigSpec for an AST_IDENTIFIER node
878  // for identifiers with dynamic bit ranges (e.g. "foo[bar]" or "foo[bar+3:bar]") a
879  // shifter cell is created and the output signal of this cell is returned
880  case AST_IDENTIFIER:
881  {
882  RTLIL::Wire *wire = NULL;
883  RTLIL::SigChunk chunk;
884 
885  int add_undef_bits_msb = 0;
886  int add_undef_bits_lsb = 0;
887 
888  if (id2ast && id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
890  wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
891  wire->name = str;
892  if (flag_autowire)
893  log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
894  else
895  log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum);
896  }
897  else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
898  if (id2ast->children[0]->type != AST_CONSTANT)
899  log_error("Parameter %s does not evaluate to constant value at %s:%d!\n",
900  str.c_str(), filename.c_str(), linenum);
901  chunk = RTLIL::Const(id2ast->children[0]->bits);
902  goto use_const_chunk;
903  }
904  else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
905  id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
906  log_error("Identifier `%s' doesn't map to any signal at %s:%d!\n",
907  str.c_str(), filename.c_str(), linenum);
908 
909  if (id2ast->type == AST_MEMORY)
910  log_error("Identifier `%s' does map to an unexpanded memory at %s:%d!\n",
911  str.c_str(), filename.c_str(), linenum);
912 
913  wire = current_module->wires_[str];
914  chunk.wire = wire;
915  chunk.width = wire->width;
916  chunk.offset = 0;
917 
918  use_const_chunk:
919  if (children.size() != 0) {
921  int source_width = id2ast->range_left - id2ast->range_right + 1;
922  int source_offset = id2ast->range_right;
923  if (!children[0]->range_valid) {
924  AstNode *left_at_zero_ast = children[0]->children[0]->clone();
925  AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : left_at_zero_ast->clone();
926  while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
927  while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
928  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
929  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
930  str.c_str(), filename.c_str(), linenum);
931  int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
932  AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
933  children[0]->children[1]->clone() : children[0]->children[0]->clone());
934  fake_ast->children[0]->delete_children();
935  RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL();
936  if (id2ast->range_right != 0) {
937  shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast->children[1]->is_signed);
938  fake_ast->children[1]->is_signed = true;
939  }
940  if (id2ast->range_swapped) {
941  shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed);
942  fake_ast->children[1]->is_signed = true;
943  }
944  if (GetSize(shift_val) >= 32)
945  fake_ast->children[1]->is_signed = true;
946  RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val);
947  delete left_at_zero_ast;
948  delete right_at_zero_ast;
949  delete fake_ast;
950  return sig;
951  } else {
952  chunk.width = children[0]->range_left - children[0]->range_right + 1;
953  chunk.offset = children[0]->range_right - source_offset;
954  if (id2ast->range_swapped)
955  chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width);
956  if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
957  if (chunk.width == 1)
958  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n",
959  str.c_str(), filename.c_str(), linenum);
960  else
961  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n",
962  str.c_str(), filename.c_str(), linenum, chunk.width);
963  chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
964  } else {
965  if (chunk.width + chunk.offset > source_width) {
966  add_undef_bits_msb = (chunk.width + chunk.offset) - source_width;
967  chunk.width -= add_undef_bits_msb;
968  }
969  if (chunk.offset < 0) {
970  add_undef_bits_lsb = -chunk.offset;
971  chunk.width -= add_undef_bits_lsb;
972  chunk.offset += add_undef_bits_lsb;
973  }
974  if (add_undef_bits_lsb)
975  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n",
976  str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb);
977  if (add_undef_bits_msb)
978  log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n",
979  str.c_str(), filename.c_str(), linenum, add_undef_bits_msb);
980  }
981  }
982  }
983 
984  RTLIL::SigSpec sig = { RTLIL::SigSpec(RTLIL::State::Sx, add_undef_bits_msb), chunk, RTLIL::SigSpec(RTLIL::State::Sx, add_undef_bits_lsb) };
985 
986  if (genRTLIL_subst_ptr)
988 
989  is_signed = children.size() > 0 ? false : id2ast->is_signed && sign_hint;
990  return sig;
991  }
992 
993  // just pass thru the signal. the parent will evaluate the is_signed property and interpret the SigSpec accordingly
994  case AST_TO_SIGNED:
995  case AST_TO_UNSIGNED: {
996  RTLIL::SigSpec sig = children[0]->genRTLIL();
997  if (sig.size() < width_hint)
998  sig.extend_u0(width_hint, sign_hint);
999  is_signed = sign_hint;
1000  return sig;
1001  }
1002 
1003  // concatenation of signals can be done directly using RTLIL::SigSpec
1004  case AST_CONCAT: {
1005  RTLIL::SigSpec sig;
1006  for (auto it = children.begin(); it != children.end(); it++)
1007  sig.append((*it)->genRTLIL());
1008  if (sig.size() < width_hint)
1009  sig.extend_u0(width_hint, false);
1010  return sig;
1011  }
1012 
1013  // replication of signals can be done directly using RTLIL::SigSpec
1014  case AST_REPLICATE: {
1015  RTLIL::SigSpec left = children[0]->genRTLIL();
1016  RTLIL::SigSpec right = children[1]->genRTLIL();
1017  if (!left.is_fully_const())
1018  log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
1019  int count = left.as_int();
1020  RTLIL::SigSpec sig;
1021  for (int i = 0; i < count; i++)
1022  sig.append(right);
1023  if (sig.size() < width_hint)
1024  sig.extend_u0(width_hint, false);
1025  is_signed = false;
1026  return sig;
1027  }
1028 
1029  // generate cells for unary operations: $not, $pos, $neg
1030  if (0) { case AST_BIT_NOT: type_name = "$not"; }
1031  if (0) { case AST_POS: type_name = "$pos"; }
1032  if (0) { case AST_NEG: type_name = "$neg"; }
1033  {
1034  RTLIL::SigSpec arg = children[0]->genRTLIL(width_hint, sign_hint);
1035  is_signed = children[0]->is_signed;
1036  int width = arg.size();
1037  if (width_hint > 0) {
1038  width = width_hint;
1039  widthExtend(this, arg, width, is_signed);
1040  }
1041  return uniop2rtlil(this, type_name, width, arg);
1042  }
1043 
1044  // generate cells for binary operations: $and, $or, $xor, $xnor
1045  if (0) { case AST_BIT_AND: type_name = "$and"; }
1046  if (0) { case AST_BIT_OR: type_name = "$or"; }
1047  if (0) { case AST_BIT_XOR: type_name = "$xor"; }
1048  if (0) { case AST_BIT_XNOR: type_name = "$xnor"; }
1049  {
1050  if (width_hint < 0)
1051  detectSignWidth(width_hint, sign_hint);
1052  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1053  RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1054  int width = std::max(left.size(), right.size());
1055  if (width_hint > 0)
1056  width = width_hint;
1057  is_signed = children[0]->is_signed && children[1]->is_signed;
1058  return binop2rtlil(this, type_name, width, left, right);
1059  }
1060 
1061  // generate cells for unary operations: $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor
1062  if (0) { case AST_REDUCE_AND: type_name = "$reduce_and"; }
1063  if (0) { case AST_REDUCE_OR: type_name = "$reduce_or"; }
1064  if (0) { case AST_REDUCE_XOR: type_name = "$reduce_xor"; }
1065  if (0) { case AST_REDUCE_XNOR: type_name = "$reduce_xnor"; }
1066  {
1067  RTLIL::SigSpec arg = children[0]->genRTLIL();
1068  RTLIL::SigSpec sig = uniop2rtlil(this, type_name, std::max(width_hint, 1), arg);
1069  return sig;
1070  }
1071 
1072  // generate cells for unary operations: $reduce_bool
1073  // (this is actually just an $reduce_or, but for clearity a different cell type is used)
1074  if (0) { case AST_REDUCE_BOOL: type_name = "$reduce_bool"; }
1075  {
1076  RTLIL::SigSpec arg = children[0]->genRTLIL();
1077  RTLIL::SigSpec sig = arg.size() > 1 ? uniop2rtlil(this, type_name, std::max(width_hint, 1), arg) : arg;
1078  return sig;
1079  }
1080 
1081  // generate cells for binary operations: $shl, $shr, $sshl, $sshr
1082  if (0) { case AST_SHIFT_LEFT: type_name = "$shl"; }
1083  if (0) { case AST_SHIFT_RIGHT: type_name = "$shr"; }
1084  if (0) { case AST_SHIFT_SLEFT: type_name = "$sshl"; }
1085  if (0) { case AST_SHIFT_SRIGHT: type_name = "$sshr"; }
1086  {
1087  if (width_hint < 0)
1088  detectSignWidth(width_hint, sign_hint);
1089  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1090  RTLIL::SigSpec right = children[1]->genRTLIL();
1091  int width = width_hint > 0 ? width_hint : left.size();
1092  is_signed = children[0]->is_signed;
1093  return binop2rtlil(this, type_name, width, left, right);
1094  }
1095 
1096  // generate cells for binary operations: $pow
1097  case AST_POW:
1098  {
1099  int right_width;
1100  bool right_signed;
1101  children[1]->detectSignWidth(right_width, right_signed);
1102  if (width_hint < 0)
1103  detectSignWidth(width_hint, sign_hint);
1104  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1105  RTLIL::SigSpec right = children[1]->genRTLIL(right_width, right_signed);
1106  int width = width_hint > 0 ? width_hint : left.size();
1107  is_signed = children[0]->is_signed;
1108  if (!flag_noopt && left.is_fully_const() && left.as_int() == 2 && !right_signed)
1109  return binop2rtlil(this, "$shl", width, RTLIL::SigSpec(1, left.size()), right);
1110  return binop2rtlil(this, "$pow", width, left, right);
1111  }
1112 
1113  // generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt
1114  if (0) { case AST_LT: type_name = "$lt"; }
1115  if (0) { case AST_LE: type_name = "$le"; }
1116  if (0) { case AST_EQ: type_name = "$eq"; }
1117  if (0) { case AST_NE: type_name = "$ne"; }
1118  if (0) { case AST_EQX: type_name = "$eqx"; }
1119  if (0) { case AST_NEX: type_name = "$nex"; }
1120  if (0) { case AST_GE: type_name = "$ge"; }
1121  if (0) { case AST_GT: type_name = "$gt"; }
1122  {
1123  int width = std::max(width_hint, 1);
1124  width_hint = -1, sign_hint = true;
1125  children[0]->detectSignWidthWorker(width_hint, sign_hint);
1126  children[1]->detectSignWidthWorker(width_hint, sign_hint);
1127  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1128  RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1129  RTLIL::SigSpec sig = binop2rtlil(this, type_name, width, left, right);
1130  return sig;
1131  }
1132 
1133  // generate cells for binary operations: $add, $sub, $mul, $div, $mod
1134  if (0) { case AST_ADD: type_name = "$add"; }
1135  if (0) { case AST_SUB: type_name = "$sub"; }
1136  if (0) { case AST_MUL: type_name = "$mul"; }
1137  if (0) { case AST_DIV: type_name = "$div"; }
1138  if (0) { case AST_MOD: type_name = "$mod"; }
1139  {
1140  if (width_hint < 0)
1141  detectSignWidth(width_hint, sign_hint);
1142  RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
1143  RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
1144  #if 0
1145  int width = std::max(left.size(), right.size());
1146  if (width > width_hint && width_hint > 0)
1147  width = width_hint;
1148  if (width < width_hint) {
1149  if (type == AST_ADD || type == AST_SUB || type == AST_DIV)
1150  width++;
1151  if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed))
1152  width = width_hint;
1153  if (type == AST_MUL)
1154  width = std::min(left.size() + right.size(), width_hint);
1155  }
1156  #else
1157  int width = std::max(std::max(left.size(), right.size()), width_hint);
1158  #endif
1159  is_signed = children[0]->is_signed && children[1]->is_signed;
1160  return binop2rtlil(this, type_name, width, left, right);
1161  }
1162 
1163  // generate cells for binary operations: $logic_and, $logic_or
1164  if (0) { case AST_LOGIC_AND: type_name = "$logic_and"; }
1165  if (0) { case AST_LOGIC_OR: type_name = "$logic_or"; }
1166  {
1167  RTLIL::SigSpec left = children[0]->genRTLIL();
1168  RTLIL::SigSpec right = children[1]->genRTLIL();
1169  return binop2rtlil(this, type_name, std::max(width_hint, 1), left, right);
1170  }
1171 
1172  // generate cells for unary operations: $logic_not
1173  case AST_LOGIC_NOT:
1174  {
1175  RTLIL::SigSpec arg = children[0]->genRTLIL();
1176  return uniop2rtlil(this, "$logic_not", std::max(width_hint, 1), arg);
1177  }
1178 
1179  // generate multiplexer for ternary operator (aka ?:-operator)
1180  case AST_TERNARY:
1181  {
1182  if (width_hint < 0)
1183  detectSignWidth(width_hint, sign_hint);
1184 
1185  RTLIL::SigSpec cond = children[0]->genRTLIL();
1186  RTLIL::SigSpec val1 = children[1]->genRTLIL(width_hint, sign_hint);
1187  RTLIL::SigSpec val2 = children[2]->genRTLIL(width_hint, sign_hint);
1188 
1189  if (cond.size() > 1)
1190  cond = uniop2rtlil(this, "$reduce_bool", 1, cond, false);
1191 
1192  int width = std::max(val1.size(), val2.size());
1193  is_signed = children[1]->is_signed && children[2]->is_signed;
1194  widthExtend(this, val1, width, is_signed);
1195  widthExtend(this, val2, width, is_signed);
1196 
1197  RTLIL::SigSpec sig = mux2rtlil(this, cond, val1, val2);
1198 
1199  if (sig.size() < width_hint)
1200  sig.extend_u0(width_hint, sign_hint);
1201  return sig;
1202  }
1203 
1204  // generate $memrd cells for memory read ports
1205  case AST_MEMRD:
1206  {
1207  std::stringstream sstr;
1208  sstr << "$memrd$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1209 
1210  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$memrd");
1211  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1212 
1213  RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width);
1214  wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1215 
1216  int addr_bits = 1;
1217  while ((1 << addr_bits) < current_module->memories[str]->size)
1218  addr_bits++;
1219 
1220  cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
1221  cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
1222  cell->setPort("\\DATA", RTLIL::SigSpec(wire));
1223 
1224  cell->parameters["\\MEMID"] = RTLIL::Const(str);
1225  cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits);
1226  cell->parameters["\\WIDTH"] = RTLIL::Const(wire->width);
1227 
1228  cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
1229  cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
1230  cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
1231 
1232  return RTLIL::SigSpec(wire);
1233  }
1234 
1235  // generate $memwr cells for memory write ports
1236  case AST_MEMWR:
1237  {
1238  std::stringstream sstr;
1239  sstr << "$memwr$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1240 
1241  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$memwr");
1242  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1243 
1244  int addr_bits = 1;
1245  while ((1 << addr_bits) < current_module->memories[str]->size)
1246  addr_bits++;
1247 
1248  cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
1249  cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
1250  cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width));
1251  cell->setPort("\\EN", children[2]->genRTLIL());
1252 
1253  cell->parameters["\\MEMID"] = RTLIL::Const(str);
1254  cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits);
1255  cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width);
1256 
1257  cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
1258  cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
1259 
1260  cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1);
1261  }
1262  break;
1263 
1264  // generate $assert cells
1265  case AST_ASSERT:
1266  {
1267  log_assert(children.size() == 2);
1268 
1269  RTLIL::SigSpec check = children[0]->genRTLIL();
1270  log_assert(check.size() == 1);
1271 
1272  RTLIL::SigSpec en = children[1]->genRTLIL();
1273  log_assert(en.size() == 1);
1274 
1275  std::stringstream sstr;
1276  sstr << "$assert$" << filename << ":" << linenum << "$" << (autoidx++);
1277 
1278  RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$assert");
1279  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1280 
1281  for (auto &attr : attributes) {
1282  if (attr.second->type != AST_CONSTANT)
1283  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
1284  attr.first.c_str(), filename.c_str(), linenum);
1285  cell->attributes[attr.first] = attr.second->asAttrConst();
1286  }
1287 
1288  cell->setPort("\\A", check);
1289  cell->setPort("\\EN", en);
1290  }
1291  break;
1292 
1293  // add entries to current_module->connections for assignments (outside of always blocks)
1294  case AST_ASSIGN:
1295  {
1296  if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_AUTOWIRE) {
1297  RTLIL::SigSpec right = children[1]->genRTLIL();
1298  RTLIL::SigSpec left = children[0]->genWidthRTLIL(right.size());
1299  current_module->connect(RTLIL::SigSig(left, right));
1300  } else {
1301  RTLIL::SigSpec left = children[0]->genRTLIL();
1302  RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size());
1303  current_module->connect(RTLIL::SigSig(left, right));
1304  }
1305  }
1306  break;
1307 
1308  // create an RTLIL::Cell for an AST_CELL
1309  case AST_CELL:
1310  {
1311  int port_counter = 0, para_counter = 0;
1312 
1313  if (current_module->count_id(str) != 0)
1314  log_error("Re-definition of cell `%s' at %s:%d!\n",
1315  str.c_str(), filename.c_str(), linenum);
1316 
1317  RTLIL::Cell *cell = current_module->addCell(str, "");
1318  cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
1319 
1320  for (auto it = children.begin(); it != children.end(); it++) {
1321  AstNode *child = *it;
1322  if (child->type == AST_CELLTYPE) {
1323  cell->type = child->str;
1324  if (flag_icells && cell->type.substr(0, 2) == "\\$")
1325  cell->type = cell->type.substr(1);
1326  continue;
1327  }
1328  if (child->type == AST_PARASET) {
1329  if (child->children[0]->type != AST_CONSTANT)
1330  log_error("Parameter `%s' with non-constant value at %s:%d!\n",
1331  child->str.c_str(), filename.c_str(), linenum);
1332  if (child->str.size() == 0) {
1333  char buf[100];
1334  snprintf(buf, 100, "$%d", ++para_counter);
1335  cell->parameters[buf] = child->children[0]->asParaConst();
1336  } else {
1337  cell->parameters[child->str] = child->children[0]->asParaConst();
1338  }
1339  continue;
1340  }
1341  if (child->type == AST_ARGUMENT) {
1342  RTLIL::SigSpec sig;
1343  if (child->children.size() > 0)
1344  sig = child->children[0]->genRTLIL();
1345  if (child->str.size() == 0) {
1346  char buf[100];
1347  snprintf(buf, 100, "$%d", ++port_counter);
1348  cell->setPort(buf, sig);
1349  } else {
1350  cell->setPort(child->str, sig);
1351  }
1352  continue;
1353  }
1354  log_abort();
1355  }
1356  for (auto &attr : attributes) {
1357  if (attr.second->type != AST_CONSTANT)
1358  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
1359  attr.first.c_str(), filename.c_str(), linenum);
1360  cell->attributes[attr.first] = attr.second->asAttrConst();
1361  }
1362  }
1363  break;
1364 
1365  // use ProcessGenerator for always blocks
1366  case AST_ALWAYS: {
1367  AstNode *always = this->clone();
1368  ProcessGenerator generator(always);
1369  ignoreThisSignalsInInitial.append(generator.outputSignals);
1370  delete always;
1371  } break;
1372 
1373  case AST_INITIAL: {
1374  AstNode *always = this->clone();
1375  ProcessGenerator generator(always, ignoreThisSignalsInInitial);
1376  delete always;
1377  } break;
1378 
1379  // everything should have been handled above -> print error if not.
1380  default:
1381  for (auto f : log_files)
1382  current_ast->dumpAst(f, "verilog-ast> ");
1383  type_name = type2str(type);
1384  log_error("Don't know how to generate RTLIL code for %s node at %s:%d!\n",
1385  type_name.c_str(), filename.c_str(), linenum);
1386  }
1387 
1388  return RTLIL::SigSpec();
1389 }
RTLIL::Const bitsAsConst(int width, bool is_signed)
Definition: ast.cc:741
bool range_valid
Definition: ast.h:158
RTLIL::SigSpec genWidthRTLIL(int width, const std::map< RTLIL::SigBit, RTLIL::SigBit > *new_subst_ptr=NULL)
Definition: genrtlil.cc:1394
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
void log_warning(const char *format,...)
Definition: log.cc:196
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void dumpAst(FILE *f, std::string indent)
Definition: ast.cc:250
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
bool upto
Definition: rtlil.h:827
RTLIL::SigSpec genRTLIL(int width_hint=-1, bool sign_hint=false)
Definition: genrtlil.cc:762
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
bool port_input
Definition: rtlil.h:827
RTLIL::SigSpec Sub(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed=false)
std::map< RTLIL::IdString, RTLIL::Memory * > memories
Definition: rtlil.h:601
void(* set_line_num)(int)
Definition: ast.cc:50
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed)
Definition: genrtlil.cc:73
void log_error(const char *format,...)
Definition: log.cc:204
std::set< RTLIL::IdString > avail_parameters
Definition: rtlil.h:600
int port_id
Definition: rtlil.h:826
RTLIL::IdString type
Definition: rtlil.h:854
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
void extend_u0(int width, bool is_signed=false)
Definition: rtlil.cc:2612
AstNode * id2ast
Definition: ast.h:167
int size() const
Definition: rtlil.h:1019
#define log_abort()
Definition: log.h:84
AstNode * current_ast
Definition: ast.cc:57
bool range_swapped
Definition: ast.h:158
std::string type2str(AstNodeType type)
Definition: ast.cc:66
static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
Definition: genrtlil.cc:107
static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
Definition: genrtlil.cc:140
bool port_output
Definition: rtlil.h:827
RTLIL::Wire * wire
Definition: rtlil.h:885
RTLIL::SigSpec ignoreThisSignalsInInitial
Definition: ast.cc:60
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
YOSYS_NAMESPACE_BEGIN std::vector< FILE * > log_files
Definition: log.cc:37
static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes=true)
Definition: genrtlil.cc:44
int range_right
Definition: ast.h:159
bool flag_autowire
Definition: ast.cc:56
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
const BigUnsigned & check(const BigUnsigned &x)
Definition: testsuite.cc:25
#define log_assert(_assert_expr_)
Definition: log.h:85
double realvalue
Definition: ast.h:161
bool is_fully_const() const
Definition: rtlil.cc:2763
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
#define NEW_ID
Definition: yosys.h:166
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real=NULL)
Definition: genrtlil.cc:746
bool flag_noopt
Definition: ast.cc:56
AstNodeType type
Definition: ast.h:146
RTLIL::IdString name
Definition: rtlil.h:825
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
std::string substr(size_t pos=0, size_t len=std::string::npos) const
Definition: rtlil.h:208
virtual size_t count_id(RTLIL::IdString id)
Definition: rtlil.cc:472
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
Definition: rtlil.cc:2297
std::string current_filename
Definition: ast.cc:49
AstNode * clone()
Definition: ast.cc:208
#define NULL
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
int as_int(bool is_signed=false) const
Definition: rtlil.cc:2829
std::string filename
Definition: ast.h:175
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
bool is_signed
Definition: ast.h:158
std::string str
Definition: ast.h:156
int start_offset
Definition: rtlil.h:826
std::vector< AstNode * > children
Definition: ast.h:149
int linenum
Definition: ast.h:176
const std::map< RTLIL::SigBit, RTLIL::SigBit > * genRTLIL_subst_ptr
Definition: ast.cc:59
AstModule * current_module
Definition: ast.cc:62
bool flag_icells
Definition: ast.cc:56
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71
RTLIL::Const realAsConst(int width)
Definition: ast.cc:850
bool is_output
Definition: ast.h:158
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51
int port_id
Definition: ast.h:159
bool is_input
Definition: ast.h:158

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

RTLIL::SigSpec AstNode::genWidthRTLIL ( int  width,
const std::map< RTLIL::SigBit, RTLIL::SigBit > *  new_subst_ptr = NULL 
)

Definition at line 1394 of file genrtlil.cc.

1395 {
1396  const std::map<RTLIL::SigBit, RTLIL::SigBit> *backup_subst_ptr = genRTLIL_subst_ptr;
1397 
1398  if (new_subst_ptr)
1399  genRTLIL_subst_ptr = new_subst_ptr;
1400 
1401  bool sign_hint = true;
1402  int width_hint = width;
1403  detectSignWidthWorker(width_hint, sign_hint);
1404  RTLIL::SigSpec sig = genRTLIL(width_hint, sign_hint);
1405 
1406  genRTLIL_subst_ptr = backup_subst_ptr;
1407 
1408  if (width >= 0)
1409  sig.extend_u0(width, is_signed);
1410 
1411  return sig;
1412 }
RTLIL::SigSpec genRTLIL(int width_hint=-1, bool sign_hint=false)
Definition: genrtlil.cc:762
void extend_u0(int width, bool is_signed=false)
Definition: rtlil.cc:2612
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real=NULL)
Definition: genrtlil.cc:534
bool is_signed
Definition: ast.h:158
const std::map< RTLIL::SigBit, RTLIL::SigBit > * genRTLIL_subst_ptr
Definition: ast.cc:59

+ Here is the call graph for this function:

bool AstNode::get_bool_attribute ( RTLIL::IdString  id)

Definition at line 166 of file ast.cc.

167 {
168  if (attributes.count(id) == 0)
169  return false;
170 
171  AstNode *attr = attributes.at(id);
172  if (attr->type != AST_CONSTANT)
173  log_error("Attribute `%s' with non-constant value at %s:%d!\n",
174  id.c_str(), attr->filename.c_str(), attr->linenum);
175 
176  return attr->integer != 0;
177 }
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
void log_error(const char *format,...)
Definition: log.cc:204
AstNodeType type
Definition: ast.h:146
uint32_t integer
Definition: ast.h:160
std::string filename
Definition: ast.h:175
int linenum
Definition: ast.h:176

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool AstNode::has_const_only_constructs ( bool &  recommend_const_eval)

Definition at line 2495 of file simplify.cc.

2496 {
2497  if (type == AST_FOR)
2498  recommend_const_eval = true;
2499  if (type == AST_WHILE || type == AST_REPEAT)
2500  return true;
2501  if (type == AST_FCALL && current_scope.count(str))
2502  if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
2503  return true;
2504  for (auto child : children)
2505  if (child->AstNode::has_const_only_constructs(recommend_const_eval))
2506  return true;
2507  return false;
2508 }
std::map< std::string, AstNode * > current_scope
Definition: ast.cc:58
AstNodeType type
Definition: ast.h:146
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
bool has_const_only_constructs(bool &recommend_const_eval)
Definition: simplify.cc:2495
int AstNode::isConst ( )

Definition at line 793 of file ast.cc.

794 {
795  if (type == AST_CONSTANT)
796  return 1;
797  if (type == AST_REALVALUE)
798  return 2;
799  return 0;
800 }
AstNodeType type
Definition: ast.h:146

+ Here is the caller graph for this function:

void AstNode::mem2reg_as_needed_pass1 ( std::map< AstNode *, std::set< std::string >> &  mem2reg_places,
std::map< AstNode *, uint32_t > &  mem2reg_flags,
std::map< AstNode *, uint32_t > &  proc_flags,
uint32_t &  status_flags 
)

Definition at line 2202 of file simplify.cc.

2204 {
2205  uint32_t children_flags = 0;
2206  int ignore_children_counter = 0;
2207 
2208  if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
2209  {
2210  // mark all memories that are used in a complex expression on the left side of an assignment
2211  for (auto &lhs_child : children[0]->children)
2212  mark_memories_assign_lhs_complex(mem2reg_places, mem2reg_candidates, lhs_child);
2213 
2214  if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY)
2215  {
2216  AstNode *mem = children[0]->id2ast;
2217 
2218  // activate mem2reg if this is assigned in an async proc
2219  if (flags & AstNode::MEM2REG_FL_ASYNC) {
2220  if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
2221  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2222  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
2223  }
2224 
2225  // remember if this is assigned blocking (=)
2226  if (type == AST_ASSIGN_EQ) {
2227  if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
2228  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2229  proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
2230  }
2231 
2232  // remember where this is
2233  if (flags & MEM2REG_FL_INIT) {
2234  if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
2235  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2236  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
2237  } else {
2238  if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
2239  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2240  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
2241  }
2242  }
2243 
2244  ignore_children_counter = 1;
2245  }
2246 
2247  if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY)
2248  {
2249  AstNode *mem = id2ast;
2250 
2251  // flag if used after blocking assignment (in same proc)
2252  if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
2253  mem2reg_places[mem].insert(stringf("%s:%d", filename.c_str(), linenum));
2254  mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
2255  }
2256  }
2257 
2258  // also activate if requested, either by using mem2reg attribute or by declaring array as 'wire' instead of 'reg'
2259  if (type == AST_MEMORY && (get_bool_attribute("\\mem2reg") || (flags & AstNode::MEM2REG_FL_ALL) || !is_reg))
2260  mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED;
2261 
2262  if (type == AST_MODULE && get_bool_attribute("\\mem2reg"))
2263  children_flags |= AstNode::MEM2REG_FL_ALL;
2264 
2265  std::map<AstNode*, uint32_t> *proc_flags_p = NULL;
2266 
2267  if (type == AST_ALWAYS) {
2268  int count_edge_events = 0;
2269  for (auto child : children)
2270  if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE)
2271  count_edge_events++;
2272  if (count_edge_events != 1)
2273  children_flags |= AstNode::MEM2REG_FL_ASYNC;
2274  proc_flags_p = new std::map<AstNode*, uint32_t>;
2275  }
2276 
2277  if (type == AST_INITIAL) {
2278  children_flags |= AstNode::MEM2REG_FL_INIT;
2279  proc_flags_p = new std::map<AstNode*, uint32_t>;
2280  }
2281 
2282  uint32_t backup_flags = flags;
2283  flags |= children_flags;
2284  log_assert((flags & ~0x000000ff) == 0);
2285 
2286  for (auto child : children)
2287  if (ignore_children_counter > 0)
2288  ignore_children_counter--;
2289  else if (proc_flags_p)
2290  child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
2291  else
2292  child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
2293 
2294  flags &= ~children_flags | backup_flags;
2295 
2296  if (proc_flags_p) {
2297  for (auto it : *proc_flags_p)
2298  log_assert((it.second & ~0xff000000) == 0);
2299  delete proc_flags_p;
2300  }
2301 }
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
AstNode * id2ast
Definition: ast.h:167
bool get_bool_attribute(RTLIL::IdString id)
Definition: ast.cc:166
static void mark_memories_assign_lhs_complex(std::map< AstNode *, std::set< std::string >> &mem2reg_places, std::map< AstNode *, uint32_t > &mem2reg_candidates, AstNode *that)
Definition: simplify.cc:2187
bool is_reg
Definition: ast.h:158
#define log_assert(_assert_expr_)
Definition: log.h:85
AstNodeType type
Definition: ast.h:146
#define NULL
std::string filename
Definition: ast.h:175
std::vector< AstNode * > children
Definition: ast.h:149
int linenum
Definition: ast.h:176

+ Here is the call graph for this function:

void AstNode::mem2reg_as_needed_pass2 ( std::set< AstNode * > &  mem2reg_set,
AstNode mod,
AstNode block 
)

Definition at line 2315 of file simplify.cc.

2316 {
2317  if (type == AST_BLOCK)
2318  block = this;
2319 
2320  if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && block != NULL &&
2321  children[0]->mem2reg_check(mem2reg_set) && children[0]->children[0]->children[0]->type != AST_CONSTANT)
2322  {
2323  std::stringstream sstr;
2324  sstr << "$mem2reg_wr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
2325  std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
2326 
2327  int mem_width, mem_size, addr_bits;
2328  children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
2329 
2330  AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
2331  wire_addr->str = id_addr;
2332  wire_addr->is_reg = true;
2333  wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2334  mod->children.push_back(wire_addr);
2335  while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
2336 
2337  AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
2338  wire_data->str = id_data;
2339  wire_data->is_reg = true;
2340  wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2341  mod->children.push_back(wire_data);
2342  while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
2343 
2344  log_assert(block != NULL);
2345  size_t assign_idx = 0;
2346  while (assign_idx < block->children.size() && block->children[assign_idx] != this)
2347  assign_idx++;
2348  log_assert(assign_idx < block->children.size());
2349 
2350  AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
2351  assign_addr->children[0]->str = id_addr;
2352  block->children.insert(block->children.begin()+assign_idx+1, assign_addr);
2353 
2354  AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
2355  case_node->children[0]->str = id_addr;
2356  for (int i = 0; i < mem_size; i++) {
2357  if (children[0]->children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->children[0]->integer) != i)
2358  continue;
2359  AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
2360  AstNode *assign_reg = new AstNode(type, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
2361  if (children[0]->children.size() == 2)
2362  assign_reg->children[0]->children.push_back(children[0]->children[1]->clone());
2363  assign_reg->children[0]->str = stringf("%s[%d]", children[0]->str.c_str(), i);
2364  assign_reg->children[1]->str = id_data;
2365  cond_node->children[1]->children.push_back(assign_reg);
2366  case_node->children.push_back(cond_node);
2367  }
2368  block->children.insert(block->children.begin()+assign_idx+2, case_node);
2369 
2370  children[0]->delete_children();
2371  children[0]->range_valid = false;
2372  children[0]->id2ast = NULL;
2373  children[0]->str = id_data;
2374  type = AST_ASSIGN_EQ;
2375  }
2376 
2377  if (mem2reg_check(mem2reg_set))
2378  {
2379  AstNode *bit_part_sel = NULL;
2380  if (children.size() == 2)
2381  bit_part_sel = children[1]->clone();
2382 
2383  if (children[0]->children[0]->type == AST_CONSTANT)
2384  {
2385  int id = children[0]->children[0]->integer;
2386  str = stringf("%s[%d]", str.c_str(), id);
2387 
2388  delete_children();
2389  range_valid = false;
2390  id2ast = NULL;
2391  }
2392  else
2393  {
2394  std::stringstream sstr;
2395  sstr << "$mem2reg_rd$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
2396  std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
2397 
2398  int mem_width, mem_size, addr_bits;
2399  id2ast->meminfo(mem_width, mem_size, addr_bits);
2400 
2401  AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
2402  wire_addr->str = id_addr;
2403  wire_addr->is_reg = true;
2404  if (block)
2405  wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2406  mod->children.push_back(wire_addr);
2407  while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
2408 
2409  AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
2410  wire_data->str = id_data;
2411  wire_data->is_reg = true;
2412  if (block)
2413  wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
2414  mod->children.push_back(wire_data);
2415  while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
2416 
2417  AstNode *assign_addr = new AstNode(block ? AST_ASSIGN_EQ : AST_ASSIGN, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone());
2418  assign_addr->children[0]->str = id_addr;
2419 
2420  AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER));
2421  case_node->children[0]->str = id_addr;
2422 
2423  for (int i = 0; i < mem_size; i++) {
2424  if (children[0]->children[0]->type == AST_CONSTANT && int(children[0]->children[0]->integer) != i)
2425  continue;
2426  AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK));
2427  AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER));
2428  assign_reg->children[0]->str = id_data;
2429  assign_reg->children[1]->str = stringf("%s[%d]", str.c_str(), i);
2430  cond_node->children[1]->children.push_back(assign_reg);
2431  case_node->children.push_back(cond_node);
2432  }
2433 
2434  std::vector<RTLIL::State> x_bits;
2435  for (int i = 0; i < mem_width; i++)
2436  x_bits.push_back(RTLIL::State::Sx);
2437 
2438  AstNode *cond_node = new AstNode(AST_COND, new AstNode(AST_DEFAULT), new AstNode(AST_BLOCK));
2439  AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false));
2440  assign_reg->children[0]->str = id_data;
2441  cond_node->children[1]->children.push_back(assign_reg);
2442  case_node->children.push_back(cond_node);
2443 
2444  if (block)
2445  {
2446  size_t assign_idx = 0;
2447  while (assign_idx < block->children.size() && !block->children[assign_idx]->contains(this))
2448  assign_idx++;
2449  log_assert(assign_idx < block->children.size());
2450  block->children.insert(block->children.begin()+assign_idx, case_node);
2451  block->children.insert(block->children.begin()+assign_idx, assign_addr);
2452  }
2453  else
2454  {
2455  AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
2456  proc->children[0]->children.push_back(case_node);
2457  mod->children.push_back(proc);
2458  mod->children.push_back(assign_addr);
2459  }
2460 
2461  delete_children();
2462  range_valid = false;
2463  id2ast = NULL;
2464  str = id_data;
2465  }
2466 
2467  if (bit_part_sel)
2468  children.push_back(bit_part_sel);
2469  }
2470 
2471  log_assert(id2ast == NULL || mem2reg_set.count(id2ast) == 0);
2472 
2473  auto children_list = children;
2474  for (size_t i = 0; i < children_list.size(); i++)
2475  children_list[i]->mem2reg_as_needed_pass2(mem2reg_set, mod, block);
2476 }
bool range_valid
Definition: ast.h:158
static AstNode * mkconst_int(uint32_t v, bool is_signed, int width=32)
Definition: ast.cc:672
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
Definition: ast.cc:688
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
AstNode * id2ast
Definition: ast.h:167
bool mem2reg_check(std::set< AstNode * > &mem2reg_set)
Definition: simplify.cc:2303
bool is_reg
Definition: ast.h:158
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
#define log_assert(_assert_expr_)
Definition: log.h:85
AstNodeType type
Definition: ast.h:146
uint32_t integer
Definition: ast.h:160
void meminfo(int &mem_width, int &mem_size, int &addr_bits)
Definition: simplify.cc:2479
AstNode * clone()
Definition: ast.cc:208
#define NULL
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
std::string filename
Definition: ast.h:175
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
std::string id(RTLIL::IdString internal_id, bool may_rename=true)
int linenum
Definition: ast.h:176
void delete_children()
Definition: ast.cc:231
void mem2reg_as_needed_pass2(std::set< AstNode * > &mem2reg_set, AstNode *mod, AstNode *block)
Definition: simplify.cc:2315
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51

+ Here is the call graph for this function:

bool AstNode::mem2reg_check ( std::set< AstNode * > &  mem2reg_set)

Definition at line 2303 of file simplify.cc.

2304 {
2305  if (type != AST_IDENTIFIER || !id2ast || !mem2reg_set.count(id2ast))
2306  return false;
2307 
2308  if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1)
2309  log_error("Invalid array access at %s:%d.\n", filename.c_str(), linenum);
2310 
2311  return true;
2312 }
void log_error(const char *format,...)
Definition: log.cc:204
AstNode * id2ast
Definition: ast.h:167
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
AstNodeType type
Definition: ast.h:146
std::string filename
Definition: ast.h:175
std::vector< AstNode * > children
Definition: ast.h:149
int linenum
Definition: ast.h:176

+ Here is the call graph for this function:

void AstNode::meminfo ( int &  mem_width,
int &  mem_size,
int &  addr_bits 
)

Definition at line 2479 of file simplify.cc.

2480 {
2482 
2483  mem_width = children[0]->range_left - children[0]->range_right + 1;
2484  mem_size = children[1]->range_left - children[1]->range_right;
2485 
2486  if (mem_size < 0)
2487  mem_size *= -1;
2488  mem_size += std::min(children[1]->range_left, children[1]->range_right) + 1;
2489 
2490  addr_bits = 1;
2491  while ((1 << addr_bits) < mem_size)
2492  addr_bits++;
2493 }
int range_right
Definition: ast.h:159
#define log_assert(_assert_expr_)
Definition: log.h:85
AstNodeType type
Definition: ast.h:146
int range_left
Definition: ast.h:159
std::vector< AstNode * > children
Definition: ast.h:149
AstNode * AstNode::mkconst_bits ( const std::vector< RTLIL::State > &  v,
bool  is_signed 
)
static

Definition at line 688 of file ast.cc.

689 {
690  AstNode *node = new AstNode(AST_CONSTANT);
691  node->is_signed = is_signed;
692  node->bits = v;
693  for (size_t i = 0; i < 32; i++) {
694  if (i < node->bits.size())
695  node->integer |= (node->bits[i] == RTLIL::S1) << i;
696  else if (is_signed)
697  node->integer |= (node->bits.back() == RTLIL::S1) << i;
698  }
699  node->range_valid = true;
700  node->range_left = node->bits.size()-1;
701  node->range_right = 0;
702  return node;
703 }
bool range_valid
Definition: ast.h:158
int range_right
Definition: ast.h:159
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
bool is_signed
Definition: ast.h:158
std::vector< RTLIL::State > bits
Definition: ast.h:157

+ Here is the caller graph for this function:

AstNode * AstNode::mkconst_int ( uint32_t  v,
bool  is_signed,
int  width = 32 
)
static

Definition at line 672 of file ast.cc.

673 {
674  AstNode *node = new AstNode(AST_CONSTANT);
675  node->integer = v;
676  node->is_signed = is_signed;
677  for (int i = 0; i < width; i++) {
678  node->bits.push_back((v & 1) ? RTLIL::S1 : RTLIL::S0);
679  v = v >> 1;
680  }
681  node->range_valid = true;
682  node->range_left = width-1;
683  node->range_right = 0;
684  return node;
685 }
bool range_valid
Definition: ast.h:158
int range_right
Definition: ast.h:159
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
bool is_signed
Definition: ast.h:158
std::vector< RTLIL::State > bits
Definition: ast.h:157

+ Here is the caller graph for this function:

AstNode * AstNode::mkconst_str ( const std::vector< RTLIL::State > &  v)
static

Definition at line 706 of file ast.cc.

707 {
708  AstNode *node = mkconst_str(RTLIL::Const(v).decode_string());
709  while (GetSize(node->bits) < GetSize(v))
710  node->bits.push_back(RTLIL::State::S0);
711  log_assert(node->bits == v);
712  return node;
713 }
static AstNode * mkconst_str(const std::vector< RTLIL::State > &v)
Definition: ast.cc:706
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
#define log_assert(_assert_expr_)
Definition: log.h:85
std::vector< RTLIL::State > bits
Definition: ast.h:157

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

AstNode * AstNode::mkconst_str ( const std::string &  str)
static

Definition at line 716 of file ast.cc.

717 {
718  std::vector<RTLIL::State> data;
719  data.reserve(str.size() * 8);
720  for (size_t i = 0; i < str.size(); i++) {
721  unsigned char ch = str[str.size() - i - 1];
722  for (int j = 0; j < 8; j++) {
723  data.push_back((ch & 1) ? RTLIL::S1 : RTLIL::S0);
724  ch = ch >> 1;
725  }
726  }
727  AstNode *node = AstNode::mkconst_bits(data, false);
728  node->is_string = true;
729  node->str = str;
730  return node;
731 }
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
Definition: ast.cc:688
std::string str
Definition: ast.h:156
bool is_string
Definition: ast.h:158

+ Here is the call graph for this function:

bool AstNode::operator!= ( const AstNode other) const

Definition at line 655 of file ast.cc.

656 {
657  return !(*this == other);
658 }
bool AstNode::operator== ( const AstNode other) const

Definition at line 616 of file ast.cc.

617 {
618  if (type != other.type)
619  return false;
620  if (children.size() != other.children.size())
621  return false;
622  if (str != other.str)
623  return false;
624  if (bits != other.bits)
625  return false;
626  if (is_input != other.is_input)
627  return false;
628  if (is_output != other.is_output)
629  return false;
630  if (is_reg != other.is_reg)
631  return false;
632  if (is_signed != other.is_signed)
633  return false;
634  if (is_string != other.is_string)
635  return false;
636  if (range_valid != other.range_valid)
637  return false;
638  if (range_swapped != other.range_swapped)
639  return false;
640  if (port_id != other.port_id)
641  return false;
642  if (range_left != other.range_left)
643  return false;
644  if (range_right != other.range_right)
645  return false;
646  if (integer != other.integer)
647  return false;
648  for (size_t i = 0; i < children.size(); i++)
649  if (*children[i] != *other.children[i])
650  return false;
651  return true;
652 }
bool range_valid
Definition: ast.h:158
bool range_swapped
Definition: ast.h:158
int range_right
Definition: ast.h:159
bool is_reg
Definition: ast.h:158
AstNodeType type
Definition: ast.h:146
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
bool is_signed
Definition: ast.h:158
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
std::vector< RTLIL::State > bits
Definition: ast.h:157
bool is_string
Definition: ast.h:158
bool is_output
Definition: ast.h:158
int port_id
Definition: ast.h:159
bool is_input
Definition: ast.h:158
AstNode * AstNode::readmem ( bool  is_readmemh,
std::string  mem_filename,
AstNode memory,
int  start_addr,
int  finish_addr 
)

Definition at line 2036 of file simplify.cc.

2037 {
2038  AstNode *block = new AstNode(AST_BLOCK);
2039 
2040  std::ifstream f;
2041  f.open(mem_filename.c_str());
2042 
2043  if (f.fail())
2044  log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename.c_str(), str.c_str(), filename.c_str(), linenum);
2045 
2046  log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid);
2047  int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right;
2048  int range_min = std::min(range_left, range_right), range_max = std::max(range_left, range_right);
2049 
2050  if (start_addr < 0)
2051  start_addr = range_min;
2052 
2053  if (finish_addr < 0)
2054  finish_addr = range_max;
2055 
2056  bool in_comment = false;
2057  int increment = start_addr <= finish_addr ? +1 : -1;
2058  int cursor = start_addr;
2059 
2060  while (!f.eof())
2061  {
2062  std::string line, token;
2063  std::getline(f, line);
2064 
2065  for (int i = 0; i < GetSize(line); i++) {
2066  if (in_comment && line.substr(i, 2) == "*/") {
2067  line[i] = ' ';
2068  line[i+1] = ' ';
2069  in_comment = false;
2070  continue;
2071  }
2072  if (!in_comment && line.substr(i, 2) == "/*")
2073  in_comment = true;
2074  if (in_comment)
2075  line[i] = ' ';
2076  }
2077 
2078  while (1)
2079  {
2080  token = next_token(line, " \t\r\n");
2081  if (token.empty() || token.substr(0, 2) == "//")
2082  break;
2083 
2084  if (token[0] == '@') {
2085  token = token.substr(1);
2086  const char *nptr = token.c_str();
2087  char *endptr;
2088  cursor = strtol(nptr, &endptr, 16);
2089  if (!*nptr || *endptr)
2090  log_error("Can not parse address `%s` for %s at %s:%d.\n", nptr, str.c_str(), filename.c_str(), linenum);
2091  continue;
2092  }
2093 
2094  AstNode *value = VERILOG_FRONTEND::const2ast((is_readmemh ? "'h" : "'b") + token);
2095 
2096  block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));
2097  block->children.back()->children[0]->str = memory->str;
2098  block->children.back()->children[0]->id2ast = memory;
2099 
2100  if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
2101  break;
2102  cursor += increment;
2103  }
2104 
2105  if ((cursor == finish_addr) || (increment > 0 && cursor >= range_max) || (increment < 0 && cursor <= range_min))
2106  break;
2107  }
2108 
2109  return block;
2110 }
static std::string next_token(bool pass_newline=false)
Definition: preproc.cc:96
static AstNode * mkconst_int(uint32_t v, bool is_signed, int width=32)
Definition: ast.cc:672
void log_error(const char *format,...)
Definition: log.cc:204
int range_right
Definition: ast.h:159
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
#define log_assert(_assert_expr_)
Definition: log.h:85
int range_left
Definition: ast.h:159
std::string filename
Definition: ast.h:175
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
AST::AstNode * const2ast(std::string code, char case_type=0, bool warn_z=false)
Definition: const2ast.cc:135
int linenum
Definition: ast.h:176

+ Here is the call graph for this function:

RTLIL::Const AstNode::realAsConst ( int  width)

Definition at line 850 of file ast.cc.

851 {
852  double v = round(realvalue);
853  RTLIL::Const result;
854 #ifdef EMSCRIPTEN
855  if (!isfinite(v)) {
856 #else
857  if (!std::isfinite(v)) {
858 #endif
859  result.bits = std::vector<RTLIL::State>(width, RTLIL::State::Sx);
860  } else {
861  bool is_negative = v < 0;
862  if (is_negative)
863  v *= -1;
864  for (int i = 0; i < width; i++, v /= 2)
865  result.bits.push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0);
866  if (is_negative)
867  result = const_neg(result, result, false, false, result.bits.size());
868  }
869  return result;
870 }
double realvalue
Definition: ast.h:161
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
RTLIL::Const const_neg(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:570

+ Here is the call graph for this function:

void AstNode::replace_ids ( const std::string &  prefix,
const std::map< std::string, std::string > &  rules 
)

Definition at line 2160 of file simplify.cc.

2161 {
2162  if (type == AST_BLOCK)
2163  {
2164  std::map<std::string, std::string> new_rules = rules;
2165  std::string new_prefix = prefix + str;
2166 
2167  for (auto child : children)
2168  if (child->type == AST_WIRE) {
2169  new_rules[child->str] = new_prefix + child->str;
2170  child->str = new_prefix + child->str;
2171  }
2172 
2173  for (auto child : children)
2174  if (child->type != AST_WIRE)
2175  child->replace_ids(new_prefix, new_rules);
2176  }
2177  else
2178  {
2179  if (type == AST_IDENTIFIER && rules.count(str) > 0)
2180  str = rules.at(str);
2181  for (auto child : children)
2182  child->replace_ids(prefix, rules);
2183  }
2184 }
AstNodeType type
Definition: ast.h:146
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149

+ Here is the caller graph for this function:

void AstNode::replace_variables ( std::map< std::string, varinfo_t > &  variables,
AstNode fcall 
)

Definition at line 2511 of file simplify.cc.

2512 {
2513  if (type == AST_IDENTIFIER && variables.count(str)) {
2514  int offset = variables.at(str).offset, width = variables.at(str).val.bits.size();
2515  if (!children.empty()) {
2516  if (children.size() != 1 || children.at(0)->type != AST_RANGE)
2517  log_error("Memory access in constant function is not supported in %s:%d (called from %s:%d).\n",
2518  filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum);
2519  children.at(0)->replace_variables(variables, fcall);
2520  while (simplify(true, false, false, 1, -1, false, true)) { }
2521  if (!children.at(0)->range_valid)
2522  log_error("Non-constant range in %s:%d (called from %s:%d).\n",
2523  filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum);
2524  offset = std::min(children.at(0)->range_left, children.at(0)->range_right);
2525  width = std::min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
2526  }
2527  offset -= variables.at(str).offset;
2528  std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
2529  std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
2530  AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
2531  newNode->cloneInto(this);
2532  delete newNode;
2533  return;
2534  }
2535 
2536  for (auto &child : children)
2537  child->replace_variables(variables, fcall);
2538 }
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
Definition: ast.cc:688
void log_error(const char *format,...)
Definition: log.cc:204
void cloneInto(AstNode *other)
Definition: ast.cc:220
list variables
Definition: fsm/generate.py:47
AstNodeType type
Definition: ast.h:146
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
std::string filename
Definition: ast.h:175
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
int linenum
Definition: ast.h:176

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool AstNode::simplify ( bool  const_fold,
bool  at_zero,
bool  in_lvalue,
int  stage,
int  width_hint,
bool  sign_hint,
bool  in_param 
)

Definition at line 50 of file simplify.cc.

51 {
52  AstNode *newNode = NULL;
53  bool did_something = false;
54 
55 #if 0
56  log("-------------\n");
57  log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n",
58  int(const_fold), int(at_zero), int(in_lvalue), int(stage), int(width_hint), int(sign_hint), int(in_param));
59  dumpAst(NULL, "> ");
60 #endif
61 
62  if (stage == 0)
63  {
65 
66  while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
67 
68  if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg"))
69  {
70  std::map<AstNode*, std::set<std::string>> mem2reg_places;
71  std::map<AstNode*, uint32_t> mem2reg_candidates, dummy_proc_flags;
72  uint32_t flags = flag_mem2reg ? AstNode::MEM2REG_FL_ALL : 0;
73  mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, dummy_proc_flags, flags);
74 
75  std::set<AstNode*> mem2reg_set;
76  for (auto &it : mem2reg_candidates)
77  {
78  AstNode *mem = it.first;
79  uint32_t memflags = it.second;
80  log_assert((memflags & ~0x00ffff00) == 0);
81 
82  if (mem->get_bool_attribute("\\nomem2reg"))
83  continue;
84 
85  if (memflags & AstNode::MEM2REG_FL_FORCED)
86  goto silent_activate;
87 
88  if (memflags & AstNode::MEM2REG_FL_EQ2)
89  goto verbose_activate;
90 
91  if (memflags & AstNode::MEM2REG_FL_SET_ASYNC)
92  goto verbose_activate;
93 
94  if ((memflags & AstNode::MEM2REG_FL_SET_INIT) && (memflags & AstNode::MEM2REG_FL_SET_ELSE))
95  goto verbose_activate;
96 
97  if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
98  goto verbose_activate;
99 
100  // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
101  continue;
102 
103  verbose_activate:
104  if (mem2reg_set.count(mem) == 0) {
105  log_warning("Replacing memory %s with list of registers.", mem->str.c_str());
106  bool first_element = true;
107  for (auto &place : mem2reg_places[it.first]) {
108  log("%s%s", first_element ? " See " : ", ", place.c_str());
109  first_element = false;
110  }
111  log("\n");
112  }
113 
114  silent_activate:
115  // log("Note: Replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
116  mem2reg_set.insert(mem);
117  }
118 
119  for (auto node : mem2reg_set)
120  {
121  int mem_width, mem_size, addr_bits;
122  node->meminfo(mem_width, mem_size, addr_bits);
123 
124  for (int i = 0; i < mem_size; i++) {
125  AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE,
126  mkconst_int(mem_width-1, true), mkconst_int(0, true)));
127  reg->str = stringf("%s[%d]", node->str.c_str(), i);
128  reg->is_reg = true;
129  reg->is_signed = node->is_signed;
130  children.push_back(reg);
131  while (reg->simplify(true, false, false, 1, -1, false, false)) { }
132  }
133  }
134 
135  mem2reg_as_needed_pass2(mem2reg_set, this, NULL);
136 
137  for (size_t i = 0; i < children.size(); i++) {
138  if (mem2reg_set.count(children[i]) > 0) {
139  delete children[i];
140  children.erase(children.begin() + (i--));
141  }
142  }
143  }
144 
145  while (simplify(const_fold, at_zero, in_lvalue, 2, width_hint, sign_hint, in_param)) { }
146  return false;
147  }
148 
151 
152  // we do not look inside a task or function
153  // (but as soon as a task of function is instanciated we process the generated AST as usual)
154  if (type == AST_FUNCTION || type == AST_TASK)
155  return false;
156 
157  // deactivate all calls to non-synthesis system taks
158  if ((type == AST_FCALL || type == AST_TCALL) && (str == "$display" || str == "$stop" || str == "$finish")) {
159  delete_children();
160  str = std::string();
161  }
162 
163  // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
165  const_fold = true;
166  if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))
167  const_fold = true;
168 
169  // in certain cases a function must be evaluated constant. this is what in_param controls.
171  in_param = true;
172 
173  std::map<std::string, AstNode*> backup_scope;
174 
175  // create name resolution entries for all objects with names
176  // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
177  if (type == AST_MODULE) {
178  current_scope.clear();
179  std::map<std::string, AstNode*> this_wire_scope;
180  for (size_t i = 0; i < children.size(); i++) {
181  AstNode *node = children[i];
182  if (node->type == AST_WIRE) {
183  if (this_wire_scope.count(node->str) > 0) {
184  AstNode *first_node = this_wire_scope[node->str];
185  if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0)
186  goto wires_are_compatible;
187  if (first_node->children.size() != node->children.size())
188  goto wires_are_incompatible;
189  for (size_t j = 0; j < node->children.size(); j++) {
190  AstNode *n1 = first_node->children[j], *n2 = node->children[j];
191  if (n1->type == AST_RANGE && n2->type == AST_RANGE && n1->range_valid && n2->range_valid) {
192  if (n1->range_left != n2->range_left)
193  goto wires_are_incompatible;
194  if (n1->range_right != n2->range_right)
195  goto wires_are_incompatible;
196  } else if (*n1 != *n2)
197  goto wires_are_incompatible;
198  }
199  if (first_node->range_left != node->range_left)
200  goto wires_are_incompatible;
201  if (first_node->range_right != node->range_right)
202  goto wires_are_incompatible;
203  if (first_node->port_id == 0 && (node->is_input || node->is_output))
204  goto wires_are_incompatible;
205  wires_are_compatible:
206  if (node->is_input)
207  first_node->is_input = true;
208  if (node->is_output)
209  first_node->is_output = true;
210  if (node->is_reg)
211  first_node->is_reg = true;
212  if (node->is_signed)
213  first_node->is_signed = true;
214  for (auto &it : node->attributes) {
215  if (first_node->attributes.count(it.first) > 0)
216  delete first_node->attributes[it.first];
217  first_node->attributes[it.first] = it.second->clone();
218  }
219  children.erase(children.begin()+(i--));
220  did_something = true;
221  delete node;
222  continue;
223  wires_are_incompatible:
224  if (stage > 1)
225  log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node->str.c_str(), filename.c_str(), linenum);
226  continue;
227  }
228  this_wire_scope[node->str] = node;
229  }
230  if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
231  node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) {
232  backup_scope[node->str] = current_scope[node->str];
233  current_scope[node->str] = node;
234  }
235  }
236  for (size_t i = 0; i < children.size(); i++) {
237  AstNode *node = children[i];
238  if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE)
239  while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
240  did_something = true;
241  }
242  }
243 
244  auto backup_current_block = current_block;
245  auto backup_current_block_child = current_block_child;
246  auto backup_current_top_block = current_top_block;
247 
248  int backup_width_hint = width_hint;
249  bool backup_sign_hint = sign_hint;
250 
251  bool detect_width_simple = false;
252  bool child_0_is_self_determined = false;
253  bool child_1_is_self_determined = false;
254  bool child_2_is_self_determined = false;
255  bool children_are_self_determined = false;
256  bool reset_width_after_children = false;
257 
258  switch (type)
259  {
260  case AST_ASSIGN_EQ:
261  case AST_ASSIGN_LE:
262  case AST_ASSIGN:
263  while (!children[0]->basic_prep && children[0]->simplify(false, false, true, stage, -1, false, in_param) == true)
264  did_something = true;
265  while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, in_param) == true)
266  did_something = true;
267  children[0]->detectSignWidth(backup_width_hint, backup_sign_hint);
268  children[1]->detectSignWidth(width_hint, sign_hint);
269  width_hint = std::max(width_hint, backup_width_hint);
270  child_0_is_self_determined = true;
271  break;
272 
273  case AST_PARAMETER:
274  case AST_LOCALPARAM:
275  while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
276  did_something = true;
277  children[0]->detectSignWidth(width_hint, sign_hint);
278  if (children.size() > 1 && children[1]->type == AST_RANGE) {
279  while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true)
280  did_something = true;
281  if (!children[1]->range_valid)
282  log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
283  width_hint = std::max(width_hint, children[1]->range_left - children[1]->range_right + 1);
284  }
285  break;
286 
287  case AST_TO_BITS:
288  case AST_TO_SIGNED:
289  case AST_TO_UNSIGNED:
290  case AST_CONCAT:
291  case AST_REPLICATE:
292  case AST_REDUCE_AND:
293  case AST_REDUCE_OR:
294  case AST_REDUCE_XOR:
295  case AST_REDUCE_XNOR:
296  case AST_REDUCE_BOOL:
297  detect_width_simple = true;
298  children_are_self_determined = true;
299  break;
300 
301  case AST_NEG:
302  case AST_BIT_NOT:
303  case AST_POS:
304  case AST_BIT_AND:
305  case AST_BIT_OR:
306  case AST_BIT_XOR:
307  case AST_BIT_XNOR:
308  case AST_ADD:
309  case AST_SUB:
310  case AST_MUL:
311  case AST_DIV:
312  case AST_MOD:
313  detect_width_simple = true;
314  break;
315 
316  case AST_SHIFT_LEFT:
317  case AST_SHIFT_RIGHT:
318  case AST_SHIFT_SLEFT:
319  case AST_SHIFT_SRIGHT:
320  case AST_POW:
321  detect_width_simple = true;
322  child_1_is_self_determined = true;
323  break;
324 
325  case AST_LT:
326  case AST_LE:
327  case AST_EQ:
328  case AST_NE:
329  case AST_EQX:
330  case AST_NEX:
331  case AST_GE:
332  case AST_GT:
333  width_hint = -1;
334  sign_hint = true;
335  for (auto child : children) {
336  while (!child->basic_prep && child->simplify(false, false, in_lvalue, stage, -1, false, in_param) == true)
337  did_something = true;
338  child->detectSignWidthWorker(width_hint, sign_hint);
339  }
340  reset_width_after_children = true;
341  break;
342 
343  case AST_LOGIC_AND:
344  case AST_LOGIC_OR:
345  case AST_LOGIC_NOT:
346  detect_width_simple = true;
347  children_are_self_determined = true;
348  break;
349 
350  case AST_TERNARY:
351  detect_width_simple = true;
352  child_0_is_self_determined = true;
353  break;
354 
355  case AST_MEMRD:
356  detect_width_simple = true;
357  children_are_self_determined = true;
358  break;
359 
360  default:
361  width_hint = -1;
362  sign_hint = false;
363  }
364 
365  if (detect_width_simple && width_hint < 0) {
366  if (type == AST_REPLICATE)
367  while (children[0]->simplify(true, false, in_lvalue, stage, -1, false, true) == true)
368  did_something = true;
369  for (auto child : children)
370  while (!child->basic_prep && child->simplify(false, false, in_lvalue, stage, -1, false, in_param) == true)
371  did_something = true;
372  detectSignWidth(width_hint, sign_hint);
373  }
374 
375  if (type == AST_TERNARY) {
376  int width_hint_left, width_hint_right;
377  bool sign_hint_left, sign_hint_right;
378  bool found_real_left, found_real_right;
379  children[1]->detectSignWidth(width_hint_left, sign_hint_left, &found_real_left);
380  children[2]->detectSignWidth(width_hint_right, sign_hint_right, &found_real_right);
381  if (found_real_left || found_real_right) {
382  child_1_is_self_determined = true;
383  child_2_is_self_determined = true;
384  }
385  }
386 
387  if (const_fold && type == AST_CASE)
388  {
389  while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
390  if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) {
391  std::vector<AstNode*> new_children;
392  new_children.push_back(children[0]);
393  for (int i = 1; i < GetSize(children); i++) {
394  AstNode *child = children[i];
395  log_assert(child->type == AST_COND);
396  for (auto v : child->children) {
397  if (v->type == AST_DEFAULT)
398  goto keep_const_cond;
399  if (v->type == AST_BLOCK)
400  continue;
401  while (v->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
402  if (v->type == AST_CONSTANT && v->bits_only_01()) {
403  if (v->bits == children[0]->bits) {
404  while (i+1 < GetSize(children))
405  delete children[++i];
406  goto keep_const_cond;
407  }
408  continue;
409  }
410  goto keep_const_cond;
411  }
412  if (0)
413  keep_const_cond:
414  new_children.push_back(child);
415  else
416  delete child;
417  }
418  new_children.swap(children);
419  }
420  }
421 
422  // simplify all children first
423  // (iterate by index as e.g. auto wires can add new children in the process)
424  for (size_t i = 0; i < children.size(); i++) {
425  bool did_something_here = true;
426  if ((type == AST_GENFOR || type == AST_FOR) && i >= 3)
427  break;
428  if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1)
429  break;
430  if (type == AST_GENBLOCK)
431  break;
432  if (type == AST_BLOCK && !str.empty())
433  break;
434  if (type == AST_PREFIX && i >= 1)
435  break;
436  while (did_something_here && i < children.size()) {
437  bool const_fold_here = const_fold, in_lvalue_here = in_lvalue;
438  int width_hint_here = width_hint;
439  bool sign_hint_here = sign_hint;
440  bool in_param_here = in_param;
441  if (i == 0 && (type == AST_REPLICATE || type == AST_WIRE))
442  const_fold_here = true, in_param_here = true;
443  if (type == AST_PARAMETER || type == AST_LOCALPARAM)
444  const_fold_here = true;
445  if (i == 0 && (type == AST_ASSIGN || type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE))
446  in_lvalue_here = true;
447  if (type == AST_BLOCK) {
448  current_block = this;
449  current_block_child = children[i];
450  }
451  if ((type == AST_ALWAYS || type == AST_INITIAL) && children[i]->type == AST_BLOCK)
452  current_top_block = children[i];
453  if (i == 0 && child_0_is_self_determined)
454  width_hint_here = -1, sign_hint_here = false;
455  if (i == 1 && child_1_is_self_determined)
456  width_hint_here = -1, sign_hint_here = false;
457  if (i == 2 && child_2_is_self_determined)
458  width_hint_here = -1, sign_hint_here = false;
459  if (children_are_self_determined)
460  width_hint_here = -1, sign_hint_here = false;
461  did_something_here = children[i]->simplify(const_fold_here, at_zero, in_lvalue_here, stage, width_hint_here, sign_hint_here, in_param_here);
462  if (did_something_here)
463  did_something = true;
464  }
465  if (stage == 2 && children[i]->type == AST_INITIAL && current_ast_mod != this) {
466  current_ast_mod->children.push_back(children[i]);
467  children.erase(children.begin() + (i--));
468  did_something = true;
469  }
470  }
471  for (auto &attr : attributes) {
472  while (attr.second->simplify(true, false, false, stage, -1, false, true))
473  did_something = true;
474  }
475 
476  if (reset_width_after_children) {
477  width_hint = backup_width_hint;
478  sign_hint = backup_sign_hint;
479  if (width_hint < 0)
480  detectSignWidth(width_hint, sign_hint);
481  }
482 
483  current_block = backup_current_block;
484  current_block_child = backup_current_block_child;
485  current_top_block = backup_current_top_block;
486 
487  for (auto it = backup_scope.begin(); it != backup_scope.end(); it++) {
488  if (it->second == NULL)
489  current_scope.erase(it->first);
490  else
491  current_scope[it->first] = it->second;
492  }
493 
496 
497  if (type == AST_MODULE)
498  current_scope.clear();
499 
500  // convert defparam nodes to cell parameters
501  if (type == AST_DEFPARAM && !str.empty()) {
502  size_t pos = str.rfind('.');
503  if (pos == std::string::npos)
504  log_error("Defparam `%s' does not contain a dot (module/parameter separator) at %s:%d!\n",
505  RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
506  std::string modname = str.substr(0, pos), paraname = "\\" + str.substr(pos+1);
507  if (current_scope.count(modname) == 0 || current_scope.at(modname)->type != AST_CELL)
508  log_error("Can't find cell for defparam `%s . %s` at %s:%d!\n", RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paraname).c_str(), filename.c_str(), linenum);
509  AstNode *cell = current_scope.at(modname), *paraset = clone();
510  cell->children.insert(cell->children.begin() + 1, paraset);
511  paraset->type = AST_PARASET;
512  paraset->str = paraname;
513  str.clear();
514  }
515 
516  // resolve constant prefixes
517  if (type == AST_PREFIX) {
518  if (children[0]->type != AST_CONSTANT) {
519  // dumpAst(NULL, "> ");
520  log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum);
521  }
522  log_assert(children[1]->type == AST_IDENTIFIER);
523  newNode = children[1]->clone();
524  const char *second_part = children[1]->str.c_str();
525  if (second_part[0] == '\\')
526  second_part++;
527  newNode->str = stringf("%s[%d].%s", str.c_str(), children[0]->integer, second_part);
528  goto apply_newNode;
529  }
530 
531  // evaluate TO_BITS nodes
532  if (type == AST_TO_BITS) {
533  if (children[0]->type != AST_CONSTANT)
534  log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
535  if (children[1]->type != AST_CONSTANT)
536  log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
537  RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
538  newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
539  goto apply_newNode;
540  }
541 
542  // annotate constant ranges
543  if (type == AST_RANGE) {
544  bool old_range_valid = range_valid;
545  range_valid = false;
546  range_swapped = false;
547  range_left = -1;
548  range_right = 0;
549  log_assert(children.size() >= 1);
550  if (children[0]->type == AST_CONSTANT) {
551  range_valid = true;
552  range_left = children[0]->integer;
553  if (children.size() == 1)
555  }
556  if (children.size() >= 2) {
557  if (children[1]->type == AST_CONSTANT)
558  range_right = children[1]->integer;
559  else
560  range_valid = false;
561  }
562  if (old_range_valid != range_valid)
563  did_something = true;
564  if (range_valid && range_left >= 0 && range_right > range_left) {
565  int tmp = range_right;
567  range_left = tmp;
568  range_swapped = true;
569  }
570  }
571 
572  // annotate wires with their ranges
573  if (type == AST_WIRE) {
574  if (children.size() > 0) {
575  if (children[0]->range_valid) {
576  if (!range_valid)
577  did_something = true;
578  range_valid = true;
579  range_swapped = children[0]->range_swapped;
580  range_left = children[0]->range_left;
581  range_right = children[0]->range_right;
582  }
583  } else {
584  if (!range_valid)
585  did_something = true;
586  range_valid = true;
587  range_swapped = false;
588  range_left = 0;
589  range_right = 0;
590  }
591  }
592 
593  // resolve multiranges on memory decl
594  if (type == AST_MEMORY && children.size() > 1 && children[1]->type == AST_MULTIRANGE)
595  {
596  int total_size = 1;
597  multirange_dimensions.clear();
598  for (auto range : children[1]->children) {
599  if (!range->range_valid)
600  log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
601  multirange_dimensions.push_back(std::min(range->range_left, range->range_right));
602  multirange_dimensions.push_back(std::max(range->range_left, range->range_right) - std::min(range->range_left, range->range_right) + 1);
603  total_size *= multirange_dimensions.back();
604  }
605  delete children[1];
606  children[1] = new AstNode(AST_RANGE, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size-1, true));
607  did_something = true;
608  }
609 
610  // resolve multiranges on memory access
611  if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY && children.size() > 0 && children[0]->type == AST_MULTIRANGE)
612  {
613  AstNode *index_expr = nullptr;
614 
615  for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++)
616  {
617  if (GetSize(children[0]->children) < i)
618  log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum);
619 
620  AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
621 
622  if (id2ast->multirange_dimensions[2*i])
623  new_index_expr = new AstNode(AST_SUB, new_index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i], true));
624 
625  if (i == 0)
626  index_expr = new_index_expr;
627  else
628  index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i-1], true)), new_index_expr);
629  }
630 
631  for (int i = GetSize(id2ast->multirange_dimensions)/1; i < GetSize(children[0]->children); i++)
632  children.push_back(children[0]->children[i]->clone());
633 
634  delete children[0];
635  if (index_expr == nullptr)
636  children.erase(children.begin());
637  else
638  children[0] = new AstNode(AST_RANGE, index_expr);
639 
640  did_something = true;
641  }
642 
643  // trim/extend parameters
644  if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
645  if (children.size() > 1 && children[1]->type == AST_RANGE) {
646  if (!children[1]->range_valid)
647  log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
648  int width = children[1]->range_left - children[1]->range_right + 1;
649  if (children[0]->type == AST_REALVALUE) {
650  RTLIL::Const constvalue = children[0]->realAsConst(width);
651  log_warning("converting real value %e to binary %s at %s:%d.\n",
652  children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum);
653  delete children[0];
654  children[0] = mkconst_bits(constvalue.bits, sign_hint);
655  did_something = true;
656  }
657  if (children[0]->type == AST_CONSTANT) {
658  if (width != int(children[0]->bits.size())) {
659  RTLIL::SigSpec sig(children[0]->bits);
660  sig.extend_u0(width, children[0]->is_signed);
661  AstNode *old_child_0 = children[0];
662  children[0] = mkconst_bits(sig.as_const().bits, children[0]->is_signed);
663  delete old_child_0;
664  }
665  children[0]->is_signed = is_signed;
666  }
667  range_valid = true;
668  range_swapped = children[1]->range_swapped;
669  range_left = children[1]->range_left;
670  range_right = children[1]->range_right;
671  } else
672  if (children.size() > 1 && children[1]->type == AST_REALVALUE && children[0]->type == AST_CONSTANT) {
673  double as_realvalue = children[0]->asReal(sign_hint);
674  delete children[0];
675  children[0] = new AstNode(AST_REALVALUE);
676  children[0]->realvalue = as_realvalue;
677  did_something = true;
678  }
679  }
680 
681  // annotate identifiers using scope resolution and create auto-wires as needed
682  if (type == AST_IDENTIFIER) {
683  if (current_scope.count(str) == 0) {
684  for (auto node : current_ast_mod->children) {
685  if ((node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR ||
686  node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION) && str == node->str) {
687  current_scope[node->str] = node;
688  break;
689  }
690  }
691  }
692  if (current_scope.count(str) == 0) {
693  // log_warning("Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str());
694  AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
695  auto_wire->str = str;
696  current_ast_mod->children.push_back(auto_wire);
697  current_scope[str] = auto_wire;
698  did_something = true;
699  }
700  if (id2ast != current_scope[str]) {
702  did_something = true;
703  }
704  }
705 
706  // split memory access with bit select to individual statements
707  if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
708  {
709  if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
710  log_error("Invalid bit-select on memory access at %s:%d!\n", filename.c_str(), linenum);
711 
712  int mem_width, mem_size, addr_bits;
713  id2ast->meminfo(mem_width, mem_size, addr_bits);
714 
715  std::stringstream sstr;
716  sstr << "$mem2bits$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
717  std::string wire_id = sstr.str();
718 
719  AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
720  wire->str = wire_id;
721  if (current_block)
722  wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
723  current_ast_mod->children.push_back(wire);
724  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
725 
726  AstNode *data = clone();
727  delete data->children[1];
728  data->children.pop_back();
729 
730  AstNode *assign = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), data);
731  assign->children[0]->str = wire_id;
732 
733  if (current_block)
734  {
735  size_t assign_idx = 0;
736  while (assign_idx < current_block->children.size() && current_block->children[assign_idx] != current_block_child)
737  assign_idx++;
738  log_assert(assign_idx < current_block->children.size());
739  current_block->children.insert(current_block->children.begin()+assign_idx, assign);
740  wire->is_reg = true;
741  }
742  else
743  {
744  AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK));
745  proc->children[0]->children.push_back(assign);
746  current_ast_mod->children.push_back(proc);
747  }
748 
749  newNode = new AstNode(AST_IDENTIFIER, children[1]->clone());
750  newNode->str = wire_id;
751  newNode->id2ast = wire;
752  goto apply_newNode;
753  }
754 
755  if (type == AST_WHILE)
756  log_error("While loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
757 
758  if (type == AST_REPEAT)
759  log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
760 
761  // unroll for loops and generate-for blocks
762  if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
763  {
764  AstNode *init_ast = children[0];
765  AstNode *while_ast = children[1];
766  AstNode *next_ast = children[2];
767  AstNode *body_ast = children[3];
768 
769  while (body_ast->type == AST_GENBLOCK && body_ast->str.empty() &&
770  body_ast->children.size() == 1 && body_ast->children.at(0)->type == AST_GENBLOCK)
771  body_ast = body_ast->children.at(0);
772 
773  if (init_ast->type != AST_ASSIGN_EQ)
774  log_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
775  if (next_ast->type != AST_ASSIGN_EQ)
776  log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
777 
778  if (type == AST_GENFOR) {
779  if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
780  log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
781  if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR)
782  log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
783  } else {
784  if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE)
785  log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
786  if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE)
787  log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum);
788  }
789 
790  if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast)
791  log_error("Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
792 
793  // eval 1st expression
794  AstNode *varbuf = init_ast->children[1]->clone();
795  while (varbuf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
796 
797  if (varbuf->type != AST_CONSTANT)
798  log_error("Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
799 
800  varbuf = new AstNode(AST_LOCALPARAM, varbuf);
801  varbuf->str = init_ast->children[0]->str;
802 
803  AstNode *backup_scope_varbuf = current_scope[varbuf->str];
804  current_scope[varbuf->str] = varbuf;
805 
806  size_t current_block_idx = 0;
807  if (type == AST_FOR) {
808  while (current_block_idx < current_block->children.size() &&
809  current_block->children[current_block_idx] != current_block_child)
810  current_block_idx++;
811  }
812 
813  while (1)
814  {
815  // eval 2nd expression
816  AstNode *buf = while_ast->clone();
817  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
818 
819  if (buf->type != AST_CONSTANT)
820  log_error("2nd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
821 
822  if (buf->integer == 0) {
823  delete buf;
824  break;
825  }
826  delete buf;
827 
828  // expand body
829  int index = varbuf->children[0]->integer;
830  if (body_ast->type == AST_GENBLOCK)
831  buf = body_ast->clone();
832  else
833  buf = new AstNode(AST_GENBLOCK, body_ast->clone());
834  if (buf->str.empty()) {
835  std::stringstream sstr;
836  sstr << "$genblock$" << filename << ":" << linenum << "$" << (autoidx++);
837  buf->str = sstr.str();
838  }
839  std::map<std::string, std::string> name_map;
840  std::stringstream sstr;
841  sstr << buf->str << "[" << index << "].";
842  buf->expand_genblock(varbuf->str, sstr.str(), name_map);
843 
844  if (type == AST_GENFOR) {
845  for (size_t i = 0; i < buf->children.size(); i++) {
846  buf->children[i]->simplify(false, false, false, stage, -1, false, false);
847  current_ast_mod->children.push_back(buf->children[i]);
848  }
849  } else {
850  for (size_t i = 0; i < buf->children.size(); i++)
851  current_block->children.insert(current_block->children.begin() + current_block_idx++, buf->children[i]);
852  }
853  buf->children.clear();
854  delete buf;
855 
856  // eval 3rd expression
857  buf = next_ast->children[1]->clone();
858  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
859 
860  if (buf->type != AST_CONSTANT)
861  log_error("Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum);
862 
863  delete varbuf->children[0];
864  varbuf->children[0] = buf;
865  }
866 
867  current_scope[varbuf->str] = backup_scope_varbuf;
868  delete varbuf;
869  delete_children();
870  did_something = true;
871  }
872 
873  // transform block with name
874  if (type == AST_BLOCK && !str.empty())
875  {
876  std::map<std::string, std::string> name_map;
877  expand_genblock(std::string(), str + ".", name_map);
878 
879  std::vector<AstNode*> new_children;
880  for (size_t i = 0; i < children.size(); i++)
881  if (children[i]->type == AST_WIRE) {
882  children[i]->simplify(false, false, false, stage, -1, false, false);
883  current_ast_mod->children.push_back(children[i]);
884  current_scope[children[i]->str] = children[i];
885  } else
886  new_children.push_back(children[i]);
887 
888  children.swap(new_children);
889  did_something = true;
890  str.clear();
891  }
892 
893  // simplify unconditional generate block
894  if (type == AST_GENBLOCK && children.size() != 0)
895  {
896  if (!str.empty()) {
897  std::map<std::string, std::string> name_map;
898  expand_genblock(std::string(), str + ".", name_map);
899  }
900 
901  for (size_t i = 0; i < children.size(); i++) {
902  children[i]->simplify(false, false, false, stage, -1, false, false);
903  current_ast_mod->children.push_back(children[i]);
904  }
905 
906  children.clear();
907  did_something = true;
908  }
909 
910  // simplify generate-if blocks
911  if (type == AST_GENIF && children.size() != 0)
912  {
913  AstNode *buf = children[0]->clone();
914  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
915  if (buf->type != AST_CONSTANT) {
916  // for (auto f : log_files)
917  // dumpAst(f, "verilog-ast> ");
918  log_error("Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum);
919  }
920  if (buf->asBool() != 0) {
921  delete buf;
922  buf = children[1]->clone();
923  } else {
924  delete buf;
925  buf = children.size() > 2 ? children[2]->clone() : NULL;
926  }
927 
928  if (buf)
929  {
930  if (buf->type != AST_GENBLOCK)
931  buf = new AstNode(AST_GENBLOCK, buf);
932 
933  if (!buf->str.empty()) {
934  std::map<std::string, std::string> name_map;
935  buf->expand_genblock(std::string(), buf->str + ".", name_map);
936  }
937 
938  for (size_t i = 0; i < buf->children.size(); i++) {
939  buf->children[i]->simplify(false, false, false, stage, -1, false, false);
940  current_ast_mod->children.push_back(buf->children[i]);
941  }
942 
943  buf->children.clear();
944  delete buf;
945  }
946 
947  delete_children();
948  did_something = true;
949  }
950 
951  // simplify generate-case blocks
952  if (type == AST_GENCASE && children.size() != 0)
953  {
954  AstNode *buf = children[0]->clone();
955  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
956  if (buf->type != AST_CONSTANT) {
957  // for (auto f : log_files)
958  // dumpAst(f, "verilog-ast> ");
959  log_error("Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
960  }
961 
962  bool ref_signed = buf->is_signed;
963  RTLIL::Const ref_value = buf->bitsAsConst();
964  delete buf;
965 
966  AstNode *selected_case = NULL;
967  for (size_t i = 1; i < children.size(); i++)
968  {
969  log_assert(children.at(i)->type == AST_COND);
970 
971  AstNode *this_genblock = NULL;
972  for (auto child : children.at(i)->children) {
973  log_assert(this_genblock == NULL);
974  if (child->type == AST_GENBLOCK)
975  this_genblock = child;
976  }
977 
978  for (auto child : children.at(i)->children)
979  {
980  if (child->type == AST_DEFAULT) {
981  if (selected_case == NULL)
982  selected_case = this_genblock;
983  continue;
984  }
985  if (child->type == AST_GENBLOCK)
986  continue;
987 
988  buf = child->clone();
989  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
990  if (buf->type != AST_CONSTANT) {
991  // for (auto f : log_files)
992  // dumpAst(f, "verilog-ast> ");
993  log_error("Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
994  }
995 
996  bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool();
997  delete buf;
998 
999  if (is_selected) {
1000  selected_case = this_genblock;
1001  i = children.size();
1002  break;
1003  }
1004  }
1005  }
1006 
1007  if (selected_case != NULL)
1008  {
1009  log_assert(selected_case->type == AST_GENBLOCK);
1010  buf = selected_case->clone();
1011 
1012  if (!buf->str.empty()) {
1013  std::map<std::string, std::string> name_map;
1014  buf->expand_genblock(std::string(), buf->str + ".", name_map);
1015  }
1016 
1017  for (size_t i = 0; i < buf->children.size(); i++) {
1018  buf->children[i]->simplify(false, false, false, stage, -1, false, false);
1019  current_ast_mod->children.push_back(buf->children[i]);
1020  }
1021 
1022  buf->children.clear();
1023  delete buf;
1024  }
1025 
1026  delete_children();
1027  did_something = true;
1028  }
1029 
1030  // unroll cell arrays
1031  if (type == AST_CELLARRAY)
1032  {
1033  if (!children.at(0)->range_valid)
1034  log_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum);
1035 
1036  newNode = new AstNode(AST_GENBLOCK);
1037  int num = std::max(children.at(0)->range_left, children.at(0)->range_right) - std::min(children.at(0)->range_left, children.at(0)->range_right) + 1;
1038 
1039  for (int i = 0; i < num; i++) {
1040  int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
1041  AstNode *new_cell = children.at(1)->clone();
1042  newNode->children.push_back(new_cell);
1043  new_cell->str += stringf("[%d]", idx);
1044  if (new_cell->type == AST_PRIMITIVE) {
1045  log_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename.c_str(), linenum);
1046  } else {
1047  log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
1048  new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
1049  }
1050  }
1051 
1052  goto apply_newNode;
1053  }
1054 
1055  // replace primitives with assignmens
1056  if (type == AST_PRIMITIVE)
1057  {
1058  if (children.size() < 2)
1059  log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n",
1060  str.c_str(), filename.c_str(), linenum);
1061 
1062  std::vector<AstNode*> children_list;
1063  for (auto child : children) {
1064  log_assert(child->type == AST_ARGUMENT);
1065  log_assert(child->children.size() == 1);
1066  children_list.push_back(child->children[0]);
1067  child->children.clear();
1068  delete child;
1069  }
1070  children.clear();
1071 
1072  if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
1073  {
1074  if (children_list.size() != 3)
1075  log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
1076  str.c_str(), filename.c_str(), linenum);
1077 
1078  std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
1079 
1080  AstNode *mux_input = children_list.at(1);
1081  if (str == "notif0" || str == "notif1") {
1082  mux_input = new AstNode(AST_BIT_NOT, mux_input);
1083  }
1084  AstNode *node = new AstNode(AST_TERNARY, children_list.at(2));
1085  if (str == "bufif0") {
1086  node->children.push_back(AstNode::mkconst_bits(z_const, false));
1087  node->children.push_back(mux_input);
1088  } else {
1089  node->children.push_back(mux_input);
1090  node->children.push_back(AstNode::mkconst_bits(z_const, false));
1091  }
1092 
1093  str.clear();
1094  type = AST_ASSIGN;
1095  children.push_back(children_list.at(0));
1096  children.push_back(node);
1097  did_something = true;
1098  }
1099  else
1100  {
1101  AstNodeType op_type = AST_NONE;
1102  bool invert_results = false;
1103 
1104  if (str == "and")
1105  op_type = AST_BIT_AND;
1106  if (str == "nand")
1107  op_type = AST_BIT_AND, invert_results = true;
1108  if (str == "or")
1109  op_type = AST_BIT_OR;
1110  if (str == "nor")
1111  op_type = AST_BIT_OR, invert_results = true;
1112  if (str == "xor")
1113  op_type = AST_BIT_XOR;
1114  if (str == "xnor")
1115  op_type = AST_BIT_XOR, invert_results = true;
1116  if (str == "buf")
1117  op_type = AST_POS;
1118  if (str == "not")
1119  op_type = AST_POS, invert_results = true;
1120  log_assert(op_type != AST_NONE);
1121 
1122  AstNode *node = children_list[1];
1123  if (op_type != AST_POS)
1124  for (size_t i = 2; i < children_list.size(); i++)
1125  node = new AstNode(op_type, node, children_list[i]);
1126  if (invert_results)
1127  node = new AstNode(AST_BIT_NOT, node);
1128 
1129  str.clear();
1130  type = AST_ASSIGN;
1131  children.push_back(children_list[0]);
1132  children.push_back(node);
1133  did_something = true;
1134  }
1135  }
1136 
1137  // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
1138  // a big case block that selects the correct single-bit assignment.
1139  if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) {
1140  if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0)
1141  goto skip_dynamic_range_lvalue_expansion;
1142  if (children[0]->children[0]->range_valid || did_something)
1143  goto skip_dynamic_range_lvalue_expansion;
1144  if (children[0]->id2ast == NULL || children[0]->id2ast->type != AST_WIRE)
1145  goto skip_dynamic_range_lvalue_expansion;
1146  if (!children[0]->id2ast->range_valid)
1147  goto skip_dynamic_range_lvalue_expansion;
1148  int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1;
1149  int result_width = 1;
1150  AstNode *shift_expr = NULL;
1151  AstNode *range = children[0]->children[0];
1152  if (range->children.size() == 1) {
1153  shift_expr = range->children[0]->clone();
1154  } else {
1155  shift_expr = range->children[1]->clone();
1156  AstNode *left_at_zero_ast = range->children[0]->clone();
1157  AstNode *right_at_zero_ast = range->children[1]->clone();
1158  while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1159  while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
1160  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1161  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
1162  str.c_str(), filename.c_str(), linenum);
1163  result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
1164  }
1165  did_something = true;
1166  newNode = new AstNode(AST_CASE, shift_expr);
1167  for (int i = 0; i <= source_width-result_width; i++) {
1168  int start_bit = children[0]->id2ast->range_right + i;
1169  AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));
1170  AstNode *lvalue = children[0]->clone();
1171  lvalue->delete_children();
1172  lvalue->children.push_back(new AstNode(AST_RANGE,
1173  mkconst_int(start_bit+result_width-1, true), mkconst_int(start_bit, true)));
1174  cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
1175  newNode->children.push_back(cond);
1176  }
1177  goto apply_newNode;
1178  }
1179 skip_dynamic_range_lvalue_expansion:;
1180 
1181  if (stage > 1 && type == AST_ASSERT && current_block != NULL)
1182  {
1183  std::stringstream sstr;
1184  sstr << "$assert$" << filename << ":" << linenum << "$" << (autoidx++);
1185  std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
1186 
1187  AstNode *wire_check = new AstNode(AST_WIRE);
1188  wire_check->str = id_check;
1189  current_ast_mod->children.push_back(wire_check);
1190  current_scope[wire_check->str] = wire_check;
1191  while (wire_check->simplify(true, false, false, 1, -1, false, false)) { }
1192 
1193  AstNode *wire_en = new AstNode(AST_WIRE);
1194  wire_en->str = id_en;
1195  current_ast_mod->children.push_back(wire_en);
1197  current_ast_mod->children.back()->children[0]->children[0]->children[0]->str = id_en;
1198  current_scope[wire_en->str] = wire_en;
1199  while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
1200 
1201  std::vector<RTLIL::State> x_bit;
1202  x_bit.push_back(RTLIL::State::Sx);
1203 
1204  AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false));
1205  assign_check->children[0]->str = id_check;
1206 
1207  AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1));
1208  assign_en->children[0]->str = id_en;
1209 
1210  AstNode *default_signals = new AstNode(AST_BLOCK);
1211  default_signals->children.push_back(assign_check);
1212  default_signals->children.push_back(assign_en);
1213  current_top_block->children.insert(current_top_block->children.begin(), default_signals);
1214 
1215  assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
1216  assign_check->children[0]->str = id_check;
1217 
1218  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
1219  assign_en->children[0]->str = id_en;
1220 
1221  newNode = new AstNode(AST_BLOCK);
1222  newNode->children.push_back(assign_check);
1223  newNode->children.push_back(assign_en);
1224 
1225  AstNode *assertnode = new AstNode(AST_ASSERT);
1226  assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1227  assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
1228  assertnode->children[0]->str = id_check;
1229  assertnode->children[1]->str = id_en;
1230  assertnode->attributes.swap(attributes);
1231  current_ast_mod->children.push_back(assertnode);
1232 
1233  goto apply_newNode;
1234  }
1235 
1236  if (stage > 1 && type == AST_ASSERT && children.size() == 1)
1237  {
1238  children[0] = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
1239  children.push_back(mkconst_int(1, false, 1));
1240  did_something = true;
1241  }
1242 
1243  // found right-hand side identifier for memory -> replace with memory read port
1244  if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
1245  children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
1246  newNode = new AstNode(AST_MEMRD, children[0]->children[0]->clone());
1247  newNode->str = str;
1248  newNode->id2ast = id2ast;
1249  goto apply_newNode;
1250  }
1251 
1252  // assignment with memory in left-hand side expression -> replace with memory write port
1253  if (stage > 1 && (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_IDENTIFIER &&
1254  children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
1255  children[0]->id2ast->children[0]->range_valid && children[0]->id2ast->children[1]->range_valid &&
1256  (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE)
1257  {
1258  std::stringstream sstr;
1259  sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
1260  std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
1261 
1262  if (type == AST_ASSIGN_EQ)
1263  log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",
1264  filename.c_str(), linenum);
1265 
1266  int mem_width, mem_size, addr_bits;
1267  children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
1268 
1269  AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
1270  wire_addr->str = id_addr;
1271  current_ast_mod->children.push_back(wire_addr);
1272  current_scope[wire_addr->str] = wire_addr;
1273  while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
1274 
1275  AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1276  wire_data->str = id_data;
1277  current_ast_mod->children.push_back(wire_data);
1278  current_scope[wire_data->str] = wire_data;
1279  while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
1280 
1281  AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
1282  wire_en->str = id_en;
1283  current_ast_mod->children.push_back(wire_en);
1284  current_scope[wire_en->str] = wire_en;
1285  while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
1286 
1287  std::vector<RTLIL::State> x_bits_addr, x_bits_data, set_bits_en;
1288  for (int i = 0; i < addr_bits; i++)
1289  x_bits_addr.push_back(RTLIL::State::Sx);
1290  for (int i = 0; i < mem_width; i++)
1291  x_bits_data.push_back(RTLIL::State::Sx);
1292  for (int i = 0; i < mem_width; i++)
1293  set_bits_en.push_back(RTLIL::State::S1);
1294 
1295  AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
1296  assign_addr->children[0]->str = id_addr;
1297 
1298  AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
1299  assign_data->children[0]->str = id_data;
1300 
1301  AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
1302  assign_en->children[0]->str = id_en;
1303 
1304  AstNode *default_signals = new AstNode(AST_BLOCK);
1305  default_signals->children.push_back(assign_addr);
1306  default_signals->children.push_back(assign_data);
1307  default_signals->children.push_back(assign_en);
1308  current_top_block->children.insert(current_top_block->children.begin(), default_signals);
1309 
1310  assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
1311  assign_addr->children[0]->str = id_addr;
1312 
1313  if (children[0]->children.size() == 2)
1314  {
1315  if (children[0]->children[1]->range_valid)
1316  {
1317  int offset = children[0]->children[1]->range_right;
1318  int width = children[0]->children[1]->range_left - offset + 1;
1319 
1320  std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx);
1321 
1322  for (int i = 0; i < mem_width; i++)
1323  set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
1324 
1325  assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1326  new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone()));
1327  assign_data->children[0]->str = id_data;
1328 
1329  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
1330  assign_en->children[0]->str = id_en;
1331  }
1332  else
1333  {
1334  AstNode *the_range = children[0]->children[1];
1335  AstNode *left_at_zero_ast = the_range->children[0]->clone();
1336  AstNode *right_at_zero_ast = the_range->children.size() >= 2 ? the_range->children[1]->clone() : left_at_zero_ast->clone();
1337  AstNode *offset_ast = right_at_zero_ast->clone();
1338 
1339  while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1340  while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
1341  if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
1342  log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
1343  int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
1344 
1345  for (int i = 0; i < mem_width; i++)
1346  set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
1347 
1348  assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1349  new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));
1350  assign_data->children[0]->str = id_data;
1351 
1352  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
1353  new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
1354  assign_en->children[0]->str = id_en;
1355 
1356  delete left_at_zero_ast;
1357  delete right_at_zero_ast;
1358  delete offset_ast;
1359  }
1360  }
1361  else
1362  {
1363  assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
1364  assign_data->children[0]->str = id_data;
1365 
1366  assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
1367  assign_en->children[0]->str = id_en;
1368  }
1369 
1370  newNode = new AstNode(AST_BLOCK);
1371  newNode->children.push_back(assign_addr);
1372  newNode->children.push_back(assign_data);
1373  newNode->children.push_back(assign_en);
1374 
1375  AstNode *wrnode = new AstNode(AST_MEMWR);
1376  wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1377  wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1378  wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
1379  wrnode->str = children[0]->str;
1380  wrnode->children[0]->str = id_addr;
1381  wrnode->children[1]->str = id_data;
1382  wrnode->children[2]->str = id_en;
1383  current_ast_mod->children.push_back(wrnode);
1384 
1385  goto apply_newNode;
1386  }
1387 
1388  // replace function and task calls with the code from the function or task
1389  if ((type == AST_FCALL || type == AST_TCALL) && !str.empty())
1390  {
1391  if (type == AST_FCALL)
1392  {
1393  if (str == "\\$clog2")
1394  {
1395  if (children.size() != 1)
1396  log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1397  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1398 
1399  AstNode *buf = children[0]->clone();
1400  while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1401  if (buf->type != AST_CONSTANT)
1402  log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1403 
1404  RTLIL::Const arg_value = buf->bitsAsConst();
1405  if (arg_value.as_bool())
1406  arg_value = const_sub(arg_value, 1, false, false, GetSize(arg_value));
1407  delete buf;
1408 
1409  uint32_t result = 0;
1410  for (size_t i = 0; i < arg_value.bits.size(); i++)
1411  if (arg_value.bits.at(i) == RTLIL::State::S1)
1412  result = i + 1;
1413 
1414  newNode = mkconst_int(result, false);
1415  goto apply_newNode;
1416  }
1417 
1418  if (str == "\\$ln" || str == "\\$log10" || str == "\\$exp" || str == "\\$sqrt" || str == "\\$pow" ||
1419  str == "\\$floor" || str == "\\$ceil" || str == "\\$sin" || str == "\\$cos" || str == "\\$tan" ||
1420  str == "\\$asin" || str == "\\$acos" || str == "\\$atan" || str == "\\$atan2" || str == "\\$hypot" ||
1421  str == "\\$sinh" || str == "\\$cosh" || str == "\\$tanh" || str == "\\$asinh" || str == "\\$acosh" || str == "\\$atanh")
1422  {
1423  bool func_with_two_arguments = str == "\\$pow" || str == "\\$atan2" || str == "\\$hypot";
1424  double x = 0, y = 0;
1425 
1426  if (func_with_two_arguments) {
1427  if (children.size() != 2)
1428  log_error("System function %s got %d arguments, expected 2 at %s:%d.\n",
1429  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1430  } else {
1431  if (children.size() != 1)
1432  log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
1433  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1434  }
1435 
1436  if (children.size() >= 1) {
1437  while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1438  if (!children[0]->isConst())
1439  log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1440  RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
1441  int child_width_hint = width_hint;
1442  bool child_sign_hint = sign_hint;
1443  children[0]->detectSignWidth(child_width_hint, child_sign_hint);
1444  x = children[0]->asReal(child_sign_hint);
1445  }
1446 
1447  if (children.size() >= 2) {
1448  while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1449  if (!children[1]->isConst())
1450  log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
1451  RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
1452  int child_width_hint = width_hint;
1453  bool child_sign_hint = sign_hint;
1454  children[1]->detectSignWidth(child_width_hint, child_sign_hint);
1455  y = children[1]->asReal(child_sign_hint);
1456  }
1457 
1458  newNode = new AstNode(AST_REALVALUE);
1459  if (str == "\\$ln") newNode->realvalue = ::log(x);
1460  else if (str == "\\$log10") newNode->realvalue = ::log10(x);
1461  else if (str == "\\$exp") newNode->realvalue = ::exp(x);
1462  else if (str == "\\$sqrt") newNode->realvalue = ::sqrt(x);
1463  else if (str == "\\$pow") newNode->realvalue = ::pow(x, y);
1464  else if (str == "\\$floor") newNode->realvalue = ::floor(x);
1465  else if (str == "\\$ceil") newNode->realvalue = ::ceil(x);
1466  else if (str == "\\$sin") newNode->realvalue = ::sin(x);
1467  else if (str == "\\$cos") newNode->realvalue = ::cos(x);
1468  else if (str == "\\$tan") newNode->realvalue = ::tan(x);
1469  else if (str == "\\$asin") newNode->realvalue = ::asin(x);
1470  else if (str == "\\$acos") newNode->realvalue = ::acos(x);
1471  else if (str == "\\$atan") newNode->realvalue = ::atan(x);
1472  else if (str == "\\$atan2") newNode->realvalue = ::atan2(x, y);
1473  else if (str == "\\$hypot") newNode->realvalue = ::hypot(x, y);
1474  else if (str == "\\$sinh") newNode->realvalue = ::sinh(x);
1475  else if (str == "\\$cosh") newNode->realvalue = ::cosh(x);
1476  else if (str == "\\$tanh") newNode->realvalue = ::tanh(x);
1477  else if (str == "\\$asinh") newNode->realvalue = ::asinh(x);
1478  else if (str == "\\$acosh") newNode->realvalue = ::acosh(x);
1479  else if (str == "\\$atanh") newNode->realvalue = ::atanh(x);
1480  else log_abort();
1481  goto apply_newNode;
1482  }
1483 
1484  if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION)
1485  {
1486  AstNode *dpi_decl = current_scope[str];
1487 
1488  std::string rtype, fname;
1489  std::vector<std::string> argtypes;
1490  std::vector<AstNode*> args;
1491 
1492  rtype = RTLIL::unescape_id(dpi_decl->children.at(0)->str);
1493  fname = RTLIL::unescape_id(dpi_decl->children.at(1)->str);
1494 
1495  for (int i = 2; i < GetSize(dpi_decl->children); i++)
1496  {
1497  if (i-2 >= GetSize(children))
1498  log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename.c_str(), linenum);
1499 
1500  argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str));
1501  args.push_back(children.at(i-2)->clone());
1502  while (args.back()->simplify(true, false, false, stage, -1, false, true)) { }
1503 
1504  if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE)
1505  log_error("Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename.c_str(), linenum);
1506  }
1507 
1508  newNode = dpi_call(rtype, fname, argtypes, args);
1509 
1510  for (auto arg : args)
1511  delete arg;
1512 
1513  goto apply_newNode;
1514  }
1515 
1516  if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION)
1517  log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1518  }
1519  if (type == AST_TCALL) {
1520  if (str == "\\$readmemh" || str == "\\$readmemb")
1521  {
1522  if (GetSize(children) < 2 || GetSize(children) > 4)
1523  log_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n",
1524  RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
1525 
1526  AstNode *node_filename = children[0]->clone();
1527  while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1528  if (node_filename->type != AST_CONSTANT)
1529  log_error("Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1530 
1531  AstNode *node_memory = children[1]->clone();
1532  while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1533  if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY)
1534  log_error("Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1535 
1536  int start_addr = -1, finish_addr = -1;
1537 
1538  if (GetSize(children) > 2) {
1539  AstNode *node_addr = children[2]->clone();
1540  while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1541  if (node_addr->type != AST_CONSTANT)
1542  log_error("Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1543  start_addr = node_addr->asInt(false);
1544  }
1545 
1546  if (GetSize(children) > 3) {
1547  AstNode *node_addr = children[3]->clone();
1548  while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
1549  if (node_addr->type != AST_CONSTANT)
1550  log_error("Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1551  finish_addr = node_addr->asInt(false);
1552  }
1553 
1554  newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr);
1555  goto apply_newNode;
1556  }
1557 
1558  if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK)
1559  log_error("Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1560  }
1561 
1562  AstNode *decl = current_scope[str];
1563 
1564  std::stringstream sstr;
1565  sstr << "$func$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++) << "$";
1566  std::string prefix = sstr.str();
1567 
1568  bool recommend_const_eval = false;
1569  bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval);
1570  if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count("\\via_celltype"))
1571  {
1572  bool all_args_const = true;
1573  for (auto child : children) {
1574  while (child->simplify(true, false, false, 1, -1, false, true)) { }
1575  if (child->type != AST_CONSTANT)
1576  all_args_const = false;
1577  }
1578 
1579  if (all_args_const) {
1580  AstNode *func_workspace = current_scope[str]->clone();
1581  newNode = func_workspace->eval_const_function(this);
1582  delete func_workspace;
1583  goto apply_newNode;
1584  }
1585 
1586  if (in_param)
1587  log_error("Non-constant function call in constant expression at %s:%d.\n", filename.c_str(), linenum);
1588  if (require_const_eval)
1589  log_error("Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
1590  }
1591 
1592  size_t arg_count = 0;
1593  std::map<std::string, std::string> replace_rules;
1594 
1595  if (current_block == NULL)
1596  {
1598 
1599  AstNode *wire = NULL;
1600  for (auto child : decl->children)
1601  if (child->type == AST_WIRE && child->str == str)
1602  wire = child->clone();
1603  log_assert(wire != NULL);
1604 
1605  wire->str = prefix + str;
1606  wire->port_id = 0;
1607  wire->is_input = false;
1608  wire->is_output = false;
1609 
1610  current_ast_mod->children.push_back(wire);
1611  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1612 
1613  AstNode *lvalue = new AstNode(AST_IDENTIFIER);
1614  lvalue->str = wire->str;
1615 
1616  AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK,
1617  new AstNode(AST_ASSIGN_EQ, lvalue, clone())));
1618  current_ast_mod->children.push_back(always);
1619 
1620  goto replace_fcall_with_id;
1621  }
1622 
1623  if (decl->attributes.count("\\via_celltype"))
1624  {
1625  std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string();
1626  std::string outport = str;
1627 
1628  if (celltype.find(' ') != std::string::npos) {
1629  int pos = celltype.find(' ');
1630  outport = RTLIL::escape_id(celltype.substr(pos+1));
1631  celltype = RTLIL::escape_id(celltype.substr(0, pos));
1632  } else
1633  celltype = RTLIL::escape_id(celltype);
1634 
1635  AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE));
1636  cell->str = prefix.substr(0, GetSize(prefix)-1);
1637  cell->children[0]->str = celltype;
1638 
1639  for (auto attr : decl->attributes)
1640  if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0)
1641  {
1642  AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone());
1643  cell_arg->str = RTLIL::escape_id(attr.first.str().substr(strlen("\\via_celltype_defparam_")));
1644  cell->children.push_back(cell_arg);
1645  }
1646 
1647  for (auto child : decl->children)
1648  if (child->type == AST_WIRE && (child->is_input || child->is_output || (type == AST_FCALL && child->str == str)))
1649  {
1650  AstNode *wire = child->clone();
1651  wire->str = prefix + wire->str;
1652  wire->port_id = 0;
1653  wire->is_input = false;
1654  wire->is_output = false;
1655  current_ast_mod->children.push_back(wire);
1656  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1657 
1658  AstNode *wire_id = new AstNode(AST_IDENTIFIER);
1659  wire_id->str = wire->str;
1660 
1661  if ((child->is_input || child->is_output) && arg_count < children.size())
1662  {
1663  AstNode *arg = children[arg_count++]->clone();
1664  AstNode *assign = child->is_input ?
1665  new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) :
1666  new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone());
1667 
1668  for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
1669  if (*it != current_block_child)
1670  continue;
1671  current_block->children.insert(it, assign);
1672  break;
1673  }
1674  }
1675 
1676  AstNode *cell_arg = new AstNode(AST_ARGUMENT, wire_id);
1677  cell_arg->str = child->str == str ? outport : child->str;
1678  cell->children.push_back(cell_arg);
1679  }
1680 
1681  current_ast_mod->children.push_back(cell);
1682  goto replace_fcall_with_id;
1683  }
1684 
1685  for (auto child : decl->children)
1686  if (child->type == AST_WIRE)
1687  {
1688  AstNode *wire = child->clone();
1689  wire->str = prefix + wire->str;
1690  wire->port_id = 0;
1691  wire->is_input = false;
1692  wire->is_output = false;
1693  current_ast_mod->children.push_back(wire);
1694  while (wire->simplify(true, false, false, 1, -1, false, false)) { }
1695 
1696  replace_rules[child->str] = wire->str;
1697 
1698  if ((child->is_input || child->is_output) && arg_count < children.size())
1699  {
1700  AstNode *arg = children[arg_count++]->clone();
1701  AstNode *wire_id = new AstNode(AST_IDENTIFIER);
1702  wire_id->str = wire->str;
1703  AstNode *assign = child->is_input ?
1704  new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
1705  new AstNode(AST_ASSIGN_EQ, arg, wire_id);
1706 
1707  for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
1708  if (*it != current_block_child)
1709  continue;
1710  current_block->children.insert(it, assign);
1711  break;
1712  }
1713  }
1714  }
1715 
1716  for (auto child : decl->children)
1717  if (child->type != AST_WIRE)
1718  {
1719  AstNode *stmt = child->clone();
1720  stmt->replace_ids(prefix, replace_rules);
1721 
1722  for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
1723  if (*it != current_block_child)
1724  continue;
1725  current_block->children.insert(it, stmt);
1726  break;
1727  }
1728  }
1729 
1730  replace_fcall_with_id:
1731  if (type == AST_FCALL) {
1732  delete_children();
1733  type = AST_IDENTIFIER;
1734  str = prefix + str;
1735  }
1736  if (type == AST_TCALL)
1737  str = "";
1738  did_something = true;
1739  }
1740 
1741  // perform const folding when activated
1742  if (const_fold)
1743  {
1744  bool string_op;
1745  std::vector<RTLIL::State> tmp_bits;
1746  RTLIL::Const (*const_func)(const RTLIL::Const&, const RTLIL::Const&, bool, bool, int);
1747  RTLIL::Const dummy_arg;
1748 
1749  switch (type)
1750  {
1751  case AST_IDENTIFIER:
1752  if (current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) {
1753  if (current_scope[str]->children[0]->type == AST_CONSTANT) {
1754  if (children.size() != 0 && children[0]->type == AST_RANGE && children[0]->range_valid) {
1755  std::vector<RTLIL::State> data;
1756  bool param_upto = current_scope[str]->range_valid && current_scope[str]->range_swapped;
1757  int param_offset = current_scope[str]->range_valid ? current_scope[str]->range_right : 0;
1758  int param_width = current_scope[str]->range_valid ? current_scope[str]->range_left - current_scope[str]->range_right + 1 :
1759  GetSize(current_scope[str]->children[0]->bits);
1760  int tmp_range_left = children[0]->range_left, tmp_range_right = children[0]->range_right;
1761  if (param_upto) {
1762  tmp_range_left = (param_width + 2*param_offset) - children[0]->range_right - 1;
1763  tmp_range_right = (param_width + 2*param_offset) - children[0]->range_left - 1;
1764  }
1765  for (int i = tmp_range_right; i <= tmp_range_left; i++) {
1766  int index = i - param_offset;
1767  if (0 <= index && index < param_width)
1768  data.push_back(current_scope[str]->children[0]->bits[index]);
1769  else
1770  data.push_back(RTLIL::State::Sx);
1771  }
1772  newNode = mkconst_bits(data, false);
1773  } else
1774  if (children.size() == 0)
1775  newNode = current_scope[str]->children[0]->clone();
1776  } else
1777  if (current_scope[str]->children[0]->isConst())
1778  newNode = current_scope[str]->children[0]->clone();
1779  }
1780  else if (at_zero && current_scope.count(str) > 0 && (current_scope[str]->type == AST_WIRE || current_scope[str]->type == AST_AUTOWIRE)) {
1781  newNode = mkconst_int(0, sign_hint, width_hint);
1782  }
1783  break;
1784  case AST_BIT_NOT:
1785  if (children[0]->type == AST_CONSTANT) {
1786  RTLIL::Const y = RTLIL::const_not(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
1787  newNode = mkconst_bits(y.bits, sign_hint);
1788  }
1789  break;
1790  case AST_TO_SIGNED:
1791  case AST_TO_UNSIGNED:
1792  if (children[0]->type == AST_CONSTANT) {
1793  RTLIL::Const y = children[0]->bitsAsConst(width_hint, sign_hint);
1794  newNode = mkconst_bits(y.bits, type == AST_TO_SIGNED);
1795  }
1796  break;
1797  if (0) { case AST_BIT_AND: const_func = RTLIL::const_and; }
1798  if (0) { case AST_BIT_OR: const_func = RTLIL::const_or; }
1799  if (0) { case AST_BIT_XOR: const_func = RTLIL::const_xor; }
1800  if (0) { case AST_BIT_XNOR: const_func = RTLIL::const_xnor; }
1801  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1802  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1803  children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
1804  newNode = mkconst_bits(y.bits, sign_hint);
1805  }
1806  break;
1807  if (0) { case AST_REDUCE_AND: const_func = RTLIL::const_reduce_and; }
1808  if (0) { case AST_REDUCE_OR: const_func = RTLIL::const_reduce_or; }
1809  if (0) { case AST_REDUCE_XOR: const_func = RTLIL::const_reduce_xor; }
1810  if (0) { case AST_REDUCE_XNOR: const_func = RTLIL::const_reduce_xnor; }
1811  if (0) { case AST_REDUCE_BOOL: const_func = RTLIL::const_reduce_bool; }
1812  if (children[0]->type == AST_CONSTANT) {
1813  RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), dummy_arg, false, false, -1);
1814  newNode = mkconst_bits(y.bits, false);
1815  }
1816  break;
1817  case AST_LOGIC_NOT:
1818  if (children[0]->type == AST_CONSTANT) {
1819  RTLIL::Const y = RTLIL::const_logic_not(RTLIL::Const(children[0]->bits), dummy_arg, children[0]->is_signed, false, -1);
1820  newNode = mkconst_bits(y.bits, false);
1821  } else
1822  if (children[0]->isConst()) {
1823  newNode = mkconst_int(children[0]->asReal(sign_hint) == 0, false, 1);
1824  }
1825  break;
1826  if (0) { case AST_LOGIC_AND: const_func = RTLIL::const_logic_and; }
1827  if (0) { case AST_LOGIC_OR: const_func = RTLIL::const_logic_or; }
1828  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1829  RTLIL::Const y = const_func(RTLIL::Const(children[0]->bits), RTLIL::Const(children[1]->bits),
1830  children[0]->is_signed, children[1]->is_signed, -1);
1831  newNode = mkconst_bits(y.bits, false);
1832  } else
1833  if (children[0]->isConst() && children[1]->isConst()) {
1834  if (type == AST_LOGIC_AND)
1835  newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) && (children[1]->asReal(sign_hint) != 0), false, 1);
1836  else
1837  newNode = mkconst_int((children[0]->asReal(sign_hint) != 0) || (children[1]->asReal(sign_hint) != 0), false, 1);
1838  }
1839  break;
1840  if (0) { case AST_SHIFT_LEFT: const_func = RTLIL::const_shl; }
1841  if (0) { case AST_SHIFT_RIGHT: const_func = RTLIL::const_shr; }
1842  if (0) { case AST_SHIFT_SLEFT: const_func = RTLIL::const_sshl; }
1843  if (0) { case AST_SHIFT_SRIGHT: const_func = RTLIL::const_sshr; }
1844  if (0) { case AST_POW: const_func = RTLIL::const_pow; }
1845  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1846  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1847  RTLIL::Const(children[1]->bits), sign_hint, type == AST_POW ? children[1]->is_signed : false, width_hint);
1848  newNode = mkconst_bits(y.bits, sign_hint);
1849  } else
1850  if (type == AST_POW && children[0]->isConst() && children[1]->isConst()) {
1851  newNode = new AstNode(AST_REALVALUE);
1852  newNode->realvalue = pow(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint));
1853  }
1854  break;
1855  if (0) { case AST_LT: const_func = RTLIL::const_lt; }
1856  if (0) { case AST_LE: const_func = RTLIL::const_le; }
1857  if (0) { case AST_EQ: const_func = RTLIL::const_eq; }
1858  if (0) { case AST_NE: const_func = RTLIL::const_ne; }
1859  if (0) { case AST_EQX: const_func = RTLIL::const_eqx; }
1860  if (0) { case AST_NEX: const_func = RTLIL::const_nex; }
1861  if (0) { case AST_GE: const_func = RTLIL::const_ge; }
1862  if (0) { case AST_GT: const_func = RTLIL::const_gt; }
1863  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1864  int cmp_width = std::max(children[0]->bits.size(), children[1]->bits.size());
1865  bool cmp_signed = children[0]->is_signed && children[1]->is_signed;
1866  RTLIL::Const y = const_func(children[0]->bitsAsConst(cmp_width, cmp_signed),
1867  children[1]->bitsAsConst(cmp_width, cmp_signed), cmp_signed, cmp_signed, 1);
1868  newNode = mkconst_bits(y.bits, false);
1869  } else
1870  if (children[0]->isConst() && children[1]->isConst()) {
1871  bool cmp_signed = (children[0]->type == AST_REALVALUE || children[0]->is_signed) && (children[1]->type == AST_REALVALUE || children[1]->is_signed);
1872  switch (type) {
1873  case AST_LT: newNode = mkconst_int(children[0]->asReal(cmp_signed) < children[1]->asReal(cmp_signed), false, 1); break;
1874  case AST_LE: newNode = mkconst_int(children[0]->asReal(cmp_signed) <= children[1]->asReal(cmp_signed), false, 1); break;
1875  case AST_EQ: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
1876  case AST_NE: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
1877  case AST_EQX: newNode = mkconst_int(children[0]->asReal(cmp_signed) == children[1]->asReal(cmp_signed), false, 1); break;
1878  case AST_NEX: newNode = mkconst_int(children[0]->asReal(cmp_signed) != children[1]->asReal(cmp_signed), false, 1); break;
1879  case AST_GE: newNode = mkconst_int(children[0]->asReal(cmp_signed) >= children[1]->asReal(cmp_signed), false, 1); break;
1880  case AST_GT: newNode = mkconst_int(children[0]->asReal(cmp_signed) > children[1]->asReal(cmp_signed), false, 1); break;
1881  default: log_abort();
1882  }
1883  }
1884  break;
1885  if (0) { case AST_ADD: const_func = RTLIL::const_add; }
1886  if (0) { case AST_SUB: const_func = RTLIL::const_sub; }
1887  if (0) { case AST_MUL: const_func = RTLIL::const_mul; }
1888  if (0) { case AST_DIV: const_func = RTLIL::const_div; }
1889  if (0) { case AST_MOD: const_func = RTLIL::const_mod; }
1890  if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
1891  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
1892  children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);
1893  newNode = mkconst_bits(y.bits, sign_hint);
1894  } else
1895  if (children[0]->isConst() && children[1]->isConst()) {
1896  newNode = new AstNode(AST_REALVALUE);
1897  switch (type) {
1898  case AST_ADD: newNode->realvalue = children[0]->asReal(sign_hint) + children[1]->asReal(sign_hint); break;
1899  case AST_SUB: newNode->realvalue = children[0]->asReal(sign_hint) - children[1]->asReal(sign_hint); break;
1900  case AST_MUL: newNode->realvalue = children[0]->asReal(sign_hint) * children[1]->asReal(sign_hint); break;
1901  case AST_DIV: newNode->realvalue = children[0]->asReal(sign_hint) / children[1]->asReal(sign_hint); break;
1902  case AST_MOD: newNode->realvalue = fmod(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint)); break;
1903  default: log_abort();
1904  }
1905  }
1906  break;
1907  if (0) { case AST_POS: const_func = RTLIL::const_pos; }
1908  if (0) { case AST_NEG: const_func = RTLIL::const_neg; }
1909  if (children[0]->type == AST_CONSTANT) {
1910  RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint), dummy_arg, sign_hint, false, width_hint);
1911  newNode = mkconst_bits(y.bits, sign_hint);
1912  } else
1913  if (children[0]->isConst()) {
1914  newNode = new AstNode(AST_REALVALUE);
1915  if (type == AST_POS)
1916  newNode->realvalue = +children[0]->asReal(sign_hint);
1917  else
1918  newNode->realvalue = -children[0]->asReal(sign_hint);
1919  }
1920  break;
1921  case AST_TERNARY:
1922  if (children[0]->isConst())
1923  {
1924  bool found_sure_true = false;
1925  bool found_maybe_true = false;
1926 
1927  if (children[0]->type == AST_CONSTANT)
1928  for (auto &bit : children[0]->bits) {
1929  if (bit == RTLIL::State::S1)
1930  found_sure_true = true;
1931  if (bit > RTLIL::State::S1)
1932  found_maybe_true = true;
1933  }
1934  else
1935  found_sure_true = children[0]->asReal(sign_hint) != 0;
1936 
1937  AstNode *choice = NULL, *not_choice = NULL;
1938  if (found_sure_true)
1939  choice = children[1], not_choice = children[2];
1940  else if (!found_maybe_true)
1941  choice = children[2], not_choice = children[1];
1942 
1943  if (choice != NULL) {
1944  if (choice->type == AST_CONSTANT) {
1945  int other_width_hint = width_hint;
1946  bool other_sign_hint = sign_hint, other_real = false;
1947  not_choice->detectSignWidth(other_width_hint, other_sign_hint, &other_real);
1948  if (other_real) {
1949  newNode = new AstNode(AST_REALVALUE);
1950  choice->detectSignWidth(width_hint, sign_hint);
1951  newNode->realvalue = choice->asReal(sign_hint);
1952  } else {
1953  RTLIL::Const y = choice->bitsAsConst(width_hint, sign_hint);
1954  if (choice->is_string && y.bits.size() % 8 == 0 && sign_hint == false)
1955  newNode = mkconst_str(y.bits);
1956  else
1957  newNode = mkconst_bits(y.bits, sign_hint);
1958  }
1959  } else
1960  if (choice->isConst()) {
1961  newNode = choice->clone();
1962  }
1963  } else if (children[1]->type == AST_CONSTANT && children[2]->type == AST_CONSTANT) {
1964  RTLIL::Const a = children[1]->bitsAsConst(width_hint, sign_hint);
1965  RTLIL::Const b = children[2]->bitsAsConst(width_hint, sign_hint);
1966  log_assert(a.bits.size() == b.bits.size());
1967  for (size_t i = 0; i < a.bits.size(); i++)
1968  if (a.bits[i] != b.bits[i])
1969  a.bits[i] = RTLIL::State::Sx;
1970  newNode = mkconst_bits(a.bits, sign_hint);
1971  } else if (children[1]->isConst() && children[2]->isConst()) {
1972  newNode = new AstNode(AST_REALVALUE);
1973  if (children[1]->asReal(sign_hint) == children[2]->asReal(sign_hint))
1974  newNode->realvalue = children[1]->asReal(sign_hint);
1975  else
1976  // IEEE Std 1800-2012 Sec. 11.4.11 states that the entry in Table 7-1 for
1977  // the data type in question should be returned if the ?: is ambiguous. The
1978  // value in Table 7-1 for the 'real' type is 0.0.
1979  newNode->realvalue = 0.0;
1980  }
1981  }
1982  break;
1983  case AST_CONCAT:
1984  string_op = !children.empty();
1985  for (auto it = children.begin(); it != children.end(); it++) {
1986  if ((*it)->type != AST_CONSTANT)
1987  goto not_const;
1988  if (!(*it)->is_string)
1989  string_op = false;
1990  tmp_bits.insert(tmp_bits.end(), (*it)->bits.begin(), (*it)->bits.end());
1991  }
1992  newNode = string_op ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
1993  break;
1994  case AST_REPLICATE:
1995  if (children.at(0)->type != AST_CONSTANT || children.at(1)->type != AST_CONSTANT)
1996  goto not_const;
1997  for (int i = 0; i < children[0]->bitsAsConst().as_int(); i++)
1998  tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end());
1999  newNode = children.at(1)->is_string ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
2000  break;
2001  default:
2002  not_const:
2003  break;
2004  }
2005  }
2006 
2007  // if any of the above set 'newNode' -> use 'newNode' as template to update 'this'
2008  if (newNode) {
2009 apply_newNode:
2010  // fprintf(stderr, "----\n");
2011  // dumpAst(stderr, "- ");
2012  // newNode->dumpAst(stderr, "+ ");
2013  log_assert(newNode != NULL);
2014  newNode->filename = filename;
2015  newNode->linenum = linenum;
2016  newNode->cloneInto(this);
2017  delete newNode;
2018  did_something = true;
2019  }
2020 
2021  if (!did_something)
2022  basic_prep = true;
2023 
2024  return did_something;
2025 }
std::map< std::string, AstNode * > current_scope
Definition: ast.cc:58
RTLIL::Const bitsAsConst(int width, bool is_signed)
Definition: ast.cc:741
RTLIL::Const const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:256
bool range_valid
Definition: ast.h:158
RTLIL::Const const_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:175
static AstNode * mkconst_int(uint32_t v, bool is_signed, int width=32)
Definition: ast.cc:672
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
RTLIL::Const const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:511
AstNode * current_top_block
Definition: ast.cc:61
AstNode * dpi_call(const std::string &rtype, const std::string &fname, const std::vector< std::string > &argtypes, const std::vector< AstNode * > &args)
Definition: dpicall.cc:140
void log_warning(const char *format,...)
Definition: log.cc:196
RTLIL::Const const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:403
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
Definition: ast.cc:688
AstNode * current_block
Definition: ast.cc:61
RTLIL::Const const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:379
static AstNode * mkconst_str(const std::vector< RTLIL::State > &v)
Definition: ast.cc:706
void dumpAst(FILE *f, std::string indent)
Definition: ast.cc:250
static std::string unescape_id(std::string str)
Definition: rtlil.h:257
void mem2reg_as_needed_pass1(std::map< AstNode *, std::set< std::string >> &mem2reg_places, std::map< AstNode *, uint32_t > &mem2reg_flags, std::map< AstNode *, uint32_t > &proc_flags, uint32_t &status_flags)
Definition: simplify.cc:2202
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
static std::string idx(std::string str)
Definition: test_autotb.cc:57
RTLIL::Const const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:471
RTLIL::Const const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:230
void(* set_line_num)(int)
Definition: ast.cc:50
std::map< RTLIL::IdString, AstNode * > attributes
Definition: ast.h:152
void log_error(const char *format,...)
Definition: log.cc:204
bool bits_only_01()
Definition: ast.cc:733
AstNode * id2ast
Definition: ast.h:167
#define log_abort()
Definition: log.h:84
RTLIL::Const const_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:170
bool get_bool_attribute(RTLIL::IdString id)
Definition: ast.cc:166
RTLIL::Const const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:442
bool range_swapped
Definition: ast.h:158
RTLIL::Const const_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:165
RTLIL::Const const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:478
static std::string escape_id(std::string str)
Definition: rtlil.h:251
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool did_something
Definition: opt_const.cc:32
RTLIL::Const const_reduce_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:198
void cloneInto(AstNode *other)
Definition: ast.cc:220
RTLIL::Const const_reduce_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:208
double asReal(bool is_signed)
Definition: ast.cc:822
RTLIL::Const const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:310
int range_right
Definition: ast.h:159
RTLIL::Const const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:213
AstNodeType
Definition: ast.h:42
bool is_reg
Definition: ast.h:158
RTLIL::Const const_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:180
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
AstNode(AstNodeType type=AST_NONE, AstNode *child1=NULL, AstNode *child2=NULL)
Definition: ast.cc:181
std::string decode_string() const
Definition: rtlil.cc:131
#define log_assert(_assert_expr_)
Definition: log.h:85
RTLIL::Const const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:303
double realvalue
Definition: ast.h:161
RTLIL::Const const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:498
RTLIL::Const const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:296
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real=NULL)
Definition: genrtlil.cc:746
AstNode * current_block_child
Definition: ast.cc:61
RTLIL::Const const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:368
RTLIL::Const const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:413
AstNodeType type
Definition: ast.h:146
std::vector< int > multirange_dimensions
Definition: ast.h:164
AstNode * eval_const_function(AstNode *fcall)
Definition: simplify.cc:2541
RTLIL::Const const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:317
uint32_t integer
Definition: ast.h:160
int range_left
Definition: ast.h:159
void meminfo(int &mem_width, int &mem_size, int &addr_bits)
Definition: simplify.cc:2479
void expand_genblock(std::string index_var, std::string prefix, std::map< std::string, std::string > &name_map)
Definition: simplify.cc:2113
std::string current_filename
Definition: ast.cc:49
RTLIL::Const const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:241
AstNode * clone()
Definition: ast.cc:208
#define NULL
RTLIL::Const const_reduce_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:203
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
Definition: simplify.cc:50
RTLIL::Const const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:432
RTLIL::Const const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:485
std::string filename
Definition: ast.h:175
RTLIL::Const const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:357
AstNode * current_ast_mod
Definition: ast.cc:57
void log(const char *format,...)
Definition: log.cc:180
AstNode * readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr)
Definition: simplify.cc:2036
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
bool is_signed
Definition: ast.h:158
RTLIL::Const const_neg(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:570
RTLIL::Const const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:464
std::string str
Definition: ast.h:156
std::vector< AstNode * > children
Definition: ast.h:149
void replace_ids(const std::string &prefix, const std::map< std::string, std::string > &rules)
Definition: simplify.cc:2160
bool flag_mem2reg
Definition: ast.cc:56
std::vector< RTLIL::State > bits
Definition: ast.h:157
bool is_string
Definition: ast.h:158
int linenum
Definition: ast.h:176
uint64_t asInt(bool is_signed)
Definition: ast.cc:802
RTLIL::Const const_reduce_bool(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:225
int isConst()
Definition: ast.cc:793
bool basic_prep
Definition: ast.h:170
bool flag_nomem2reg
Definition: ast.cc:56
void delete_children()
Definition: ast.cc:231
RTLIL::Const const_pos(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:562
RTLIL::Const const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:453
void mem2reg_as_needed_pass2(std::set< AstNode * > &mem2reg_set, AstNode *mod, AstNode *block)
Definition: simplify.cc:2315
const char * log_id(RTLIL::IdString str)
Definition: log.cc:283
bool is_output
Definition: ast.h:158
YOSYS_NAMESPACE_BEGIN int autoidx
Definition: yosys.cc:51
RTLIL::Const const_not(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
Definition: calc.cc:125
int port_id
Definition: ast.h:159
bool asBool()
Definition: ast.cc:784
bool has_const_only_constructs(bool &recommend_const_eval)
Definition: simplify.cc:2495
bool is_input
Definition: ast.h:158

+ Here is the caller graph for this function:

Field Documentation

std::map<RTLIL::IdString, AstNode*> AST::AstNode::attributes

Definition at line 152 of file ast.h.

bool AST::AstNode::basic_prep

Definition at line 170 of file ast.h.

std::vector<RTLIL::State> AST::AstNode::bits

Definition at line 157 of file ast.h.

std::vector<AstNode*> AST::AstNode::children

Definition at line 149 of file ast.h.

std::string AST::AstNode::filename

Definition at line 175 of file ast.h.

AstNode* AST::AstNode::id2ast

Definition at line 167 of file ast.h.

uint32_t AST::AstNode::integer

Definition at line 160 of file ast.h.

bool AST::AstNode::is_input

Definition at line 158 of file ast.h.

bool AST::AstNode::is_output

Definition at line 158 of file ast.h.

bool AST::AstNode::is_reg

Definition at line 158 of file ast.h.

bool AST::AstNode::is_signed

Definition at line 158 of file ast.h.

bool AST::AstNode::is_string

Definition at line 158 of file ast.h.

int AST::AstNode::linenum

Definition at line 176 of file ast.h.

std::vector<int> AST::AstNode::multirange_dimensions

Definition at line 164 of file ast.h.

int AST::AstNode::port_id

Definition at line 159 of file ast.h.

int AST::AstNode::range_left

Definition at line 159 of file ast.h.

int AST::AstNode::range_right

Definition at line 159 of file ast.h.

bool AST::AstNode::range_swapped

Definition at line 158 of file ast.h.

bool AST::AstNode::range_valid

Definition at line 158 of file ast.h.

double AST::AstNode::realvalue

Definition at line 161 of file ast.h.

std::string AST::AstNode::str

Definition at line 156 of file ast.h.

AstNodeType AST::AstNode::type

Definition at line 146 of file ast.h.


The documentation for this struct was generated from the following files: