aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/ast')
-rw-r--r--frontends/ast/ast.cc82
-rw-r--r--frontends/ast/ast.h9
-rw-r--r--frontends/ast/genrtlil.cc27
-rw-r--r--frontends/ast/simplify.cc25
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;