-
Notifications
You must be signed in to change notification settings - Fork 47
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1236,6 +1236,8 @@ AST::AstNode *UhdmAst::process_value(vpiHandle obj_h) | |
vpi_get_value(obj_h, &val); | ||
std::string strValType = "'"; | ||
bool is_signed = false; | ||
bool is_unsized = false; | ||
int size = -1; | ||
if (vpiHandle typespec_h = vpi_handle(vpiTypespec, obj_h)) { | ||
is_signed = vpi_get(vpiSigned, typespec_h); | ||
if (is_signed) { | ||
|
@@ -1274,36 +1276,41 @@ AST::AstNode *UhdmAst::process_value(vpiHandle obj_h) | |
} | ||
[[fallthrough]]; | ||
case vpiIntVal: { | ||
if (val.value.integer > std::numeric_limits<std::int32_t>::max()) { | ||
strValType = "'sd"; | ||
string str_value = std::to_string(val.value.integer); | ||
val.value.str = strdup(str_value.c_str()); | ||
break; | ||
} | ||
|
||
int size = -1; | ||
// Surelog sometimes report size as part of vpiTypespec (e.g. int_typespec) | ||
// if it is the case, we need to set size to the left_range of first packed range | ||
visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) { | ||
if (node && node->attributes.count(UhdmAst::packed_ranges()) && node->attributes[UhdmAst::packed_ranges()]->children.size() && | ||
if (node->attributes.count(UhdmAst::packed_ranges()) && node->attributes[UhdmAst::packed_ranges()]->children.size() && | ||
kamilrakoczy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
node->attributes[UhdmAst::packed_ranges()]->children[0]->children.size()) { | ||
size = node->attributes[UhdmAst::packed_ranges()]->children[0]->children[0]->integer + 1; | ||
} | ||
}); | ||
if (size == -1) { | ||
size = vpi_get(vpiSize, obj_h); | ||
} | ||
Comment on lines
1287
to
1289
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Condition always true, |
||
// Surelog by default returns 64 bit numbers and stardard says that they shall be at least 32bits | ||
// yosys is assuming that int/uint is 32 bit, so we are setting here correct size | ||
// NOTE: it *shouldn't* break on explicite 64 bit const values, as they *should* be handled | ||
// above by vpi*StrVal | ||
if (size == 64) { | ||
// we know that value can be stored in 32bit integer | ||
// and yosys only supports 32 bits | ||
size = 32; | ||
is_signed = true; | ||
} | ||
auto c = AST::AstNode::mkconst_int(val.format == vpiUIntVal ? val.value.uint : val.value.integer, is_signed, size > 0 ? size : 32); | ||
if (size == 0 || size == -1) | ||
c->is_unsized = true; | ||
is_signed = true; | ||
if (size == -1) { | ||
is_unsized = false; | ||
size = 32; | ||
} | ||
Comment on lines
+1296
to
+1299
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+1296
to
+1299
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we move this |
||
if (val.value.integer > std::numeric_limits<std::int32_t>::max() || size > 32) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add |
||
strValType = "'sd"; | ||
string str_value = std::to_string(val.value.integer); | ||
val.value.str = strdup(str_value.c_str()); | ||
break; | ||
} | ||
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); | ||
} | ||
Comment on lines
+1306
to
+1311
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unreachable code. There is a break above when |
||
auto c = AST::AstNode::mkconst_int(val.format == vpiUIntVal ? val.value.uint : val.value.integer, is_signed, size); | ||
c->is_unsized = is_unsized; | ||
return c; | ||
} | ||
case vpiRealVal: | ||
|
@@ -1345,7 +1352,7 @@ AST::AstNode *UhdmAst::process_value(vpiHandle obj_h) | |
if (std::strchr(val.value.str, '\'')) { | ||
return ::systemverilog_plugin::const2ast(val.value.str, caseType, false); | ||
} else { | ||
auto size = vpi_get(vpiSize, obj_h); | ||
size = vpi_get(vpiSize, obj_h); | ||
Comment on lines
-1348
to
+1355
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
if (size == 0) { | ||
auto c = AST::AstNode::mkconst_int(atoi(val.value.str), true, 32); | ||
c->is_unsized = true; | ||
|
@@ -1891,11 +1898,39 @@ void UhdmAst::process_module() | |
} | ||
} | ||
if (shared.top_nodes.count(type)) { | ||
if (!node->children[0]->str.empty()) | ||
if (!node->children[0]->str.empty()) { | ||
module_parameters += node->str + "=" + node->children[0]->str; | ||
else | ||
} 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"); | ||
kamilrakoczy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
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); | ||
} | ||
Comment on lines
+1903
to
+1933
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't it follow the way Yosys does it in I think you can even replace this whole snippet (and a bit above and below) with There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
} | ||
delete node; | ||
} | ||
|
@@ -4016,13 +4051,14 @@ void UhdmAst::process_string_typespec() | |
|
||
void UhdmAst::process_bit_typespec() | ||
{ | ||
std::vector<AST::AstNode *> packed_ranges; // comes before wire name | ||
current_node = make_ast_node(AST::AST_WIRE); | ||
visit_range(obj_h, [&](AST::AstNode *node) { | ||
if (node) { | ||
current_node->children.push_back(node); | ||
} | ||
}); | ||
visit_range(obj_h, [&](AST::AstNode *node) { packed_ranges.push_back(node); }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if (packed_ranges.empty()) { | ||
packed_ranges.push_back(make_range(0, 0)); | ||
} | ||
current_node->is_signed = vpi_get(vpiSigned, obj_h); | ||
add_multirange_wire(current_node, packed_ranges, {}); | ||
} | ||
|
||
void UhdmAst::process_repeat() | ||
|
There was a problem hiding this comment.
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 asvpiIntVal
?