Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

systemverilog-plugin: fix handling large constants #465

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

kamilrakoczy
Copy link
Collaborator

@kamilrakoczy kamilrakoczy commented Mar 6, 2023

mkconst_int handles integers up to 32bits: https://github.com/YosysHQ/yosys/blob/master/frontends/ast/ast.cc#L754.
Whole constant can be stored in bits field. Before we were checking if value can be stored inside uint32_t, but size of const could still be larger than 32bits.

This PR moves handling of constants that are larger than 32bits to const2ast as well as fixes rename of module when parameter value is larger than 32bit.

yosys-systemverilog run: https://github.com/antmicro/yosys-systemverilog/actions/runs/4343198440

…nt is lower than 32bits

Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
…ger than 32bit

Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
Copy link
Collaborator

@mglb mglb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole situation with size in case vpiIntVal is so confusing it should be briefly described in a comment as a list of facts.
For example, in what situation can we expect size > 32 && size < 64? How does this situation differs from a situation when size == 64 (since there's a special case for this value)?
Please also add a test that covers all edge cases for vpiIntVal, i.e. sizes equal to: -1, 0, 1, 32, 33, 63, 64. I ask for a more detailed test here, because we already fixed (not sufficiently) this function before, and the thing the code has to do here is a bit confusing.

A test for module naming would be nice too.

systemverilog-plugin/UhdmAst.cc Show resolved Hide resolved
Comment on lines +1296 to +1299
if (size == -1) {
is_unsized = false;
size = 32;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

size has been set above to the result of vpi_get(vpiSize, obj_h);. In what situation is it equal to -1?
Please answer in a code comment.

Comment on lines +1296 to +1299
if (size == -1) {
is_unsized = false;
size = 32;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this if just below the size = vpi_get(vpiSize, obj_h); above?

Comment on lines +1306 to +1311
if (size > 32) {
const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
report_error("%.*s:%d: Constant with size: %d bits handled by mkconst_int that doesn't work with values larger than 32bits\n!",
(int)object->VpiFile().length(), object->VpiFile().data(), object->VpiLineNo(), size);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreachable code. There is a break above when size > 32.

Comment on lines 1287 to 1289
if (size == -1) {
size = vpi_get(vpiSize, obj_h);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Condition always true, size is not changed between initialization and this point.
To make it more visible, let's make size local to this case's scope.

is_unsized = false;
size = 32;
}
if (val.value.integer > std::numeric_limits<std::int32_t>::max() || size > 32) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add log_assert(size <= 64) above this. Or comment when this can be the case.

Comment on lines -1348 to +1355
auto size = vpi_get(vpiSize, obj_h);
size = vpi_get(vpiSize, obj_h);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make the previous size local as mentioned above, and keep this one local too.
And while at it: const int size = ... :)

Comment on lines 1276 to 1277
}
[[fallthrough]];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about case vpiUIntVal? Should it be left as is, or does it need a similar size check as vpiIntVal?

Comment on lines +1903 to +1933
} else if (node->children[0]->bits.size() > 32) {
std::string value = std::to_string(node->children[0]->bits.size()) + "'b";
for (const auto &bit : node->children[0]->bits) {
switch (bit) {
case RTLIL::State::S0:
value += "0";
break;
case RTLIL::State::S1:
value += "1";
break;
case RTLIL::State::Sx:
value += "x";
break;
case RTLIL::State::Sz:
value += "z";
break;
case RTLIL::State::Sa:
value += "a";
break;
case RTLIL::State::Sm:
value += "m";
break;
default:
report_error("Unhandled RTLIL State case!\n");
}
}
module_parameters += node->str + "=" + value;
} else {
module_parameters +=
node->str + "=" + std::to_string(node->children[0]->bits.size()) + "'d" + std::to_string(node->children[0]->integer);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it follow the way Yosys does it in serialize_param_value?

I think you can even replace this whole snippet (and a bit above and below) with AstNode::derived_module_name + AstNode::asParaConst.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know about this functions, I've extracted this change to separate PR: #466

current_node->children.push_back(node);
}
});
visit_range(obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log_assert(node); or if (node), depending which one is appropriate here.

@kamilrakoczy kamilrakoczy marked this pull request as draft March 13, 2023 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants