diff options
Diffstat (limited to 'frontends/ast/ast.cc')
-rw-r--r-- | frontends/ast/ast.cc | 323 |
1 files changed, 229 insertions, 94 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 96608ae37..1e43875ae 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -32,7 +32,9 @@ #include <sstream> #include <stdarg.h> -#include <assert.h> +#include <math.h> + +YOSYS_NAMESPACE_BEGIN using namespace AST; using namespace AST_INTERNAL; @@ -46,11 +48,10 @@ 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, flag_icells; + bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map<std::string, AstNode*> current_scope; - RTLIL::SigSpec *genRTLIL_subst_from = NULL; - RTLIL::SigSpec *genRTLIL_subst_to = NULL; + const std::map<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL; RTLIL::SigSpec ignoreThisSignalsInInitial; AstNode *current_top_block, *current_block, *current_block_child; AstModule *current_module; @@ -67,6 +68,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,7 +78,9 @@ 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) @@ -127,6 +131,7 @@ std::string AST::type2str(AstNodeType type) X(AST_ASSIGN) X(AST_CELL) X(AST_PRIMITIVE) + X(AST_CELLARRAY) X(AST_ALWAYS) X(AST_INITIAL) X(AST_BLOCK) @@ -136,6 +141,8 @@ std::string AST::type2str(AstNodeType type) X(AST_COND) X(AST_DEFAULT) X(AST_FOR) + X(AST_WHILE) + X(AST_REPEAT) X(AST_GENVAR) X(AST_GENFOR) X(AST_GENIF) @@ -177,10 +184,12 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2) 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; @@ -243,6 +252,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()) { @@ -265,9 +280,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) { @@ -309,7 +332,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"); } @@ -451,6 +474,10 @@ void AstNode::dumpVlog(FILE *f, std::string indent) fprintf(f, "%zd'b %s", bits.size(), RTLIL::Const(bits).as_string().c_str()); break; + case AST_REALVALUE: + fprintf(f, "%e", realvalue); + break; + case AST_BLOCK: if (children.size() == 1) { children[0]->dumpVlog(f, indent); @@ -603,6 +630,8 @@ bool AstNode::operator==(const AstNode &other) const 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) @@ -694,6 +723,14 @@ AstNode *AstNode::mkconst_str(const std::string &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<RTLIL::State> bits = this->bits; @@ -746,11 +783,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 realvalue; + + log_abort(); +} + +double AstNode::asReal(bool is_signed) +{ + if (type == AST_CONSTANT) + { + RTLIL::Const val(bits); + + bool is_negative = is_signed && 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<RTLIL::State>(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; @@ -766,60 +886,63 @@ static AstModule* process_module(AstNode *ast) 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<AstNode*> 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<AstNode*> 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; @@ -828,11 +951,13 @@ static AstModule* process_module(AstNode *ast) current_module->lib = flag_lib; current_module->noopt = flag_noopt; current_module->icells = flag_icells; + current_module->autowire = flag_autowire; + current_module->fixup_ports(); 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 icells, bool ignore_redef) +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 icells, bool ignore_redef, bool defer, bool autowire) { current_ast = ast; flag_dump_ast1 = dump_ast1; @@ -844,18 +969,37 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump flag_lib = lib; flag_noopt = noopt; flag_icells = icells; + flag_autowire = autowire; + + std::vector<AstNode*> 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()); + + 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 + global_decls.push_back(*it); } } @@ -869,7 +1013,12 @@ 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<RTLIL::IdString, RTLIL::Const> 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("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; @@ -881,16 +1030,14 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin flag_lib = lib; flag_noopt = noopt; flag_icells = icells; + flag_autowire = autowire; use_internal_line_num(); std::string para_info; - std::vector<unsigned char> 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) @@ -903,10 +1050,6 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin para_info += stringf("%s=%s", child->str.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; } @@ -917,33 +1060,21 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin } } if (parameters.size() > 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()); } @@ -955,6 +1086,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin RTLIL::Module *AstModule::clone() const { AstModule *new_mod = new AstModule; + new_mod->name = name; cloneInto(new_mod); new_mod->ast = ast->clone(); @@ -964,6 +1096,7 @@ RTLIL::Module *AstModule::clone() const new_mod->lib = lib; new_mod->noopt = noopt; new_mod->icells = icells; + new_mod->autowire = autowire; return new_mod; } @@ -986,3 +1119,5 @@ void AST::use_internal_line_num() get_line_num = &internal_get_line_num; } +YOSYS_NAMESPACE_END + |