mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-27 02:45:52 +00:00
Sign extend port connections where necessary
- Signed cell outputs are sign extended when bound to larger wires - Signed connections are sign extended when bound to larger cell inputs - Sign extension is performed in hierarchy and flatten phases - genrtlil indirects signed constants through signed wires - Other phases producing RTLIL may need to be updated to preserve signedness information - Resolves #1418 - Resolves #2265
This commit is contained in:
parent
40e35993af
commit
0d8e5d965f
5 changed files with 132 additions and 5 deletions
|
@ -106,6 +106,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width
|
|||
|
||||
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
|
||||
wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
|
||||
wire->is_signed = that->is_signed;
|
||||
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
|
@ -1721,8 +1722,29 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
}
|
||||
if (child->type == AST_ARGUMENT) {
|
||||
RTLIL::SigSpec sig;
|
||||
if (child->children.size() > 0)
|
||||
sig = child->children[0]->genRTLIL();
|
||||
if (child->children.size() > 0) {
|
||||
AstNode *arg = child->children[0];
|
||||
int local_width_hint = -1;
|
||||
bool local_sign_hint = false;
|
||||
// don't inadvertently attempt to detect the width of interfaces
|
||||
if (arg->type != AST_IDENTIFIER || !arg->id2ast || arg->id2ast->type != AST_CELL)
|
||||
arg->detectSignWidth(local_width_hint, local_sign_hint);
|
||||
sig = arg->genRTLIL(local_width_hint, local_sign_hint);
|
||||
log_assert(local_sign_hint == arg->is_signed);
|
||||
if (sig.is_wire()) {
|
||||
// if the resulting SigSpec is a wire, its
|
||||
// signedness should match that of the AstNode
|
||||
log_assert(arg->is_signed == sig.as_wire()->is_signed);
|
||||
} else if (arg->is_signed) {
|
||||
// non-trivial signed nodes are indirected through
|
||||
// signed wires to enable sign extension
|
||||
RTLIL::IdString wire_name = NEW_ID;
|
||||
RTLIL::Wire *wire = current_module->addWire(wire_name, arg->bits.size());
|
||||
wire->is_signed = true;
|
||||
current_module->connect(wire, sig);
|
||||
sig = wire;
|
||||
}
|
||||
}
|
||||
if (child->str.size() == 0) {
|
||||
char buf[100];
|
||||
snprintf(buf, 100, "$%d", ++port_counter);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue