case AST_ASSIGN_LE:
{
RTLIL::SigSpec unmapped_lvalue = ast->children[0]->genRTLIL(), lvalue = unmapped_lvalue;
- RTLIL::SigSpec rvalue = ast->children[1]->genWidthRTLIL(lvalue.size(), &subst_rvalue_map.stdmap());
+ RTLIL::SigSpec rvalue = ast->children[1]->genWidthRTLIL(lvalue.size(), true, &subst_rvalue_map.stdmap());
pool<SigBit> lvalue_sigbits;
for (int i = 0; i < GetSize(lvalue); i++) {
case AST_CASE:
{
+ int width_hint;
+ bool sign_hint;
+ ast->detectSignWidth(width_hint, sign_hint);
+
RTLIL::SwitchRule *sw = new RTLIL::SwitchRule;
set_src_attr(sw, ast);
- sw->signal = ast->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
+ sw->signal = ast->children[0]->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap());
current_case->switches.push_back(sw);
for (auto &attr : ast->attributes) {
else if (node->type == AST_BLOCK)
processAst(node);
else
- current_case->compare.push_back(node->genWidthRTLIL(sw->signal.size(), &subst_rvalue_map.stdmap()));
+ current_case->compare.push_back(node->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap()));
}
if (default_case != current_case)
sw->cases.push_back(current_case);
RTLIL::MemWriteAction action;
set_src_attr(&action, child);
action.memid = memid;
- action.address = child->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
- action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, &subst_rvalue_map.stdmap());
- action.enable = child->children[2]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
+ action.address = child->children[0]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap());
+ action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, true, &subst_rvalue_map.stdmap());
+ action.enable = child->children[2]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap());
RTLIL::Const orig_priority_mask = child->children[4]->bitsAsConst();
RTLIL::Const priority_mask = RTLIL::Const(0, cur_idx);
for (int i = 0; i < portid; i++) {
width_hint = max(width_hint, this_width);
break;
+ case AST_CASE:
+ {
+ // This detects the _overall_ sign and width to be used for comparing
+ // the case expression with the case item expressions. The case
+ // expression and case item expressions are extended to the maximum
+ // width among them, and are only interpreted as signed if all of them
+ // are signed.
+ width_hint = -1;
+ sign_hint = true;
+ auto visit_case_expr = [&width_hint, &sign_hint] (AstNode *node) {
+ int sub_width_hint = -1;
+ bool sub_sign_hint = true;
+ node->detectSignWidth(sub_width_hint, sub_sign_hint);
+ width_hint = max(width_hint, sub_width_hint);
+ sign_hint &= sub_sign_hint;
+ };
+ visit_case_expr(children[0]);
+ for (size_t i = 1; i < children.size(); i++) {
+ AstNode *child = children[i];
+ for (AstNode *v : child->children)
+ if (v->type != AST_DEFAULT && v->type != AST_BLOCK)
+ visit_case_expr(v);
+ }
+ break;
+ }
+
case AST_FCALL:
if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") {
if (GetSize(children) == 1) {
SigSpec addr_sig = children[0]->genRTLIL();
cell->setPort(ID::ADDR, addr_sig);
- cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words));
+ cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words, true));
cell->parameters[ID::MEMID] = RTLIL::Const(str);
cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
case AST_ASSIGN:
{
RTLIL::SigSpec left = children[0]->genRTLIL();
- RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size());
+ RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size(), true);
if (left.has_const()) {
RTLIL::SigSpec new_left, new_right;
for (int i = 0; i < GetSize(left); i++)
// this is a wrapper for AstNode::genRTLIL() when a specific signal width is requested and/or
// signals must be substituted before being used as input values (used by ProcessGenerator)
// note that this is using some global variables to communicate this special settings to AstNode::genRTLIL().
-RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr)
+RTLIL::SigSpec AstNode::genWidthRTLIL(int width, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr)
{
const dict<RTLIL::SigBit, RTLIL::SigBit> *backup_subst_ptr = genRTLIL_subst_ptr;
if (new_subst_ptr)
genRTLIL_subst_ptr = new_subst_ptr;
- bool sign_hint = true;
+ bool sign_hint = sgn;
int width_hint = width;
detectSignWidthWorker(width_hint, sign_hint);
RTLIL::SigSpec sig = genRTLIL(width_hint, sign_hint);
if (const_fold && type == AST_CASE)
{
+ int width_hint;
+ bool sign_hint;
+ detectSignWidth(width_hint, sign_hint);
while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) {
+ RTLIL::Const case_expr = children[0]->bitsAsConst(width_hint, sign_hint);
std::vector<AstNode*> new_children;
new_children.push_back(children[0]);
for (int i = 1; i < GetSize(children); i++) {
continue;
while (v->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
if (v->type == AST_CONSTANT && v->bits_only_01()) {
- if (v->bits == children[0]->bits) {
+ RTLIL::Const case_item_expr = v->bitsAsConst(width_hint, sign_hint);
+ RTLIL::Const match = const_eq(case_expr, case_item_expr, sign_hint, sign_hint, 1);
+ log_assert(match.bits.size() == 1);
+ if (match.bits.front() == RTLIL::State::S1) {
while (i+1 < GetSize(children))
delete children[++i];
goto keep_const_cond;