mirror of https://github.com/YosysHQ/yosys.git
Start Tcl design inspection methods
This commit is contained in:
parent
8c2d1a16d0
commit
ccd98d21c1
298
kernel/yosys.cc
298
kernel/yosys.cc
|
@ -829,11 +829,309 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FLAG(name) \
|
||||||
|
if (!strcmp(argv[i], "-" #name)) { \
|
||||||
|
name##_flag = true; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define ERROR(str) \
|
||||||
|
{ \
|
||||||
|
Tcl_SetResult(interp, (char *)(str), TCL_STATIC); \
|
||||||
|
return TCL_ERROR; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcl_get_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool mod_flag = false, string_flag = false, int_flag = false, bool_flag = false;
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
FLAG(mod)
|
||||||
|
FLAG(string)
|
||||||
|
FLAG(int)
|
||||||
|
FLAG(bool)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mod_flag && i != argc - 2) ||
|
||||||
|
(!mod_flag && i != argc - 3) ||
|
||||||
|
(string_flag + int_flag + bool_flag > 1))
|
||||||
|
ERROR("bad usage: expected \"get_attr -mod [-string|-int|-bool] <module> <attrname>\""
|
||||||
|
" or \"get_attr [-string|-int|-bool] <module> <identifier> <attrname>\"")
|
||||||
|
|
||||||
|
IdString mod_id, obj_id, attr_id;
|
||||||
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
if (!mod_flag)
|
||||||
|
obj_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
attr_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
|
RTLIL::Module *mod = yosys_design->module(mod_id);
|
||||||
|
if (!mod)
|
||||||
|
ERROR("module not found")
|
||||||
|
|
||||||
|
RTLIL::AttrObject *obj = nullptr;
|
||||||
|
if (mod_flag) {
|
||||||
|
obj = mod;
|
||||||
|
} else {
|
||||||
|
obj = mod->wire(obj_id);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->memories.at(obj_id, nullptr);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->cell(obj_id);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->processes.at(obj_id, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj)
|
||||||
|
ERROR("object not found")
|
||||||
|
|
||||||
|
if (string_flag) {
|
||||||
|
Tcl_SetResult(interp, (char *) obj->get_string_attribute(attr_id).c_str(), TCL_VOLATILE);
|
||||||
|
} else if (int_flag) {
|
||||||
|
if (!obj->has_attribute(attr_id))
|
||||||
|
ERROR("attribute missing (required for -int)");
|
||||||
|
|
||||||
|
RTLIL::Const &value = obj->attributes.at(attr_id);
|
||||||
|
if (value.size() > 32)
|
||||||
|
ERROR("value too large")
|
||||||
|
|
||||||
|
// FIXME: 32'hffffffff will return as negative despite is_signed=false
|
||||||
|
Tcl_SetResult(interp, (char *) std::to_string(value.as_int()).c_str(), TCL_VOLATILE);
|
||||||
|
} else if (bool_flag) {
|
||||||
|
bool value = obj->get_bool_attribute(attr_id);
|
||||||
|
Tcl_SetResult(interp, (char *) std::to_string(value).c_str(), TCL_VOLATILE);
|
||||||
|
} else {
|
||||||
|
if (!obj->has_attribute(attr_id))
|
||||||
|
ERROR("attribute missing (required unless -bool or -string)")
|
||||||
|
|
||||||
|
Tcl_SetResult(interp, (char *) obj->attributes.at(attr_id).as_string().c_str(), TCL_VOLATILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcl_has_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool mod_flag = false;
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
FLAG(mod)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mod_flag && i != argc - 2) ||
|
||||||
|
(!mod_flag && i != argc - 3))
|
||||||
|
ERROR("bad usage: expected \"has_attr -mod <module> <attrname>\""
|
||||||
|
" or \"has_attr <module> <identifier> <attrname>\"")
|
||||||
|
|
||||||
|
IdString mod_id, obj_id, attr_id;
|
||||||
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
if (!mod_flag)
|
||||||
|
obj_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
attr_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
|
RTLIL::Module *mod = yosys_design->module(mod_id);
|
||||||
|
if (!mod)
|
||||||
|
ERROR("module not found")
|
||||||
|
|
||||||
|
RTLIL::AttrObject *obj = nullptr;
|
||||||
|
if (mod_flag) {
|
||||||
|
obj = mod;
|
||||||
|
} else {
|
||||||
|
obj = mod->wire(obj_id);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->memories.at(obj_id, nullptr);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->cell(obj_id);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->processes.at(obj_id, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj)
|
||||||
|
ERROR("object not found")
|
||||||
|
|
||||||
|
Tcl_SetResult(interp, (char *) std::to_string(obj->has_attribute(attr_id)).c_str(), TCL_VOLATILE);
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcl_set_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool mod_flag = false, string_flag = false, int_flag = false, bool_flag = false;
|
||||||
|
bool false_flag = false, true_flag = false;
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
FLAG(mod)
|
||||||
|
FLAG(string)
|
||||||
|
FLAG(int)
|
||||||
|
FLAG(bool)
|
||||||
|
FLAG(false)
|
||||||
|
FLAG(true)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i != argc - (2 + !mod_flag + !(true_flag || false_flag))) ||
|
||||||
|
(string_flag + int_flag + bool_flag + true_flag + false_flag > 1))
|
||||||
|
ERROR("bad usage: expected \"set_attr -mod [-string|-int|-bool] <module> <attrname> <value>\""
|
||||||
|
" or \"set_attr [-string|-int|-bool] <module> <identifier> <attrname> <value>\""
|
||||||
|
" or \"set_attr [-true|-false] <module> <identifier> <attrname>\""
|
||||||
|
" or \"set_attr -mod [-true|-false| <module> <attrname>\"")
|
||||||
|
|
||||||
|
IdString mod_id, obj_id, attr_id;
|
||||||
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
if (!mod_flag)
|
||||||
|
obj_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
attr_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
|
RTLIL::Module *mod = yosys_design->module(mod_id);
|
||||||
|
if (!mod)
|
||||||
|
ERROR("module not found")
|
||||||
|
|
||||||
|
RTLIL::AttrObject *obj = nullptr;
|
||||||
|
if (mod_flag) {
|
||||||
|
obj = mod;
|
||||||
|
} else {
|
||||||
|
obj = mod->wire(obj_id);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->memories.at(obj_id, nullptr);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->cell(obj_id);
|
||||||
|
if (!obj)
|
||||||
|
obj = mod->processes.at(obj_id, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj)
|
||||||
|
ERROR("object not found")
|
||||||
|
|
||||||
|
if (string_flag) {
|
||||||
|
obj->set_string_attribute(attr_id, argv[i++]);
|
||||||
|
} else if (int_flag) {
|
||||||
|
obj->attributes[attr_id] = atoi(argv[i++]);
|
||||||
|
} else if (bool_flag) {
|
||||||
|
obj->set_bool_attribute(attr_id, atoi(argv[i++]) != 0);
|
||||||
|
} else if (true_flag) {
|
||||||
|
obj->set_bool_attribute(attr_id, true);
|
||||||
|
} else if (false_flag) {
|
||||||
|
obj->set_bool_attribute(attr_id, false);
|
||||||
|
} else {
|
||||||
|
obj->attributes[attr_id] = Const::from_string(std::string(argv[i++]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcl_get_param(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool string_flag = false, int_flag = false;
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
FLAG(string)
|
||||||
|
FLAG(int)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i != argc - 3) ||
|
||||||
|
(string_flag + int_flag > 1))
|
||||||
|
ERROR("bad usage: expected \"get_param [-string|-int] <module> <cellid> <paramname>")
|
||||||
|
|
||||||
|
IdString mod_id, cell_id, param_id;
|
||||||
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
cell_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
param_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
|
RTLIL::Module *mod = yosys_design->module(mod_id);
|
||||||
|
if (!mod)
|
||||||
|
ERROR("module not found")
|
||||||
|
|
||||||
|
RTLIL::Cell *cell = mod->cell(cell_id);
|
||||||
|
if (!cell)
|
||||||
|
ERROR("object not found")
|
||||||
|
|
||||||
|
if (!cell->hasParam(param_id))
|
||||||
|
ERROR("parameter missing")
|
||||||
|
|
||||||
|
const RTLIL::Const &value = cell->getParam(param_id);
|
||||||
|
|
||||||
|
if (string_flag) {
|
||||||
|
Tcl_SetResult(interp, (char *) value.decode_string().c_str(), TCL_VOLATILE);
|
||||||
|
} else if (int_flag) {
|
||||||
|
if (value.size() > 32)
|
||||||
|
ERROR("value too large")
|
||||||
|
|
||||||
|
Tcl_SetResult(interp, (char *) std::to_string(value.as_int()).c_str(), TCL_VOLATILE);
|
||||||
|
} else {
|
||||||
|
Tcl_SetResult(interp, (char *) value.as_string().c_str(), TCL_VOLATILE);
|
||||||
|
}
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcl_set_param(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bool string_flag = false, int_flag = false;
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
FLAG(string)
|
||||||
|
FLAG(int)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i != argc - 4) ||
|
||||||
|
(string_flag + int_flag > 1))
|
||||||
|
ERROR("bad usage: expected \"get_param [-string|-int] <module> <cellid> <paramname> <value>")
|
||||||
|
|
||||||
|
IdString mod_id, cell_id, param_id;
|
||||||
|
mod_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
cell_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
param_id = RTLIL::escape_id(argv[i++]);
|
||||||
|
|
||||||
|
RTLIL::Module *mod = yosys_design->module(mod_id);
|
||||||
|
if (!mod)
|
||||||
|
ERROR("module not found")
|
||||||
|
|
||||||
|
RTLIL::Cell *cell = mod->cell(cell_id);
|
||||||
|
if (!cell)
|
||||||
|
ERROR("object not found")
|
||||||
|
|
||||||
|
if (string_flag) {
|
||||||
|
cell->setParam(param_id, Const(std::string(argv[i++])));
|
||||||
|
} else if (int_flag) {
|
||||||
|
cell->setParam(param_id, Const(atoi(argv[i++])));
|
||||||
|
} else {
|
||||||
|
cell->setParam(param_id, Const::from_string(std::string(argv[i++])));
|
||||||
|
}
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int yosys_tcl_iterp_init(Tcl_Interp *interp)
|
int yosys_tcl_iterp_init(Tcl_Interp *interp)
|
||||||
{
|
{
|
||||||
if (Tcl_Init(interp)!=TCL_OK)
|
if (Tcl_Init(interp)!=TCL_OK)
|
||||||
log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno()));
|
log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno()));
|
||||||
Tcl_CreateCommand(interp, "yosys", tcl_yosys_cmd, NULL, NULL);
|
Tcl_CreateCommand(interp, "yosys", tcl_yosys_cmd, NULL, NULL);
|
||||||
|
Tcl_CreateCommand(interp, "rtlil::get_attr", tcl_get_attr, NULL, NULL);
|
||||||
|
Tcl_CreateCommand(interp, "rtlil::has_attr", tcl_has_attr, NULL, NULL);
|
||||||
|
Tcl_CreateCommand(interp, "rtlil::set_attr", tcl_set_attr, NULL, NULL);
|
||||||
|
Tcl_CreateCommand(interp, "rtlil::get_param", tcl_get_param, NULL, NULL);
|
||||||
|
Tcl_CreateCommand(interp, "rtlil::set_param", tcl_set_param, NULL, NULL);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
//
|
||||||
|
// port_list
|
||||||
|
// wire_list
|
||||||
|
// cell_list
|
||||||
|
// wire_width
|
||||||
|
//
|
||||||
|
// add_wire
|
||||||
|
// add_cell
|
||||||
|
// rename_wire
|
||||||
|
// rename_cell
|
||||||
|
// remove
|
||||||
|
//
|
||||||
|
// SigSpec land
|
||||||
|
//
|
||||||
|
// get_conn
|
||||||
|
// set_conn
|
||||||
|
// unpack
|
||||||
|
// pack
|
||||||
|
|
||||||
return TCL_OK ;
|
return TCL_OK ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue