Skip to content

Commit afb72ad

Browse files
committed
wip: check cell
1 parent f26495e commit afb72ad

File tree

6 files changed

+150
-128
lines changed

6 files changed

+150
-128
lines changed

frontends/ast/genrtlil.cc

+104-35
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,10 @@ struct AST_INTERNAL::ProcessGenerator
316316
// Buffer for generating the init action
317317
RTLIL::SigSpec init_lvalue, init_rvalue;
318318

319-
// The most recently assigned $print cell \PRIORITY.
320-
int last_print_priority;
319+
// The most recently assigned $print or $check cell \PRIORITY.
320+
int last_effect_priority;
321321

322-
ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg), last_print_priority(0)
322+
ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg), last_effect_priority(0)
323323
{
324324
// rewrite lookahead references
325325
LookaheadRewriter la_rewriter(always);
@@ -703,8 +703,10 @@ struct AST_INTERNAL::ProcessGenerator
703703
std::stringstream sstr;
704704
sstr << ast->str << "$" << ast->filename << ":" << ast->location.first_line << "$" << (autoidx++);
705705

706-
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($print));
707-
set_src_attr(cell, ast);
706+
Wire *en = current_module->addWire(sstr.str() + "_EN", 1);
707+
set_src_attr(en, ast);
708+
proc->root_case.actions.push_back(SigSig(en, false));
709+
current_case->actions.push_back(SigSig(en, true));
708710

709711
RTLIL::SigSpec triggers;
710712
RTLIL::Const polarity;
@@ -717,18 +719,15 @@ struct AST_INTERNAL::ProcessGenerator
717719
polarity.bits.push_back(RTLIL::S0);
718720
}
719721
}
720-
cell->parameters[ID::TRG_WIDTH] = triggers.size();
721-
cell->parameters[ID::TRG_ENABLE] = !triggers.empty();
722-
cell->parameters[ID::TRG_POLARITY] = polarity;
723-
cell->parameters[ID::PRIORITY] = --last_print_priority;
724-
cell->setPort(ID::TRG, triggers);
725722

726-
Wire *wire = current_module->addWire(sstr.str() + "_EN", 1);
727-
set_src_attr(wire, ast);
728-
cell->setPort(ID::EN, wire);
729-
730-
proc->root_case.actions.push_back(SigSig(wire, false));
731-
current_case->actions.push_back(SigSig(wire, true));
723+
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($print));
724+
set_src_attr(cell, ast);
725+
cell->setParam(ID::TRG_WIDTH, triggers.size());
726+
cell->setParam(ID::TRG_ENABLE, !triggers.empty());
727+
cell->setParam(ID::TRG_POLARITY, polarity);
728+
cell->setParam(ID::PRIORITY, --last_effect_priority);
729+
cell->setPort(ID::TRG, triggers);
730+
cell->setPort(ID::EN, en);
732731

733732
int default_base = 10;
734733
if (ast->str.back() == 'b')
@@ -776,6 +775,74 @@ struct AST_INTERNAL::ProcessGenerator
776775
}
777776
break;
778777

778+
// generate $check cells
779+
case AST_ASSERT:
780+
case AST_ASSUME:
781+
case AST_LIVE:
782+
case AST_FAIR:
783+
case AST_COVER:
784+
{
785+
std::string flavor, desc;
786+
if (ast->type == AST_ASSERT) { flavor = "assert"; desc = "assert ()"; }
787+
if (ast->type == AST_ASSUME) { flavor = "assume"; desc = "assume ()"; }
788+
if (ast->type == AST_LIVE) { flavor = "live"; desc = "assert (eventually)"; }
789+
if (ast->type == AST_FAIR) { flavor = "fair"; desc = "assume (eventually)"; }
790+
if (ast->type == AST_COVER) { flavor = "cover"; desc = "cover ()"; }
791+
792+
std::stringstream sstr;
793+
sstr << "$" << flavor << ast->str << "$" << ast->filename << ":" << ast->location.first_line << "$" << (autoidx++);
794+
795+
RTLIL::SigSpec check = ast->children[0]->genWidthRTLIL(-1, false, &subst_rvalue_map.stdmap());
796+
if (GetSize(check) != 1)
797+
check = current_module->ReduceBool(NEW_ID, check);
798+
799+
RTLIL::SigSpec en;
800+
RTLIL::SigSpec triggers;
801+
RTLIL::Const polarity;
802+
if (always->type == AST_ALWAYS) {
803+
Wire *enWire = current_module->addWire(sstr.str() + "_EN", 1);
804+
set_src_attr(enWire, ast);
805+
en = enWire;
806+
807+
proc->root_case.actions.push_back(SigSig(enWire, false));
808+
current_case->actions.push_back(SigSig(enWire, true));
809+
810+
for (auto sync : proc->syncs) {
811+
if (sync->type == RTLIL::STp) {
812+
triggers.append(sync->signal);
813+
polarity.bits.push_back(RTLIL::S1);
814+
} else if (sync->type == RTLIL::STn) {
815+
triggers.append(sync->signal);
816+
polarity.bits.push_back(RTLIL::S0);
817+
}
818+
}
819+
} else {
820+
en = current_module->Initstate(NEW_ID);
821+
}
822+
823+
RTLIL::IdString cellname = ast->str.empty() ? sstr.str() : ast->str;
824+
RTLIL::Cell *cell = current_module->addCell(cellname, ID($check));
825+
set_src_attr(cell, ast);
826+
for (auto &attr : ast->attributes) {
827+
if (attr.second->type != AST_CONSTANT)
828+
log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
829+
cell->attributes[attr.first] = attr.second->asAttrConst();
830+
}
831+
cell->setParam(ID(FLAVOR), flavor);
832+
cell->setParam(ID::TRG_WIDTH, triggers.size());
833+
cell->setParam(ID::TRG_ENABLE, !triggers.empty());
834+
cell->setParam(ID::TRG_POLARITY, polarity);
835+
cell->setParam(ID::PRIORITY, --last_effect_priority);
836+
cell->setPort(ID::TRG, triggers);
837+
cell->setPort(ID::EN, en);
838+
cell->setPort(ID::A, check);
839+
840+
Fmt fmt = {};
841+
fmt.append_string(stringf("%s failed at %s:%d", desc.c_str(), RTLIL::encode_filename(ast->filename).c_str(), ast->location.first_line));
842+
fmt.emit_rtlil(cell);
843+
break;
844+
}
845+
779846
case AST_NONE:
780847
case AST_FOR:
781848
break;
@@ -1945,48 +2012,50 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
19452012
}
19462013
break;
19472014

1948-
// generate $assert cells
2015+
// generate $check cells
19492016
case AST_ASSERT:
19502017
case AST_ASSUME:
19512018
case AST_LIVE:
19522019
case AST_FAIR:
19532020
case AST_COVER:
19542021
{
1955-
IdString celltype;
1956-
if (type == AST_ASSERT) celltype = ID($assert);
1957-
if (type == AST_ASSUME) celltype = ID($assume);
1958-
if (type == AST_LIVE) celltype = ID($live);
1959-
if (type == AST_FAIR) celltype = ID($fair);
1960-
if (type == AST_COVER) celltype = ID($cover);
1961-
1962-
log_assert(children.size() == 2);
2022+
std::string flavor, desc;
2023+
if (type == AST_ASSERT) { flavor = "assert"; desc = "assert property ()"; }
2024+
if (type == AST_ASSUME) { flavor = "assume"; desc = "assume property ()"; }
2025+
if (type == AST_LIVE) { flavor = "live"; desc = "assert property (eventually)"; }
2026+
if (type == AST_FAIR) { flavor = "fair"; desc = "assume property (eventually)"; }
2027+
if (type == AST_COVER) { flavor = "cover"; desc = "cover property ()"; }
19632028

19642029
RTLIL::SigSpec check = children[0]->genRTLIL();
19652030
if (GetSize(check) != 1)
19662031
check = current_module->ReduceBool(NEW_ID, check);
19672032

1968-
RTLIL::SigSpec en = children[1]->genRTLIL();
1969-
if (GetSize(en) != 1)
1970-
en = current_module->ReduceBool(NEW_ID, en);
1971-
19722033
IdString cellname;
19732034
if (str.empty())
1974-
cellname = stringf("%s$%s:%d$%d", celltype.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
2035+
cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
19752036
else
19762037
cellname = str;
1977-
19782038
check_unique_id(current_module, cellname, this, "procedural assertion");
1979-
RTLIL::Cell *cell = current_module->addCell(cellname, celltype);
1980-
set_src_attr(cell, this);
19812039

2040+
RTLIL::Cell *cell = current_module->addCell(cellname, ID($check));
2041+
set_src_attr(cell, this);
19822042
for (auto &attr : attributes) {
19832043
if (attr.second->type != AST_CONSTANT)
19842044
input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
19852045
cell->attributes[attr.first] = attr.second->asAttrConst();
19862046
}
1987-
2047+
cell->setParam(ID(FLAVOR), flavor);
2048+
cell->parameters[ID::TRG_WIDTH] = 0;
2049+
cell->parameters[ID::TRG_ENABLE] = 0;
2050+
cell->parameters[ID::TRG_POLARITY] = 0;
2051+
cell->parameters[ID::PRIORITY] = 0;
2052+
cell->setPort(ID::TRG, RTLIL::SigSpec());
2053+
cell->setPort(ID::EN, RTLIL::S1);
19882054
cell->setPort(ID::A, check);
1989-
cell->setPort(ID::EN, en);
2055+
2056+
Fmt fmt = {};
2057+
fmt.append_string(stringf("%s failed at %s:%d", desc.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line));
2058+
fmt.emit_rtlil(cell);
19902059
}
19912060
break;
19922061

frontends/ast/simplify.cc

+1-92
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ AstNode *AstNode::clone_at_zero()
781781
pointee->type != AST_MEMORY)
782782
break;
783783

