mirror of https://github.com/YosysHQ/yosys.git
parent
e9effd58d2
commit
8bdc019730
|
@ -199,7 +199,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
|
||||||
|
|
||||||
// create new node (AstNode constructor)
|
// create new node (AstNode constructor)
|
||||||
// (the optional child arguments make it easier to create AST trees)
|
// (the optional child arguments make it easier to create AST trees)
|
||||||
AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3)
|
AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3, AstNode *child4)
|
||||||
{
|
{
|
||||||
static unsigned int hashidx_count = 123456789;
|
static unsigned int hashidx_count = 123456789;
|
||||||
hashidx_count = mkhash_xorshift(hashidx_count);
|
hashidx_count = mkhash_xorshift(hashidx_count);
|
||||||
|
@ -236,6 +236,8 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
|
||||||
children.push_back(child2);
|
children.push_back(child2);
|
||||||
if (child3)
|
if (child3)
|
||||||
children.push_back(child3);
|
children.push_back(child3);
|
||||||
|
if (child4)
|
||||||
|
children.push_back(child4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a (deep recursive) copy of a node
|
// create a (deep recursive) copy of a node
|
||||||
|
|
|
@ -221,7 +221,7 @@ namespace AST
|
||||||
AstSrcLocType location;
|
AstSrcLocType location;
|
||||||
|
|
||||||
// creating and deleting nodes
|
// creating and deleting nodes
|
||||||
AstNode(AstNodeType type = AST_NONE, AstNode *child1 = NULL, AstNode *child2 = NULL, AstNode *child3 = NULL);
|
AstNode(AstNodeType type = AST_NONE, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr);
|
||||||
AstNode *clone() const;
|
AstNode *clone() const;
|
||||||
void cloneInto(AstNode *other) const;
|
void cloneInto(AstNode *other) const;
|
||||||
void delete_children();
|
void delete_children();
|
||||||
|
|
|
@ -1720,21 +1720,24 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << "$meminit$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
|
sstr << "$meminit$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
|
||||||
|
|
||||||
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($meminit));
|
SigSpec en_sig = children[2]->genRTLIL();
|
||||||
|
|
||||||
|
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($meminit_v2));
|
||||||
set_src_attr(cell, this);
|
set_src_attr(cell, this);
|
||||||
|
|
||||||
int mem_width, mem_size, addr_bits;
|
int mem_width, mem_size, addr_bits;
|
||||||
id2ast->meminfo(mem_width, mem_size, addr_bits);
|
id2ast->meminfo(mem_width, mem_size, addr_bits);
|
||||||
|
|
||||||
if (children[2]->type != AST_CONSTANT)
|
if (children[3]->type != AST_CONSTANT)
|
||||||
log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n");
|
log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n");
|
||||||
int num_words = int(children[2]->asInt(false));
|
int num_words = int(children[3]->asInt(false));
|
||||||
cell->parameters[ID::WORDS] = RTLIL::Const(num_words);
|
cell->parameters[ID::WORDS] = RTLIL::Const(num_words);
|
||||||
|
|
||||||
SigSpec addr_sig = children[0]->genRTLIL();
|
SigSpec addr_sig = children[0]->genRTLIL();
|
||||||
|
|
||||||
cell->setPort(ID::ADDR, addr_sig);
|
cell->setPort(ID::ADDR, addr_sig);
|
||||||
cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words, true));
|
cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words, true));
|
||||||
|
cell->setPort(ID::EN, en_sig);
|
||||||
|
|
||||||
cell->parameters[ID::MEMID] = RTLIL::Const(str);
|
cell->parameters[ID::MEMID] = RTLIL::Const(str);
|
||||||
cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
|
cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
|
||||||
|
|
|
@ -2648,25 +2648,20 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
node_data->str = id_data;
|
node_data->str = id_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *node_en = nullptr;
|
AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
|
||||||
if (current_always->type == AST_INITIAL) {
|
wire_en->str = id_en;
|
||||||
node_en = AstNode::mkconst_int(1, false);
|
wire_en->was_checked = true;
|
||||||
} else {
|
current_ast_mod->children.push_back(wire_en);
|
||||||
AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
|
current_scope[wire_en->str] = wire_en;
|
||||||
wire_en->str = id_en;
|
while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
|
||||||
wire_en->was_checked = true;
|
|
||||||
current_ast_mod->children.push_back(wire_en);
|
|
||||||
current_scope[wire_en->str] = wire_en;
|
|
||||||
while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
|
|
||||||
|
|
||||||
AstNode *assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
|
AstNode *assign_en_first = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
|
||||||
assign_en->children[0]->str = id_en;
|
assign_en_first->children[0]->str = id_en;
|
||||||
assign_en->children[0]->was_checked = true;
|
assign_en_first->children[0]->was_checked = true;
|
||||||
defNode->children.push_back(assign_en);
|
defNode->children.push_back(assign_en_first);
|
||||||
|
|
||||||
node_en = new AstNode(AST_IDENTIFIER);
|
AstNode *node_en = new AstNode(AST_IDENTIFIER);
|
||||||
node_en->str = id_en;
|
node_en->str = id_en;
|
||||||
}
|
|
||||||
|
|
||||||
if (!defNode->children.empty())
|
if (!defNode->children.empty())
|
||||||
current_top_block->children.insert(current_top_block->children.begin(), defNode);
|
current_top_block->children.insert(current_top_block->children.begin(), defNode);
|
||||||
|
@ -2690,13 +2685,11 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
assign_data->children[0]->str = id_data;
|
assign_data->children[0]->str = id_data;
|
||||||
assign_data->children[0]->was_checked = true;
|
assign_data->children[0]->was_checked = true;
|
||||||
|
|
||||||
if (current_always->type != AST_INITIAL) {
|
for (int i = 0; i < mem_width; i++)
|
||||||
for (int i = 0; i < mem_width; i++)
|
set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
|
||||||
set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
|
assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
|
||||||
assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
|
assign_en->children[0]->str = id_en;
|
||||||
assign_en->children[0]->str = id_en;
|
assign_en->children[0]->was_checked = true;
|
||||||
assign_en->children[0]->was_checked = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2719,14 +2712,12 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
assign_data->children[0]->str = id_data;
|
assign_data->children[0]->str = id_data;
|
||||||
assign_data->children[0]->was_checked = true;
|
assign_data->children[0]->was_checked = true;
|
||||||
|
|
||||||
if (current_always->type != AST_INITIAL) {
|
for (int i = 0; i < mem_width; i++)
|
||||||
for (int i = 0; i < mem_width; i++)
|
set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
|
||||||
set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
|
assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),
|
||||||
assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),
|
new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
|
||||||
new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
|
assign_en->children[0]->str = id_en;
|
||||||
assign_en->children[0]->str = id_en;
|
assign_en->children[0]->was_checked = true;
|
||||||
assign_en->children[0]->was_checked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete left_at_zero_ast;
|
delete left_at_zero_ast;
|
||||||
delete right_at_zero_ast;
|
delete right_at_zero_ast;
|
||||||
|
@ -2741,18 +2732,20 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
assign_data->children[0]->was_checked = true;
|
assign_data->children[0]->was_checked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_always->type != AST_INITIAL) {
|
assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
|
||||||
assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
|
assign_en->children[0]->str = id_en;
|
||||||
assign_en->children[0]->str = id_en;
|
assign_en->children[0]->was_checked = true;
|
||||||
assign_en->children[0]->was_checked = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (assign_data)
|
if (assign_data)
|
||||||
newNode->children.push_back(assign_data);
|
newNode->children.push_back(assign_data);
|
||||||
if (assign_en)
|
if (assign_en)
|
||||||
newNode->children.push_back(assign_en);
|
newNode->children.push_back(assign_en);
|
||||||
|
|
||||||
AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR, node_addr, node_data, node_en);
|
AstNode *wrnode;
|
||||||
|
if (current_always->type == AST_INITIAL)
|
||||||
|
wrnode = new AstNode(AST_MEMINIT, node_addr, node_data, node_en, mkconst_int(1, false));
|
||||||
|
else
|
||||||
|
wrnode = new AstNode(AST_MEMWR, node_addr, node_data, node_en);
|
||||||
wrnode->str = children[0]->str;
|
wrnode->str = children[0]->str;
|
||||||
wrnode->id2ast = children[0]->id2ast;
|
wrnode->id2ast = children[0]->id2ast;
|
||||||
wrnode->location = location;
|
wrnode->location = location;
|
||||||
|
@ -3921,8 +3914,12 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
|
||||||
AstNode *meminit = nullptr;
|
AstNode *meminit = nullptr;
|
||||||
int next_meminit_cursor=0;
|
int next_meminit_cursor=0;
|
||||||
vector<State> meminit_bits;
|
vector<State> meminit_bits;
|
||||||
|
vector<State> en_bits;
|
||||||
int meminit_size=0;
|
int meminit_size=0;
|
||||||
|
|
||||||
|
for (int i = 0; i < mem_width; i++)
|
||||||
|
en_bits.push_back(State::S1);
|
||||||
|
|
||||||
std::ifstream f;
|
std::ifstream f;
|
||||||
f.open(mem_filename.c_str());
|
f.open(mem_filename.c_str());
|
||||||
if (f.fail()) {
|
if (f.fail()) {
|
||||||
|
@ -3996,12 +3993,13 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
|
||||||
{
|
{
|
||||||
if (meminit != nullptr) {
|
if (meminit != nullptr) {
|
||||||
meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
|
meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
|
||||||
meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
|
meminit->children[3] = AstNode::mkconst_int(meminit_size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
meminit = new AstNode(AST_MEMINIT);
|
meminit = new AstNode(AST_MEMINIT);
|
||||||
meminit->children.push_back(AstNode::mkconst_int(cursor, false));
|
meminit->children.push_back(AstNode::mkconst_int(cursor, false));
|
||||||
meminit->children.push_back(nullptr);
|
meminit->children.push_back(nullptr);
|
||||||
|
meminit->children.push_back(AstNode::mkconst_bits(en_bits, false));
|
||||||
meminit->children.push_back(nullptr);
|
meminit->children.push_back(nullptr);
|
||||||
meminit->str = memory->str;
|
meminit->str = memory->str;
|
||||||
meminit->id2ast = memory;
|
meminit->id2ast = memory;
|
||||||
|
@ -4036,7 +4034,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
|
||||||
|
|
||||||
if (meminit != nullptr) {
|
if (meminit != nullptr) {
|
||||||
meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
|
meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
|
||||||
meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
|
meminit->children[3] = AstNode::mkconst_int(meminit_size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
|
@ -4381,10 +4379,12 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
||||||
log_assert(children[0]->type == AST_CONSTANT);
|
log_assert(children[0]->type == AST_CONSTANT);
|
||||||
log_assert(children[1]->type == AST_CONSTANT);
|
log_assert(children[1]->type == AST_CONSTANT);
|
||||||
log_assert(children[2]->type == AST_CONSTANT);
|
log_assert(children[2]->type == AST_CONSTANT);
|
||||||
|
log_assert(children[3]->type == AST_CONSTANT);
|
||||||
|
|
||||||
int cursor = children[0]->asInt(false);
|
int cursor = children[0]->asInt(false);
|
||||||
Const data = children[1]->bitsAsConst();
|
Const data = children[1]->bitsAsConst();
|
||||||
int length = children[2]->asInt(false);
|
Const en = children[2]->bitsAsConst();
|
||||||
|
int length = children[3]->asInt(false);
|
||||||
|
|
||||||
if (length != 0)
|
if (length != 0)
|
||||||
{
|
{
|
||||||
|
@ -4395,10 +4395,37 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
||||||
int wordsz = GetSize(data) / length;
|
int wordsz = GetSize(data) / length;
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false)));
|
int pos = 0;
|
||||||
block->children.back()->children[0]->str = str;
|
while (pos < wordsz) {
|
||||||
block->children.back()->children[0]->id2ast = id2ast;
|
if (en[pos] != State::S1) {
|
||||||
block->children.back()->children[0]->was_checked = true;
|
pos++;
|
||||||
|
} else {
|
||||||
|
int epos = pos + 1;
|
||||||
|
while (epos < wordsz && en[epos] == State::S1)
|
||||||
|
epos++;
|
||||||
|
int clen = epos - pos;
|
||||||
|
AstNode *range = new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false));
|
||||||
|
if (pos != 0 || epos != wordsz) {
|
||||||
|
int left;
|
||||||
|
int right;
|
||||||
|
AstNode *mrange = id2ast->children[0];
|
||||||
|
if (mrange->range_left < mrange->range_right) {
|
||||||
|
right = mrange->range_right - pos;
|
||||||
|
left = mrange->range_right - epos + 1;
|
||||||
|
} else {
|
||||||
|
right = mrange->range_right + pos;
|
||||||
|
left = mrange->range_right + epos - 1;
|
||||||
|
}
|
||||||
|
range = new AstNode(AST_MULTIRANGE, range, new AstNode(AST_RANGE, AstNode::mkconst_int(left, true), AstNode::mkconst_int(right, true)));
|
||||||
|
}
|
||||||
|
AstNode *target = new AstNode(AST_IDENTIFIER, range);
|
||||||
|
target->str = str;
|
||||||
|
target->id2ast = id2ast;
|
||||||
|
target->was_checked = true;
|
||||||
|
block->children.push_back(new AstNode(AST_ASSIGN_EQ, target, mkconst_bits(data.extract(i*wordsz + pos, clen).bits, false)));
|
||||||
|
pos = epos;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,24 +25,24 @@ proc
|
||||||
|
|
||||||
select -assert-count 2 t:$memrd
|
select -assert-count 2 t:$memrd
|
||||||
select -assert-count 1 t:$memwr
|
select -assert-count 1 t:$memwr
|
||||||
select -assert-count 1 t:$meminit
|
select -assert-count 1 t:$meminit_v2
|
||||||
design -save orig
|
design -save orig
|
||||||
|
|
||||||
opt_clean
|
opt_clean
|
||||||
select -assert-none t:$memrd
|
select -assert-none t:$memrd
|
||||||
select -assert-none t:$memwr
|
select -assert-none t:$memwr
|
||||||
select -assert-none t:$meminit
|
select -assert-none t:$meminit_v2
|
||||||
|
|
||||||
design -load orig
|
design -load orig
|
||||||
expose top/rd1
|
expose top/rd1
|
||||||
opt_clean
|
opt_clean
|
||||||
select -assert-count 1 t:$memrd
|
select -assert-count 1 t:$memrd
|
||||||
select -assert-count 1 t:$memwr
|
select -assert-count 1 t:$memwr
|
||||||
select -assert-count 1 t:$meminit
|
select -assert-count 1 t:$meminit_v2
|
||||||
|
|
||||||
design -load orig
|
design -load orig
|
||||||
expose top/rd1 top/rd2
|
expose top/rd1 top/rd2
|
||||||
opt_clean
|
opt_clean
|
||||||
select -assert-count 2 t:$memrd
|
select -assert-count 2 t:$memrd
|
||||||
select -assert-count 1 t:$memwr
|
select -assert-count 1 t:$memwr
|
||||||
select -assert-count 1 t:$meminit
|
select -assert-count 1 t:$meminit_v2
|
||||||
|
|
Loading…
Reference in New Issue