X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=frontends%2Fast%2Fast.cc;h=fd27240090bd448a72c06903359cc69b11a16ca3;hb=97583ab7295499b1b78ac7035e6e0b37d7b87734;hp=10c7fc85bf8212809885240b1cfe5ba22825dd30;hpb=4a4a3fc3377243d85100b829a0f6b785376cce9f;p=yosys.git diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 10c7fc85b..fd2724009 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -2,11 +2,11 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * + * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -26,13 +26,11 @@ * */ -#include "kernel/log.h" +#include "kernel/yosys.h" #include "libs/sha1/sha1.h" #include "ast.h" -#include -#include -#include +YOSYS_NAMESPACE_BEGIN using namespace AST; using namespace AST_INTERNAL; @@ -46,14 +44,15 @@ namespace AST { // instanciate global variables (private API) namespace AST_INTERNAL { - bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt; + bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit; + bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map current_scope; - RTLIL::SigSpec *genRTLIL_subst_from = NULL; - RTLIL::SigSpec *genRTLIL_subst_to = NULL; + const dict *genRTLIL_subst_ptr = NULL; RTLIL::SigSpec ignoreThisSignalsInInitial; - AstNode *current_top_block, *current_block, *current_block_child; + AstNode *current_always, *current_top_block, *current_block, *current_block_child; AstModule *current_module; + bool current_always_clocked; } // convert node types to string @@ -67,6 +66,7 @@ std::string AST::type2str(AstNodeType type) X(AST_MODULE) X(AST_TASK) X(AST_FUNCTION) + X(AST_DPI_FUNCTION) X(AST_WIRE) X(AST_MEMORY) X(AST_AUTOWIRE) @@ -76,11 +76,16 @@ std::string AST::type2str(AstNodeType type) X(AST_PARASET) X(AST_ARGUMENT) X(AST_RANGE) + X(AST_MULTIRANGE) X(AST_CONSTANT) + X(AST_REALVALUE) X(AST_CELLTYPE) X(AST_IDENTIFIER) X(AST_PREFIX) + X(AST_ASSERT) + X(AST_ASSUME) X(AST_FCALL) + X(AST_TO_BITS) X(AST_TO_SIGNED) X(AST_TO_UNSIGNED) X(AST_CONCAT) @@ -103,6 +108,8 @@ std::string AST::type2str(AstNodeType type) X(AST_LE) X(AST_EQ) X(AST_NE) + X(AST_EQX) + X(AST_NEX) X(AST_GE) X(AST_GT) X(AST_ADD) @@ -119,10 +126,12 @@ std::string AST::type2str(AstNodeType type) X(AST_TERNARY) X(AST_MEMRD) X(AST_MEMWR) + X(AST_MEMINIT) X(AST_TCALL) X(AST_ASSIGN) X(AST_CELL) X(AST_PRIMITIVE) + X(AST_CELLARRAY) X(AST_ALWAYS) X(AST_INITIAL) X(AST_BLOCK) @@ -130,8 +139,12 @@ std::string AST::type2str(AstNodeType type) X(AST_ASSIGN_LE) X(AST_CASE) X(AST_COND) + X(AST_CONDX) + X(AST_CONDZ) X(AST_DEFAULT) X(AST_FOR) + X(AST_WHILE) + X(AST_REPEAT) X(AST_GENVAR) X(AST_GENFOR) X(AST_GENIF) @@ -140,6 +153,7 @@ std::string AST::type2str(AstNodeType type) X(AST_POSEDGE) X(AST_NEGEDGE) X(AST_EDGE) + X(AST_PACKAGE) #undef X default: log_abort(); @@ -162,8 +176,12 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) // create new node (AstNode constructor) // (the optional child arguments make it easier to create AST trees) -AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2) +AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3) { + static unsigned int hashidx_count = 123456789; + hashidx_count = mkhash_xorshift(hashidx_count); + hashidx_ = hashidx_count; + this->type = type; filename = current_filename; linenum = get_line_num(); @@ -171,17 +189,23 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2) is_output = false; is_reg = false; is_signed = false; + is_string = false; range_valid = false; + range_swapped = false; port_id = 0; range_left = -1; range_right = 0; integer = 0; + realvalue = 0; id2ast = NULL; + basic_prep = false; if (child1) children.push_back(child1); if (child2) children.push_back(child2); + if (child3) + children.push_back(child3); } // create a (deep recursive) copy of a node @@ -237,6 +261,12 @@ void AstNode::dumpAst(FILE *f, std::string indent) std::string type_name = type2str(type); fprintf(f, "%s%s <%s:%d>", indent.c_str(), type_name.c_str(), filename.c_str(), linenum); + + if (id2ast) + fprintf(f, " [%p -> %p]", this, id2ast); + else + fprintf(f, " [%p]", this); + if (!str.empty()) fprintf(f, " str='%s'", str.c_str()); if (!bits.empty()) { @@ -246,7 +276,7 @@ void AstNode::dumpAst(FILE *f, std::string indent) bits[i-1] == RTLIL::S1 ? '1' : bits[i-1] == RTLIL::Sx ? 'x' : bits[i-1] == RTLIL::Sz ? 'z' : '?'); - fprintf(f, "'(%zd)", bits.size()); + fprintf(f, "'(%d)", GetSize(bits)); } if (is_input) fprintf(f, " input"); @@ -259,9 +289,17 @@ void AstNode::dumpAst(FILE *f, std::string indent) if (port_id > 0) fprintf(f, " port=%d", port_id); if (range_valid || range_left != -1 || range_right != 0) - fprintf(f, " range=[%d:%d]%s", range_left, range_right, range_valid ? "" : "!"); + fprintf(f, " %srange=[%d:%d]%s", range_swapped ? "swapped_" : "", range_left, range_right, range_valid ? "" : "!"); if (integer != 0) fprintf(f, " int=%u", (int)integer); + if (realvalue != 0) + fprintf(f, " real=%e", realvalue); + if (!multirange_dimensions.empty()) { + fprintf(f, " multirange=["); + for (int v : multirange_dimensions) + fprintf(f, " %d", v); + fprintf(f, " ]"); + } fprintf(f, "\n"); for (auto &it : attributes) { @@ -271,6 +309,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) for (size_t i = 0; i < children.size(); i++) children[i]->dumpAst(f, indent + " "); + + fflush(f); } // helper function for AstNode::dumpVlog() @@ -289,7 +329,7 @@ static std::string id2vl(std::string txt) return txt; } -// dump AST node as verilog pseudo-code +// dump AST node as Verilog pseudo-code void AstNode::dumpVlog(FILE *f, std::string indent) { bool first = true; @@ -303,7 +343,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) } for (auto &it : attributes) { - fprintf(f, "%s" "(* %s = ", indent.c_str(), id2vl(it.first).c_str()); + fprintf(f, "%s" "(* %s = ", indent.c_str(), id2vl(it.first.str()).c_str()); it.second->dumpVlog(f, ""); fprintf(f, " *)%s", indent.empty() ? "" : "\n"); } @@ -395,16 +435,15 @@ void AstNode::dumpVlog(FILE *f, std::string indent) break; case AST_ALWAYS: - fprintf(f, "%s" "always @(", indent.c_str()); + fprintf(f, "%s" "always @", indent.c_str()); for (auto child : children) { if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) continue; - if (!first) - fprintf(f, ", "); + fprintf(f, first ? "(" : ", "); child->dumpVlog(f, ""); first = false; } - fprintf(f, ")\n"); + fprintf(f, first ? "*\n" : ")\n"); for (auto child : children) { if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) child->dumpVlog(f, indent + " "); @@ -442,7 +481,11 @@ void AstNode::dumpVlog(FILE *f, std::string indent) else if (bits.size() == 32) fprintf(f, "%d", RTLIL::Const(bits).as_int()); else - fprintf(f, "%zd'b %s", bits.size(), RTLIL::Const(bits).as_string().c_str()); + fprintf(f, "%d'b %s", GetSize(bits), RTLIL::Const(bits).as_string().c_str()); + break; + + case AST_REALVALUE: + fprintf(f, "%e", realvalue); break; case AST_BLOCK: @@ -457,7 +500,12 @@ void AstNode::dumpVlog(FILE *f, std::string indent) break; case AST_CASE: - fprintf(f, "%s" "case (", indent.c_str()); + if (!children.empty() && children[0]->type == AST_CONDX) + fprintf(f, "%s" "casex (", indent.c_str()); + else if (!children.empty() && children[0]->type == AST_CONDZ) + fprintf(f, "%s" "casez (", indent.c_str()); + else + fprintf(f, "%s" "case (", indent.c_str()); children[0]->dumpVlog(f, ""); fprintf(f, ")\n"); for (size_t i = 1; i < children.size(); i++) { @@ -468,6 +516,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) break; case AST_COND: + case AST_CONDX: + case AST_CONDZ: for (auto child : children) { if (child->type == AST_BLOCK) { fprintf(f, ":\n"); @@ -484,6 +534,14 @@ void AstNode::dumpVlog(FILE *f, std::string indent) } break; + case AST_ASSIGN: + fprintf(f, "%sassign ", indent.c_str()); + children[0]->dumpVlog(f, ""); + fprintf(f, " = "); + children[1]->dumpVlog(f, ""); + fprintf(f, ";\n"); + break; + case AST_ASSIGN_EQ: case AST_ASSIGN_LE: fprintf(f, "%s", indent.c_str()); @@ -511,7 +569,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) children[1]->dumpVlog(f, ""); fprintf(f, "}}"); break; - + if (0) { case AST_BIT_NOT: txt = "~"; } if (0) { case AST_REDUCE_AND: txt = "&"; } if (0) { case AST_REDUCE_OR: txt = "|"; } @@ -538,6 +596,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) if (0) { case AST_LE: txt = "<="; } if (0) { case AST_EQ: txt = "=="; } if (0) { case AST_NE: txt = "!="; } + if (0) { case AST_EQX: txt = "==="; } + if (0) { case AST_NEX: txt = "!=="; } if (0) { case AST_GE: txt = ">="; } if (0) { case AST_GT: txt = ">"; } if (0) { case AST_ADD: txt = "+"; } @@ -570,6 +630,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) fprintf(f, "%s" "/** %s **/%s", indent.c_str(), type_name.c_str(), indent.empty() ? "" : "\n"); // dumpAst(f, indent, NULL); } + + fflush(f); } // check if two AST nodes are identical @@ -591,8 +653,12 @@ bool AstNode::operator==(const AstNode &other) const return false; if (is_signed != other.is_signed) return false; + if (is_string != other.is_string) + return false; if (range_valid != other.range_valid) return false; + if (range_swapped != other.range_swapped) + return false; if (port_id != other.port_id) return false; if (range_left != other.range_left) @@ -649,7 +715,7 @@ AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signe for (size_t i = 0; i < 32; i++) { if (i < node->bits.size()) node->integer |= (node->bits[i] == RTLIL::S1) << i; - else if (is_signed) + else if (is_signed && !node->bits.empty()) node->integer |= (node->bits.back() == RTLIL::S1) << i; } node->range_valid = true; @@ -658,6 +724,42 @@ AstNode *AstNode::mkconst_bits(const std::vector &v, bool is_signe return node; } +// create an AST node for a constant (using a string in bit vector form as value) +AstNode *AstNode::mkconst_str(const std::vector &v) +{ + AstNode *node = mkconst_str(RTLIL::Const(v).decode_string()); + while (GetSize(node->bits) < GetSize(v)) + node->bits.push_back(RTLIL::State::S0); + log_assert(node->bits == v); + return node; +} + +// create an AST node for a constant (using a string as value) +AstNode *AstNode::mkconst_str(const std::string &str) +{ + std::vector data; + data.reserve(str.size() * 8); + for (size_t i = 0; i < str.size(); i++) { + unsigned char ch = str[str.size() - i - 1]; + for (int j = 0; j < 8; j++) { + data.push_back((ch & 1) ? RTLIL::S1 : RTLIL::S0); + ch = ch >> 1; + } + } + AstNode *node = AstNode::mkconst_bits(data, false); + node->is_string = true; + node->str = str; + return node; +} + +bool AstNode::bits_only_01() +{ + for (auto bit : bits) + if (bit != RTLIL::S0 && bit != RTLIL::S1) + return false; + return true; +} + RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed) { std::vector bits = this->bits; @@ -685,7 +787,7 @@ RTLIL::Const AstNode::asAttrConst() RTLIL::Const val; val.bits = bits; - if (!str.empty()) { + if (is_string) { val.flags |= RTLIL::CONST_FLAG_STRING; log_assert(val.decode_string() == str); } @@ -710,11 +812,94 @@ bool AstNode::asBool() return false; } +int AstNode::isConst() +{ + if (type == AST_CONSTANT) + return 1; + if (type == AST_REALVALUE) + return 2; + return 0; +} + +uint64_t AstNode::asInt(bool is_signed) +{ + if (type == AST_CONSTANT) + { + RTLIL::Const v = bitsAsConst(64, is_signed); + uint64_t ret = 0; + + for (int i = 0; i < 64; i++) + if (v.bits.at(i) == RTLIL::State::S1) + ret |= uint64_t(1) << i; + + return ret; + } + + if (type == AST_REALVALUE) + return uint64_t(realvalue); + + log_abort(); +} + +double AstNode::asReal(bool is_signed) +{ + if (type == AST_CONSTANT) + { + RTLIL::Const val(bits); + + bool is_negative = is_signed && !val.bits.empty() && val.bits.back() == RTLIL::State::S1; + if (is_negative) + val = const_neg(val, val, false, false, val.bits.size()); + + double v = 0; + for (size_t i = 0; i < val.bits.size(); i++) + // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in + // the net or the variable shall be treated as zero upon conversion. + if (val.bits.at(i) == RTLIL::State::S1) + v += exp2(i); + if (is_negative) + v *= -1; + + return v; + } + + if (type == AST_REALVALUE) + return realvalue; + + log_abort(); +} + +RTLIL::Const AstNode::realAsConst(int width) +{ + double v = round(realvalue); + RTLIL::Const result; +#ifdef EMSCRIPTEN + if (!isfinite(v)) { +#else + if (!std::isfinite(v)) { +#endif + result.bits = std::vector(width, RTLIL::State::Sx); + } else { + bool is_negative = v < 0; + if (is_negative) + v *= -1; + for (int i = 0; i < width; i++, v /= 2) + result.bits.push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0); + if (is_negative) + result = const_neg(result, result, false, false, result.bits.size()); + } + return result; +} + // create a new AstModule from an AST_MODULE AST node -static AstModule* process_module(AstNode *ast) +static AstModule* process_module(AstNode *ast, bool defer) { - assert(ast->type == AST_MODULE); - log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str()); + log_assert(ast->type == AST_MODULE); + + if (defer) + log("Storing AST representation for module `%s'.\n", ast->str.c_str()); + else + log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str()); current_module = new AstModule; current_module->ast = NULL; @@ -725,99 +910,146 @@ static AstModule* process_module(AstNode *ast) AstNode *ast_before_simplify = ast->clone(); if (flag_dump_ast1) { - log("Dumping verilog AST before simplification:\n"); + log("Dumping Verilog AST before simplification:\n"); ast->dumpAst(NULL, " "); log("--- END OF AST DUMP ---\n"); } - while (ast->simplify(!flag_noopt, false, false, 0, -1, false)) { } + if (!defer) + { + while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { } - if (flag_dump_ast2) { - log("Dumping verilog AST after simplification:\n"); - ast->dumpAst(NULL, " "); - log("--- END OF AST DUMP ---\n"); - } + if (flag_dump_ast2) { + log("Dumping Verilog AST after simplification:\n"); + ast->dumpAst(NULL, " "); + log("--- END OF AST DUMP ---\n"); + } - if (flag_dump_vlog) { - log("Dumping verilog AST (as requested by dump_vlog option):\n"); - ast->dumpVlog(NULL, " "); - log("--- END OF AST DUMP ---\n"); - } + if (flag_dump_vlog) { + log("Dumping Verilog AST (as requested by dump_vlog option):\n"); + ast->dumpVlog(NULL, " "); + log("--- END OF AST DUMP ---\n"); + } - if (flag_lib) { - std::vector new_children; - for (auto child : ast->children) { - if (child->type == AST_WIRE && (child->is_input || child->is_output)) - new_children.push_back(child); - else - delete child; + if (flag_lib) { + std::vector new_children; + for (auto child : ast->children) { + if (child->type == AST_WIRE && (child->is_input || child->is_output)) + new_children.push_back(child); + else + delete child; + } + ast->children.swap(new_children); + ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); } - ast->children.swap(new_children); - ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); - } - ignoreThisSignalsInInitial = RTLIL::SigSpec(); + ignoreThisSignalsInInitial = RTLIL::SigSpec(); - for (auto &attr : ast->attributes) { - if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), ast->filename.c_str(), ast->linenum); - current_module->attributes[attr.first] = attr.second->asAttrConst(); - } - for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; - if (node->type == AST_WIRE || node->type == AST_MEMORY) - node->genRTLIL(); - } - for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; - if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL) - node->genRTLIL(); - } + for (auto &attr : ast->attributes) { + if (attr.second->type != AST_CONSTANT) + log_error("Attribute `%s' with non-constant value at %s:%d!\n", + attr.first.c_str(), ast->filename.c_str(), ast->linenum); + current_module->attributes[attr.first] = attr.second->asAttrConst(); + } + for (size_t i = 0; i < ast->children.size(); i++) { + AstNode *node = ast->children[i]; + if (node->type == AST_WIRE || node->type == AST_MEMORY) + node->genRTLIL(); + } + for (size_t i = 0; i < ast->children.size(); i++) { + AstNode *node = ast->children[i]; + if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL) + node->genRTLIL(); + } - ignoreThisSignalsInInitial.sort_and_unify(); + ignoreThisSignalsInInitial.sort_and_unify(); - for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; - if (node->type == AST_INITIAL) - node->genRTLIL(); - } + for (size_t i = 0; i < ast->children.size(); i++) { + AstNode *node = ast->children[i]; + if (node->type == AST_INITIAL) + node->genRTLIL(); + } - ignoreThisSignalsInInitial = RTLIL::SigSpec(); + ignoreThisSignalsInInitial = RTLIL::SigSpec(); + } current_module->ast = ast_before_simplify; current_module->nolatches = flag_nolatches; + current_module->nomeminit = flag_nomeminit; current_module->nomem2reg = flag_nomem2reg; current_module->mem2reg = flag_mem2reg; current_module->lib = flag_lib; current_module->noopt = flag_noopt; + current_module->icells = flag_icells; + current_module->autowire = flag_autowire; + current_module->fixup_ports(); + + if (flag_dump_rtlil) { + log("Dumping generated RTLIL:\n"); + log_module(current_module); + log("--- END OF RTLIL DUMP ---\n"); + } + return current_module; } // create AstModule instances for all modules in the AST tree and add them to 'design' -void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool ignore_redef) +void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool dump_rtlil, + bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire) { current_ast = ast; flag_dump_ast1 = dump_ast1; flag_dump_ast2 = dump_ast2; flag_dump_vlog = dump_vlog; + flag_dump_rtlil = dump_rtlil; flag_nolatches = nolatches; + flag_nomeminit = nomeminit; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; flag_lib = lib; flag_noopt = noopt; + flag_icells = icells; + flag_autowire = autowire; + + std::vector global_decls; - assert(current_ast->type == AST_DESIGN); - for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) { - if (design->modules.count((*it)->str) != 0) { - if (!ignore_redef) - log_error("Re-definition of module `%s' at %s:%d!\n", + log_assert(current_ast->type == AST_DESIGN); + for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) + { + if ((*it)->type == AST_MODULE) + { + for (auto n : global_decls) + (*it)->children.push_back(n->clone()); + + for (auto n : design->verilog_packages){ + for (auto o : n->children) { + AstNode *cloned_node = o->clone(); + cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1); + (*it)->children.push_back(cloned_node); + } + } + + if (flag_icells && (*it)->str.substr(0, 2) == "\\$") + (*it)->str = (*it)->str.substr(1); + + if (defer) + (*it)->str = "$abstract" + (*it)->str; + + if (design->has((*it)->str)) { + if (!ignore_redef) + log_error("Re-definition of module `%s' at %s:%d!\n", + (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); + log("Ignoring re-definition of module `%s' at %s:%d!\n", (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); - log_error("Ignoring re-definition of module `%s' at %s:%d!\n", - (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); - continue; + continue; + } + + design->add(process_module(*it, defer)); } - design->modules[(*it)->str] = process_module(*it); + else if ((*it)->type == AST_PACKAGE) + design->verilog_packages.push_back((*it)->clone()); + else + global_decls.push_back(*it); } } @@ -829,29 +1061,34 @@ AstModule::~AstModule() } // create a new parametric module (when needed) and return the name of the generated module -RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map parameters) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters) { - log_header("Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", name.c_str()); + std::string stripped_name = name.str(); + + if (stripped_name.substr(0, 9) == "$abstract") + stripped_name = stripped_name.substr(9); + + log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str()); current_ast = NULL; flag_dump_ast1 = false; flag_dump_ast2 = false; flag_dump_vlog = false; flag_nolatches = nolatches; + flag_nomeminit = nomeminit; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; flag_lib = lib; flag_noopt = noopt; + flag_icells = icells; + flag_autowire = autowire; use_internal_line_num(); std::string para_info; - std::vector hash_data; - hash_data.insert(hash_data.end(), name.begin(), name.end()); - hash_data.push_back(0); - AstNode *new_ast = ast->clone(); int para_counter = 0; + int orig_parameters_n = parameters.size(); for (auto it = new_ast->children.begin(); it != new_ast->children.end(); it++) { AstNode *child = *it; if (child->type != AST_PARAMETER) @@ -864,10 +1101,6 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::mapstr.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); delete child->children.at(0); child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0); - hash_data.insert(hash_data.end(), child->str.begin(), child->str.end()); - hash_data.push_back(0); - hash_data.insert(hash_data.end(), parameters[para_id].bits.begin(), parameters[para_id].bits.end()); - hash_data.push_back(0xff); parameters.erase(para_id); continue; } @@ -878,33 +1111,21 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map 0) - log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters.begin()->first.c_str(), name.c_str()); + log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters.begin()->first.c_str(), stripped_name.c_str()); std::string modname; - if (para_info.size() > 60) - { - unsigned char hash[20]; - unsigned char *hash_data2 = new unsigned char[hash_data.size()]; - for (size_t i = 0; i < hash_data.size(); i++) - hash_data2[i] = hash_data[i]; - sha1::calc(hash_data2, hash_data.size(), hash); - delete[] hash_data2; - - char hexstring[41]; - sha1::toHexString(hash, hexstring); - - modname = "$paramod$" + std::string(hexstring) + name; - } + if (orig_parameters_n == 0) + modname = stripped_name; + else if (para_info.size() > 60) + modname = "$paramod$" + sha1(para_info) + stripped_name; else - { - modname = "$paramod" + name + para_info; - } + modname = "$paramod" + stripped_name + para_info; - if (design->modules.count(modname) == 0) { + if (!design->has(modname)) { new_ast->str = modname; - design->modules[modname] = process_module(new_ast); - design->modules[modname]->check(); + design->add(process_module(new_ast, false)); + design->module(modname)->check(); } else { log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); } @@ -916,14 +1137,18 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::mapname = name; cloneInto(new_mod); new_mod->ast = ast->clone(); new_mod->nolatches = nolatches; + new_mod->nomeminit = nomeminit; new_mod->nomem2reg = nomem2reg; new_mod->mem2reg = mem2reg; new_mod->lib = lib; new_mod->noopt = noopt; + new_mod->icells = icells; + new_mod->autowire = autowire; return new_mod; } @@ -946,3 +1171,5 @@ void AST::use_internal_line_num() get_line_num = &internal_get_line_num; } +YOSYS_NAMESPACE_END +