3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-27 02:45:52 +00:00

Added $assert cell

This commit is contained in:
Clifford Wolf 2014-01-19 14:03:40 +01:00
parent 9a1eb45c75
commit 1e67099b77
7 changed files with 120 additions and 1 deletions

View file

@ -1276,6 +1276,38 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
break;
// generate $assert cells
case AST_ASSERT:
{
log_assert(children.size() == 2);
RTLIL::SigSpec check = children[0]->genRTLIL();
log_assert(check.width == 1);
RTLIL::SigSpec en = children[1]->genRTLIL();
log_assert(en.width == 1);
std::stringstream sstr;
sstr << "$assert$" << filename << ":" << linenum << "$" << (RTLIL::autoidx++);
RTLIL::Cell *cell = new RTLIL::Cell;
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
cell->name = sstr.str();
cell->type = "$assert";
current_module->cells[cell->name] = cell;
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
log_error("Attribute `%s' with non-constant value at %s:%d!\n",
attr.first.c_str(), filename.c_str(), linenum);
cell->attributes[attr.first] = attr.second->asAttrConst();
}
cell->connections["\\A"] = check;
cell->connections["\\EN"] = en;
}
break;
// add entries to current_module->connections for assignments (outside of always blocks)
case AST_ASSIGN:
{

View file

@ -966,6 +966,66 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
skip_dynamic_range_lvalue_expansion:;
if (stage > 1 && type == AST_ASSERT && current_block != NULL)
{
std::stringstream sstr;
sstr << "$assert$" << filename << ":" << linenum << "$" << (RTLIL::autoidx++);
std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
AstNode *wire_check = new AstNode(AST_WIRE);
wire_check->str = id_check;
current_ast_mod->children.push_back(wire_check);
current_scope[wire_check->str] = wire_check;
while (wire_check->simplify(true, false, false, 1, -1, false)) { }
AstNode *wire_en = new AstNode(AST_WIRE);
wire_en->str = id_en;
current_ast_mod->children.push_back(wire_en);
current_scope[wire_en->str] = wire_en;
while (wire_en->simplify(true, false, false, 1, -1, false)) { }
std::vector<RTLIL::State> x_bit;
x_bit.push_back(RTLIL::State::Sx);
AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false));
assign_check->children[0]->str = id_check;
AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1));
assign_en->children[0]->str = id_en;
AstNode *default_signals = new AstNode(AST_BLOCK);
default_signals->children.push_back(assign_check);
default_signals->children.push_back(assign_en);
current_top_block->children.insert(current_top_block->children.begin(), default_signals);
assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
assign_check->children[0]->str = id_check;
assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
assign_en->children[0]->str = id_en;
newNode = new AstNode(AST_BLOCK);
newNode->children.push_back(assign_check);
newNode->children.push_back(assign_en);
AstNode *assertnode = new AstNode(AST_ASSERT);
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
assertnode->children[0]->str = id_check;
assertnode->children[1]->str = id_en;
assertnode->attributes.swap(attributes);
current_ast_mod->children.push_back(assertnode);
goto apply_newNode;
}
if (stage > 1 && type == AST_ASSERT && children.size() == 1)
{
children[0] = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
children.push_back(mkconst_int(1, false, 1));
did_something = true;
}
// found right-hand side identifier for memory -> replace with memory read port
if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
children[0]->type == AST_RANGE && children[0]->children.size() == 1) {