diff options
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/ast.cc | 82 | ||||
-rw-r--r-- | frontends/ast/ast.h | 9 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 27 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 25 |
4 files changed, 110 insertions, 33 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index d35ea4171..2c552ea22 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -46,11 +46,12 @@ namespace AST { // instanciate global variables (private API) namespace AST_INTERNAL { - bool flag_dump_ast, flag_dump_ast_diff, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg; + bool flag_dump_ast, flag_dump_ast_diff, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib; 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; + RTLIL::SigSpec ignoreThisSignalsInInitial; AstNode *current_top_block, *current_block, *current_block_child; AstModule *current_module; } @@ -122,6 +123,7 @@ std::string AST::type2str(AstNodeType type) X(AST_CELL) X(AST_PRIMITIVE) X(AST_ALWAYS) + X(AST_INITIAL) X(AST_BLOCK) X(AST_ASSIGN_EQ) X(AST_ASSIGN_LE) @@ -417,6 +419,14 @@ void AstNode::dumpVlog(FILE *f, std::string indent) } break; + case AST_INITIAL: + fprintf(f, "%s" "initial\n", indent.c_str()); + for (auto child : children) { + if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) + child->dumpVlog(f, indent + " "); + } + break; + case AST_POSEDGE: case AST_NEGEDGE: case AST_EDGE: @@ -679,10 +689,25 @@ static AstModule* process_module(AstNode *ast) 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; + } + ast->children.swap(new_children); + ast->attributes["\\placeholder"] = AstNode::mkconst_int(0, false, 0); + } + current_module = new AstModule; current_module->ast = NULL; current_module->name = ast->str; current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); + + 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", @@ -697,19 +722,30 @@ static AstModule* process_module(AstNode *ast) } for (size_t i = 0; i < ast->children.size(); i++) { AstNode *node = ast->children[i]; - if (node->type != AST_WIRE && node->type != AST_MEMORY) + if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL) node->genRTLIL(); } + 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(); + } + + ignoreThisSignalsInInitial = RTLIL::SigSpec(); + current_module->ast = ast_before_simplify; current_module->nolatches = flag_nolatches; current_module->nomem2reg = flag_nomem2reg; current_module->mem2reg = flag_mem2reg; + current_module->lib = flag_lib; 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_ast, bool dump_ast_diff, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg) +void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast, bool dump_ast_diff, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg, bool lib) { current_ast = ast; flag_dump_ast = dump_ast; @@ -718,6 +754,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast, bool dump_ flag_nolatches = nolatches; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; + flag_lib = lib; assert(current_ast->type == AST_DESIGN); for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) { @@ -747,8 +784,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin flag_nolatches = nolatches; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; + flag_lib = lib; 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); @@ -762,9 +801,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin continue; para_counter++; std::string para_id = child->str; - if (parameters.count(child->str) > 0) { + if (parameters.count(para_id) > 0) { log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str]))); rewrite_parameter: + para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); child->delete_children(); child->children.push_back(AstNode::mkconst_bits(parameters[para_id].bits, false)); hash_data.insert(hash_data.end(), child->str.begin(), child->str.end()); @@ -774,10 +814,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin parameters.erase(para_id); continue; } - char buf[100]; - snprintf(buf, 100, "$%d", para_counter); - if (parameters.count(buf) > 0) { - para_id = buf; + para_id = stringf("$%d", para_counter); + if (parameters.count(para_id) > 0) { log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); goto rewrite_parameter; } @@ -785,17 +823,26 @@ 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()); - 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; + 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); + char hexstring[41]; + sha1::toHexString(hash, hexstring); - std::string modname = "$paramod$" + std::string(hexstring) + "$" + name; + modname = "$paramod$" + std::string(hexstring) + name; + } + else + { + modname = "$paramod" + name + para_info; + } if (design->modules.count(modname) == 0) { new_ast->str = modname; @@ -821,6 +868,7 @@ void AstModule::update_auto_wires(std::map<RTLIL::IdString, int> auto_sizes) flag_nolatches = nolatches; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; + flag_lib = lib; use_internal_line_num(); for (auto it = auto_sizes.begin(); it != auto_sizes.end(); it++) { diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index d65851acd..acf10f9ad 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -103,6 +103,7 @@ namespace AST AST_CELL, AST_PRIMITIVE, AST_ALWAYS, + AST_INITIAL, AST_BLOCK, AST_ASSIGN_EQ, AST_ASSIGN_LE, @@ -189,13 +190,13 @@ namespace AST }; // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code - void process(RTLIL::Design *design, AstNode *ast, bool dump_ast = false, bool dump_ast_diff = false, bool dump_vlog = false, bool nolatches = false, bool nomem2reg = false, bool mem2reg = false); + void process(RTLIL::Design *design, AstNode *ast, bool dump_ast = false, bool dump_ast_diff = false, bool dump_vlog = false, bool nolatches = false, bool nomem2reg = false, bool mem2reg = false, bool lib = false); // parametric modules are supported directly by the AST library // therfore we need our own derivate of RTLIL::Module with overloaded virtual functions struct AstModule : RTLIL::Module { AstNode *ast; - bool nolatches, nomem2reg, mem2reg; + bool nolatches, nomem2reg, mem2reg, lib; virtual ~AstModule(); virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters); virtual void update_auto_wires(std::map<RTLIL::IdString, int> auto_sizes); @@ -217,10 +218,10 @@ namespace AST namespace AST_INTERNAL { // internal state variables - extern bool flag_dump_ast, flag_dump_ast_diff, flag_nolatches, flag_nomem2reg, flag_mem2reg; + extern bool flag_dump_ast, flag_dump_ast_diff, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib; extern AST::AstNode *current_ast, *current_ast_mod; extern std::map<std::string, AST::AstNode*> current_scope; - extern RTLIL::SigSpec *genRTLIL_subst_from, *genRTLIL_subst_to; + extern RTLIL::SigSpec *genRTLIL_subst_from, *genRTLIL_subst_to, ignoreThisSignalsInInitial; extern AST::AstNode *current_top_block, *current_block, *current_block_child; extern AST::AstModule *current_module; struct ProcessGenerator; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 0654db2df..cb57bbab7 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -183,7 +183,9 @@ struct AST_INTERNAL::ProcessGenerator { // input and output structures AstNode *always; + RTLIL::SigSpec skipSyncSignals; RTLIL::Process *proc; + const RTLIL::SigSpec &outputSignals; // This always points to the RTLIL::CaseRule beeing filled at the moment RTLIL::CaseRule *current_case; @@ -205,7 +207,7 @@ struct AST_INTERNAL::ProcessGenerator // map helps generating nice numbered names for all this temporary signals. std::map<RTLIL::Wire*, int> new_temp_count; - ProcessGenerator(AstNode *always) : always(always) + ProcessGenerator(AstNode *always, RTLIL::SigSpec skipSyncSignalsArg = RTLIL::SigSpec()) : always(always), skipSyncSignals(skipSyncSignalsArg), outputSignals(subst_lvalue_from) { // generate process and simple root case proc = new RTLIL::Process; @@ -310,6 +312,7 @@ struct AST_INTERNAL::ProcessGenerator case AST_COND: case AST_ALWAYS: + case AST_INITIAL: for (auto child : ast->children) if (child->type == AST_BLOCK) collect_lvalues(reg, child, type_eq, type_le, false); @@ -334,9 +337,9 @@ struct AST_INTERNAL::ProcessGenerator reg.sort_and_unify(); } - // remove all assignments to the given signal pattern in a case and all its children - // when the last statement in the code "a = 23; if (b) a = 42; a = 0;" is processed this - // function is acalled to clean up the first two assignments as they are overwritten by + // remove all assignments to the given signal pattern in a case and all its children. + // e.g. when the last statement in the code "a = 23; if (b) a = 42; a = 0;" is processed this + // function is called to clean up the first two assignments as they are overwritten by // the third assignment. void removeSignalFromCaseTree(RTLIL::SigSpec pattern, RTLIL::CaseRule *cs) { @@ -350,8 +353,10 @@ struct AST_INTERNAL::ProcessGenerator // add an assignment (aka "action") but split it up in chunks. this way huge assignments // are avoided and the generated $mux cells have a more "natural" size. - void addChunkActions(std::vector<RTLIL::SigSig> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool noSyncToUndef = false) + void addChunkActions(std::vector<RTLIL::SigSig> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool inSyncRule = false) { + if (inSyncRule) + lvalue.remove2(skipSyncSignals, &rvalue); assert(lvalue.width == rvalue.width); lvalue.optimize(); rvalue.optimize(); @@ -360,7 +365,7 @@ struct AST_INTERNAL::ProcessGenerator for (size_t i = 0; i < lvalue.chunks.size(); i++) { RTLIL::SigSpec lhs = lvalue.chunks[i]; RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue.chunks[i].width); - if (noSyncToUndef && lvalue.chunks[i].wire && lvalue.chunks[i].wire->attributes.count("\\nosync")) + if (inSyncRule && lvalue.chunks[i].wire && lvalue.chunks[i].wire->attributes.count("\\nosync")) rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.width); actions.push_back(RTLIL::SigSig(lhs, rhs)); offset += lhs.width; @@ -456,7 +461,7 @@ struct AST_INTERNAL::ProcessGenerator } else if (node->type == AST_BLOCK) { processAst(node); } else if (!generated_default_case) - current_case->compare.push_back(node->genWidthRTLIL(sw->signal.width)); + current_case->compare.push_back(node->genWidthRTLIL(sw->signal.width, &subst_rvalue_from, &subst_rvalue_to)); } sw->cases.push_back(current_case); current_case = backup_case; @@ -528,6 +533,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint) case AST_LOCALPARAM: case AST_GENVAR: case AST_GENFOR: + case AST_GENBLOCK: case AST_GENIF: break; @@ -1015,6 +1021,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint) case AST_ALWAYS: { AstNode *always = this->clone(); ProcessGenerator generator(always); + ignoreThisSignalsInInitial.append(generator.outputSignals); + delete always; + } break; + + case AST_INITIAL: { + AstNode *always = this->clone(); + ProcessGenerator generator(always, ignoreThisSignalsInInitial); delete always; } break; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 887b62f2c..bf0f9e63f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -182,6 +182,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage) break; if (type == AST_GENIF && i >= 1) break; + if (type == AST_GENBLOCK) + break; if (type == AST_PREFIX && i >= 1) break; while (did_something_here && i < children.size()) { @@ -194,7 +196,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage) current_block = this; current_block_child = children[i]; } - if (type == AST_ALWAYS && children[i]->type == AST_BLOCK) + if ((type == AST_ALWAYS || type == AST_INITIAL) && children[i]->type == AST_BLOCK) current_top_block = children[i]; did_something_here = children[i]->simplify(const_fold_here, at_zero, in_lvalue_here, stage); if (did_something_here) @@ -409,6 +411,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage) did_something = true; } + // simplify unconditional generate block + if (type == AST_GENBLOCK && children.size() != 0) + { + if (!str.empty()) { + std::map<std::string, std::string> name_map; + expand_genblock(std::string(), str + ".", name_map); + } + + for (size_t i = 0; i < children.size(); i++) + current_ast_mod->children.push_back(children[i]); + + children.clear(); + did_something = true; + } + // simplify generate-if blocks if (type == AST_GENIF && children.size() != 0) { @@ -434,7 +451,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage) if (!buf->str.empty()) { std::map<std::string, std::string> name_map; - buf->expand_genblock(std::string(), buf->str, name_map); + buf->expand_genblock(std::string(), buf->str + ".", name_map); } for (size_t i = 0; i < buf->children.size(); i++) @@ -877,10 +894,8 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma return; } - if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) { + if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) str = name_map[str]; - return; - } std::map<std::string, std::string> backup_name_map; |