784-
YS_FALLTHROUGH;
784+
YS_FALLTHROUGH
785785
case AST_MEMRD:
786786
detectSignWidth(width_hint, sign_hint);
787787
return mkconst_int(0, sign_hint, width_hint);
@@ -3064,97 +3064,6 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
30643064
}
30653065
skip_dynamic_range_lvalue_expansion:;
30663066

3067-
if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && current_block != NULL)
3068-
{
3069-
std::stringstream sstr;
3070-
sstr << "$formal$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
3071-
std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
3072-
3073-
AstNode *wire_check = new AstNode(AST_WIRE);
3074-
wire_check->str = id_check;
3075-
wire_check->was_checked = true;
3076-
current_ast_mod->children.push_back(wire_check);
3077-
current_scope[wire_check->str] = wire_check;
3078-
while (wire_check->simplify(true, 1, -1, false)) { }
3079-
3080-
AstNode *wire_en = new AstNode(AST_WIRE);
3081-
wire_en->str = id_en;
3082-
wire_en->was_checked = true;
3083-
current_ast_mod->children.push_back(wire_en);
3084-
if (current_always_clocked) {
3085-
current_ast_mod->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1)))));
3086-
current_ast_mod->children.back()->children[0]->children[0]->children[0]->str = id_en;
3087-
current_ast_mod->children.back()->children[0]->children[0]->children[0]->was_checked = true;
3088-
}
3089-
current_scope[wire_en->str] = wire_en;
3090-
while (wire_en->simplify(true, 1, -1, false)) { }
3091-
3092-
AstNode *check_defval;
3093-
if (type == AST_LIVE || type == AST_FAIR) {
3094-
check_defval = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
3095-
} else {
3096-
std::vector<RTLIL::State> x_bit;
3097-
x_bit.push_back(RTLIL::State::Sx);
3098-
check_defval = mkconst_bits(x_bit, false);
3099-
}
3100-
3101-
AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), check_defval);
3102-
assign_check->children[0]->str = id_check;
3103-
assign_check->children[0]->was_checked = true;
3104-
3105-
AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1));
3106-
assign_en->children[0]->str = id_en;
3107-
assign_en->children[0]->was_checked = true;
3108-
3109-
AstNode *default_signals = new AstNode(AST_BLOCK);
3110-
default_signals->children.push_back(assign_check);
3111-
default_signals->children.push_back(assign_en);
3112-
current_top_block->children.insert(current_top_block->children.begin(), default_signals);
3113-
3114-
if (type == AST_LIVE || type == AST_FAIR) {
3115-
assign_check = nullptr;
3116-
} else {
3117-
assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
3118-
assign_check->children[0]->str = id_check;
3119-
assign_check->children[0]->was_checked = true;
3120-
assign_check->fixup_hierarchy_flags();
3121-
}
3122-
3123-
if (current_always == nullptr || current_always->type != AST_INITIAL) {
3124-
assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
3125-
} else {
3126-
assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_FCALL));
3127-
assign_en->children[1]->str = "\\$initstate";
3128-
}
3129-
assign_en->children[0]->str = id_en;
3130-
assign_en->children[0]->was_checked = true;
3131-
assign_en->fixup_hierarchy_flags();
3132-
3133-
newNode = new AstNode(AST_BLOCK);
3134-
if (assign_check != nullptr)
3135-
newNode->children.push_back(assign_check);
3136-
newNode->children.push_back(assign_en);
3137-
3138-
AstNode *assertnode = new AstNode(type);
3139-
assertnode->location = location;
3140-
assertnode->str = str;
3141-
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
3142-
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
3143-
assertnode->children[0]->str = id_check;
3144-
assertnode->children[1]->str = id_en;
3145-
assertnode->attributes.swap(attributes);
3146-
current_ast_mod->children.push_back(assertnode);
3147-
3148-
goto apply_newNode;
3149-
}
3150-
3151-
if (stage > 1 && (type == AST_ASSERT || type == AST_ASSUME || type == AST_LIVE || type == AST_FAIR || type == AST_COVER) && children.size() == 1)
3152-
{
3153-
children.push_back(mkconst_int(1, false, 1));
3154-
fixup_hierarchy_flags();
3155-
did_something = true;
3156-
}
3157-
31583067
// found right-hand side identifier for memory -> replace with memory read port
31593068
if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
31603069
children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) {

kernel/celltypes.h

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct CellTypes
102102
setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool<RTLIL::IdString>(), true);
103103
setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool<RTLIL::IdString>(), true);
104104
setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
105+
setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
105106
setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y});
106107
setup_type(ID($get_tag), {ID::A}, {ID::Y});
107108
setup_type(ID($overwrite_tag), {ID::A, ID::SET, ID::CLR}, pool<RTLIL::IdString>());

kernel/rtlil.cc

+22
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,12 @@ namespace {
10681068
error(__LINE__);
10691069
}
10701070

1071+
std::string param_string(const RTLIL::IdString &name)
1072+
{
1073+
param(name);
1074+
return cell->parameters.at(name).decode_string();
1075+
}
1076+
10711077
void port(const RTLIL::IdString& name, int width)
10721078
{
10731079
auto it = cell->connections_.find(name);
@@ -1747,6 +1753,22 @@ namespace {
17471753
return;
17481754
}
17491755

1756+
if (cell->type == ID($check)) {
1757+
std::string flavor = param_string(ID(FLAVOR));
1758+
if (!(flavor == "assert" || flavor == "assume" || flavor == "live" || flavor == "fair" || flavor == "cover"))
1759+
error(__LINE__);
1760+
param(ID(FORMAT));
1761+
param_bool(ID::TRG_ENABLE);
1762+
param(ID::TRG_POLARITY);
1763+
param(ID::PRIORITY);
1764+
port(ID::A, 1);
1765+
port(ID::EN, 1);
1766+
port(ID::TRG, param(ID::TRG_WIDTH));
1767+
port(ID::ARGS, param(ID::ARGS_WIDTH));
1768+
check_expected();
1769+
return;
1770+
}
1771+
17501772
if (cell->type == ID($_BUF_)) { port(ID::A,1); port(ID::Y,1); check_expected(); return; }
17511773
if (cell->type == ID($_NOT_)) { port(ID::A,1); port(ID::Y,1); check_expected(); return; }
17521774
if (cell->type == ID($_AND_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; }

passes/opt/opt_clean.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ struct keep_cache_t
8282
if (!ignore_specify && cell->type.in(ID($specify2), ID($specify3), ID($specrule)))
8383
return true;
8484

85-
if (cell->type == ID($print))
85+
if (cell->type == ID($print) || cell->type == ID($check))
8686
return true;
8787

8888
if (cell->has_keep_attr())

techlibs/common/simlib.v

+21
Original file line numberDiff line numberDiff line change
@@ -1817,6 +1817,27 @@ input [ARGS_WIDTH-1:0] ARGS;
18171817

18181818
endmodule
18191819

1820+
// --------------------------------------------------------
1821+
1822+
module \$check (A, EN, TRG, ARGS);
1823+
1824+
parameter FLAVOR = "";
1825+
1826+
parameter FORMAT = "";
1827+
parameter ARGS_WIDTH = 0;
1828+
parameter PRIORITY = 0;
1829+
parameter TRG_ENABLE = 1;
1830+
1831+
parameter TRG_WIDTH = 0;
1832+
parameter TRG_POLARITY = 0;
1833+
1834+
input A;
1835+
input EN;
1836+
input [TRG_WIDTH-1:0] TRG;
1837+
input [ARGS_WIDTH-1:0] ARGS;
1838+
1839+
endmodule
1840+
18201841
// --------------------------------------------------------
18211842
`ifndef SIMLIB_NOSR
18221843

0 commit comments

Comments
 (0)