mirror of https://github.com/YosysHQ/yosys.git
Added $assert cell
This commit is contained in:
parent
9a1eb45c75
commit
1e67099b77
|
@ -1276,6 +1276,38 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
}
|
}
|
||||||
break;
|
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)
|
// add entries to current_module->connections for assignments (outside of always blocks)
|
||||||
case AST_ASSIGN:
|
case AST_ASSIGN:
|
||||||
{
|
{
|
||||||
|
|
|
@ -966,6 +966,66 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
}
|
}
|
||||||
skip_dynamic_range_lvalue_expansion:;
|
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
|
// 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 &&
|
if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
|
||||||
children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
|
children[0]->type == AST_RANGE && children[0]->children.size() == 1) {
|
||||||
|
|
|
@ -96,6 +96,7 @@ struct CellTypes
|
||||||
cell_types.insert("$pmux");
|
cell_types.insert("$pmux");
|
||||||
cell_types.insert("$safe_pmux");
|
cell_types.insert("$safe_pmux");
|
||||||
cell_types.insert("$lut");
|
cell_types.insert("$lut");
|
||||||
|
cell_types.insert("$assert");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_internals_mem()
|
void setup_internals_mem()
|
||||||
|
|
|
@ -595,6 +595,13 @@ namespace {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cell->type == "$assert") {
|
||||||
|
port("\\A", 1);
|
||||||
|
port("\\EN", 1);
|
||||||
|
check_expected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cell->type == "$_INV_") { check_gate("AY"); return; }
|
if (cell->type == "$_INV_") { check_gate("AY"); return; }
|
||||||
if (cell->type == "$_AND_") { check_gate("ABY"); return; }
|
if (cell->type == "$_AND_") { check_gate("ABY"); return; }
|
||||||
if (cell->type == "$_OR_") { check_gate("ABY"); return; }
|
if (cell->type == "$_OR_") { check_gate("ABY"); return; }
|
||||||
|
|
|
@ -418,3 +418,7 @@ from the gate level logic network can be mapped to physical flip-flop cells from
|
||||||
pass. The combinatorial logic cells can be mapped to physical cells from a Liberty file via ABC \citeweblink{ABC}
|
pass. The combinatorial logic cells can be mapped to physical cells from a Liberty file via ABC \citeweblink{ABC}
|
||||||
using the {\tt abc} pass.
|
using the {\tt abc} pass.
|
||||||
|
|
||||||
|
\begin{fixme}
|
||||||
|
Add information about {\tt \$assert} cells.
|
||||||
|
\end{fixme}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ static void rmunused_module_cells(RTLIL::Module *module, bool verbose)
|
||||||
wire2driver.insert(sig, cell);
|
wire2driver.insert(sig, cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cell->type == "$memwr" || cell->get_bool_attribute("\\keep"))
|
if (cell->type == "$memwr" || cell->type == "$assert" || cell->get_bool_attribute("\\keep"))
|
||||||
queue.insert(cell);
|
queue.insert(cell);
|
||||||
unused.insert(cell);
|
unused.insert(cell);
|
||||||
}
|
}
|
||||||
|
|
|
@ -733,6 +733,21 @@ endmodule
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
module \$assert (A, EN);
|
||||||
|
|
||||||
|
input A, EN;
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
if (A !== 1'b1 && EN === 1'b1) begin
|
||||||
|
$display("Assertation failed!");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
|
||||||
module \$sr (SET, CLR, Q);
|
module \$sr (SET, CLR, Q);
|
||||||
|
|
||||||
parameter WIDTH = 0;
|
parameter WIDTH = 0;
|
||||||
|
|
Loading…
Reference in New Issue