mirror of https://github.com/YosysHQ/yosys.git
Add support for cell arrays
This commit is contained in:
parent
0b1ce63a19
commit
e275e8eef9
|
@ -127,6 +127,7 @@ std::string AST::type2str(AstNodeType type)
|
|||
X(AST_ASSIGN)
|
||||
X(AST_CELL)
|
||||
X(AST_PRIMITIVE)
|
||||
X(AST_CELLARRAY)
|
||||
X(AST_ALWAYS)
|
||||
X(AST_INITIAL)
|
||||
X(AST_BLOCK)
|
||||
|
|
|
@ -107,6 +107,7 @@ namespace AST
|
|||
AST_ASSIGN,
|
||||
AST_CELL,
|
||||
AST_PRIMITIVE,
|
||||
AST_CELLARRAY,
|
||||
AST_ALWAYS,
|
||||
AST_INITIAL,
|
||||
AST_BLOCK,
|
||||
|
|
|
@ -878,6 +878,31 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
did_something = true;
|
||||
}
|
||||
|
||||
// unroll cell arrays
|
||||
if (type == AST_CELLARRAY)
|
||||
{
|
||||
if (!children.at(0)->range_valid)
|
||||
log_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum);
|
||||
|
||||
newNode = new AstNode(AST_GENBLOCK);
|
||||
int num = std::max(children.at(0)->range_left, children.at(0)->range_right) - std::min(children.at(0)->range_left, children.at(0)->range_right) + 1;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
|
||||
AstNode *new_cell = children.at(1)->clone();
|
||||
newNode->children.push_back(new_cell);
|
||||
new_cell->str += stringf("[%d]", idx);
|
||||
if (new_cell->type == AST_PRIMITIVE) {
|
||||
log_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename.c_str(), linenum);
|
||||
} else {
|
||||
log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
|
||||
new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
goto apply_newNode;
|
||||
}
|
||||
|
||||
// replace primitives with assignmens
|
||||
if (type == AST_PRIMITIVE)
|
||||
{
|
||||
|
|
|
@ -634,6 +634,13 @@ single_cell:
|
|||
astbuf2->str = *$1;
|
||||
delete $1;
|
||||
ast_stack.back()->children.push_back(astbuf2);
|
||||
} '(' cell_port_list ')' |
|
||||
TOK_ID non_opt_range {
|
||||
astbuf2 = astbuf1->clone();
|
||||
if (astbuf2->type != AST_PRIMITIVE)
|
||||
astbuf2->str = *$1;
|
||||
delete $1;
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_CELLARRAY, $2, astbuf2));
|
||||
} '(' cell_port_list ')';
|
||||
|
||||
prim_list:
|
||||
|
|
|
@ -740,7 +740,8 @@ void RTLIL::Module::check()
|
|||
for (auto &it2 : it.second->parameters) {
|
||||
assert(it2.first.size() > 0 && (it2.first[0] == '\\' || it2.first[0] == '$'));
|
||||
}
|
||||
if (it.second->type[0] == '$' && it.second->type.substr(0, 3) != "$__" && it.second->type.substr(0, 8) != "$paramod" && it.second->type.substr(0, 9) != "$verific$") {
|
||||
if (it.second->type[0] == '$' && it.second->type.substr(0, 3) != "$__" && it.second->type.substr(0, 8) != "$paramod" &&
|
||||
it.second->type.substr(0, 9) != "$verific$" && it.second->type.substr(0, 7) != "$array:") {
|
||||
InternalCellChecker checker(this, it.second);
|
||||
checker.check();
|
||||
}
|
||||
|
|
|
@ -137,12 +137,23 @@ static void generate(RTLIL::Design *design, const std::vector<std::string> &cell
|
|||
static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, std::vector<std::string> &libdirs)
|
||||
{
|
||||
bool did_something = false;
|
||||
std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
|
||||
std::string filename;
|
||||
|
||||
for (auto &cell_it : module->cells)
|
||||
{
|
||||
RTLIL::Cell *cell = cell_it.second;
|
||||
|
||||
if (cell->type.substr(0, 7) == "$array:") {
|
||||
int pos_idx = cell->type.find_first_of(':');
|
||||
int pos_num = cell->type.find_first_of(':', pos_idx + 1);
|
||||
int pos_type = cell->type.find_first_of(':', pos_num + 1);
|
||||
int idx = atoi(cell->type.substr(pos_idx + 1, pos_num).c_str());
|
||||
int num = atoi(cell->type.substr(pos_num + 1, pos_type).c_str());
|
||||
array_cells[cell] = std::pair<int, int>(idx, num);
|
||||
cell->type = cell->type.substr(pos_type + 1);
|
||||
}
|
||||
|
||||
if (design->modules.count(cell->type) == 0)
|
||||
{
|
||||
if (design->modules.count("$abstract" + cell->type))
|
||||
|
@ -198,6 +209,29 @@ static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool fla
|
|||
did_something = true;
|
||||
}
|
||||
|
||||
for (auto &it : array_cells)
|
||||
{
|
||||
RTLIL::Cell *cell = it.first;
|
||||
int idx = it.second.first, num = it.second.second;
|
||||
|
||||
if (design->modules.count(cell->type) == 0)
|
||||
log_error("Array cell `%s.%s' of unkown type `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
|
||||
|
||||
RTLIL::Module *mod = design->modules[cell->type];
|
||||
|
||||
for (auto &conn : cell->connections) {
|
||||
int conn_size = conn.second.width;
|
||||
if (mod->wires.count(conn.first) == 0)
|
||||
log_error("Array cell `%s.%s' connects to unkown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
|
||||
int port_size = mod->wires.at(conn.first)->width;
|
||||
if (conn_size == port_size)
|
||||
continue;
|
||||
if (conn_size != port_size*num)
|
||||
log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
|
||||
conn.second = conn.second.extract(port_size*idx, port_size);
|
||||
}
|
||||
}
|
||||
|
||||
return did_something;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue