diff options
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/ast.cc | 1 | ||||
-rw-r--r-- | frontends/ast/ast.h | 1 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 24 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 14 |
4 files changed, 39 insertions, 1 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 03fd272da..9520ae32c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -95,6 +95,7 @@ std::string AST::type2str(AstNodeType type) X(AST_TO_SIGNED) X(AST_TO_UNSIGNED) X(AST_SELFSZ) + X(AST_CAST_SIZE) X(AST_CONCAT) X(AST_REPLICATE) X(AST_BIT_NOT) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 46864a4e1..9a5aa15f9 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -76,6 +76,7 @@ namespace AST AST_TO_SIGNED, AST_TO_UNSIGNED, AST_SELFSZ, + AST_CAST_SIZE, AST_CONCAT, AST_REPLICATE, AST_BIT_NOT, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 9546558aa..e878d0dd2 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -814,6 +814,16 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint); break; + case AST_CAST_SIZE: + while (children.at(0)->simplify(true, false, false, 1, -1, false, false)) { } + if (children.at(0)->type != AST_CONSTANT) + log_file_error(filename, location.first_line, "Static cast with non constant expression!\n"); + children.at(1)->detectSignWidthWorker(width_hint, sign_hint); + width_hint = children.at(0)->bitsAsConst().as_int(); + if (width_hint <= 0) + log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n"); + break; + case AST_CONCAT: for (auto child : children) { sub_width_hint = 0; @@ -1289,6 +1299,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) return sig; } + // changing the size of signal can be done directly using RTLIL::SigSpec + case AST_CAST_SIZE: { + RTLIL::SigSpec size = children[0]->genRTLIL(); + RTLIL::SigSpec sig = children[1]->genRTLIL(); + if (!size.is_fully_const()) + log_file_error(filename, location.first_line, "Static cast with non constant expression!\n"); + int width = size.as_int(); + if (width <= 0) + log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n"); + sig.extend_u0(width, sign_hint); + is_signed = sign_hint; + return sig; + } + // concatenation of signals can be done directly using RTLIL::SigSpec case AST_CONCAT: { RTLIL::SigSpec sig; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55e7da0aa..c4df5c0a0 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -950,6 +950,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case AST_TO_SIGNED: case AST_TO_UNSIGNED: case AST_SELFSZ: + case AST_CAST_SIZE: case AST_CONCAT: case AST_REPLICATE: case AST_REDUCE_AND: @@ -1126,6 +1127,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, bool in_param_here = in_param; if (i == 0 && (type == AST_REPLICATE || type == AST_WIRE)) const_fold_here = true, in_param_here = true; + if (i == 0 && (type == AST_GENIF || type == AST_GENCASE)) + in_param_here = true; + if (i == 1 && (type == AST_FOR || type == AST_GENFOR)) + in_param_here = true; if (type == AST_PARAMETER || type == AST_LOCALPARAM) const_fold_here = true; if (i == 0 && (type == AST_ASSIGN || type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE)) @@ -1942,7 +1947,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, continue; buf = child->clone(); - while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + while (buf->simplify(true, false, false, stage, width_hint, sign_hint, true)) { } if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); @@ -3483,6 +3488,13 @@ replace_fcall_later:; } } break; + case AST_CAST_SIZE: + if (children.at(0)->type == AST_CONSTANT && children.at(1)->type == AST_CONSTANT) { + int width = children[0]->bitsAsConst().as_int(); + RTLIL::Const val = children[1]->bitsAsConst(width); + newNode = mkconst_bits(val.bits, children[1]->is_signed); + } + break; case AST_CONCAT: string_op = !children.empty(); for (auto it = children.begin(); it != children.end(); it++) { |