Skip to content

Commit ccd98d2

Browse files
committed
Start Tcl design inspection methods
1 parent 8c2d1a1 commit ccd98d2

File tree

1 file changed

+298
-0
lines changed

1 file changed

+298
-0
lines changed

kernel/yosys.cc

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,11 +829,309 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a
829829
return TCL_OK;
830830
}
831831

832+
#define FLAG(name) \
833+
if (!strcmp(argv[i], "-" #name)) { \
834+
name##_flag = true; \
835+
continue; \
836+
} \
837+
838+
#define ERROR(str) \
839+
{ \
840+
Tcl_SetResult(interp, (char *)(str), TCL_STATIC); \
841+
return TCL_ERROR; \
842+
}
843+
844+
static int tcl_get_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
845+
{
846+
int i;
847+
bool mod_flag = false, string_flag = false, int_flag = false, bool_flag = false;
848+
for (i = 1; i < argc; i++) {
849+
FLAG(mod)
850+
FLAG(string)
851+
FLAG(int)
852+
FLAG(bool)
853+
break;
854+
}
855+
856+
if ((mod_flag && i != argc - 2) ||
857+
(!mod_flag && i != argc - 3) ||
858+
(string_flag + int_flag + bool_flag > 1))
859+
ERROR("bad usage: expected \"get_attr -mod [-string|-int|-bool] <module> <attrname>\""
860+
" or \"get_attr [-string|-int|-bool] <module> <identifier> <attrname>\"")
861+
862+
IdString mod_id, obj_id, attr_id;
863+
mod_id = RTLIL::escape_id(argv[i++]);
864+
if (!mod_flag)
865+
obj_id = RTLIL::escape_id(argv[i++]);
866+
attr_id = RTLIL::escape_id(argv[i++]);
867+
868+
RTLIL::Module *mod = yosys_design->module(mod_id);
869+
if (!mod)
870+
ERROR("module not found")
871+
872+
RTLIL::AttrObject *obj = nullptr;
873+
if (mod_flag) {
874+
obj = mod;
875+
} else {
876+
obj = mod->wire(obj_id);
877+
if (!obj)
878+
obj = mod->memories.at(obj_id, nullptr);
879+
if (!obj)
880+
obj = mod->cell(obj_id);
881+
if (!obj)
882+
obj = mod->processes.at(obj_id, nullptr);
883+
}
884+
885+
if (!obj)
886+
ERROR("object not found")
887+
888+
if (string_flag) {
889+
Tcl_SetResult(interp, (char *) obj->get_string_attribute(attr_id).c_str(), TCL_VOLATILE);
890+
} else if (int_flag) {
891+
if (!obj->has_attribute(attr_id))
892+
ERROR("attribute missing (required for -int)");
893+
894+
RTLIL::Const &value = obj->attributes.at(attr_id);
895+
if (value.size() > 32)
896+
ERROR("value too large")
897+
898+
// FIXME: 32'hffffffff will return as negative despite is_signed=false
899+
Tcl_SetResult(interp, (char *) std::to_string(value.as_int()).c_str(), TCL_VOLATILE);
900+
} else if (bool_flag) {
901+
bool value = obj->get_bool_attribute(attr_id);
902+
Tcl_SetResult(interp, (char *) std::to_string(value).c_str(), TCL_VOLATILE);
903+
} else {
904+
if (!obj->has_attribute(attr_id))
905+
ERROR("attribute missing (required unless -bool or -string)")
906+
907+
Tcl_SetResult(interp, (char *) obj->attributes.at(attr_id).as_string().c_str(), TCL_VOLATILE);
908+
}
909+
910+
return TCL_OK;
911+
}
912+
913+
static int tcl_has_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
914+
{
915+
int i;
916+
bool mod_flag = false;
917+
for (i = 1; i < argc; i++) {
918+
FLAG(mod)
919+
break;
920+
}
921+
922+
if ((mod_flag && i != argc - 2) ||
923+
(!mod_flag && i != argc - 3))
924+
ERROR("bad usage: expected \"has_attr -mod <module> <attrname>\""
925+
" or \"has_attr <module> <identifier> <attrname>\"")
926+
927+
IdString mod_id, obj_id, attr_id;
928+
mod_id = RTLIL::escape_id(argv[i++]);
929+
if (!mod_flag)
930+
obj_id = RTLIL::escape_id(argv[i++]);
931+
attr_id = RTLIL::escape_id(argv[i++]);
932+
933+
RTLIL::Module *mod = yosys_design->module(mod_id);
934+
if (!mod)
935+
ERROR("module not found")
936+
937+
RTLIL::AttrObject *obj = nullptr;
938+
if (mod_flag) {
939+
obj = mod;
940+
} else {
941+
obj = mod->wire(obj_id);
942+
if (!obj)
943+
obj = mod->memories.at(obj_id, nullptr);
944+
if (!obj)
945+
obj = mod->cell(obj_id);
946+
if (!obj)
947+
obj = mod->processes.at(obj_id, nullptr);
948+
}
949+
950+
if (!obj)
951+
ERROR("object not found")
952+
953+
Tcl_SetResult(interp, (char *) std::to_string(obj->has_attribute(attr_id)).c_str(), TCL_VOLATILE);
954+
return TCL_OK;
955+
}
956+
957+
static int tcl_set_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
958+
{
959+
int i;
960+
bool mod_flag = false, string_flag = false, int_flag = false, bool_flag = false;
961+
bool false_flag = false, true_flag = false;
962+
for (i = 1; i < argc; i++) {
963+
FLAG(mod)
964+
FLAG(string)
965+
FLAG(int)
966+
FLAG(bool)
967+
FLAG(false)
968+
FLAG(true)
969+
break;
970+
}
971+
972+
if ((i != argc - (2 + !mod_flag + !(true_flag || false_flag))) ||
973+
(string_flag + int_flag + bool_flag + true_flag + false_flag > 1))
974+
ERROR("bad usage: expected \"set_attr -mod [-string|-int|-bool] <module> <attrname> <value>\""
975+
" or \"set_attr [-string|-int|-bool] <module> <identifier> <attrname> <value>\""
976+
" or \"set_attr [-true|-false] <module> <identifier> <attrname>\""
977+
" or \"set_attr -mod [-true|-false| <module> <attrname>\"")
978+
979+
IdString mod_id, obj_id, attr_id;
980+
mod_id = RTLIL::escape_id(argv[i++]);
981+
if (!mod_flag)
982+
obj_id = RTLIL::escape_id(argv[i++]);
983+
attr_id = RTLIL::escape_id(argv[i++]);
984+
985+
RTLIL::Module *mod = yosys_design->module(mod_id);
986+
if (!mod)
987+
ERROR("module not found")
988+
989+
RTLIL::AttrObject *obj = nullptr;
990+
if (mod_flag) {
991+
obj = mod;
992+
} else {
993+
obj = mod->wire(obj_id);
994+
if (!obj)
995+
obj = mod->memories.at(obj_id, nullptr);
996+
if (!obj)
997+
obj = mod->cell(obj_id);
998+
if (!obj)
999+
obj = mod->processes.at(obj_id, nullptr);
1000+
}
1001+
1002+
if (!obj)
1003+
ERROR("object not found")
1004+
1005+
if (string_flag) {
1006+
obj->set_string_attribute(attr_id, argv[i++]);
1007+
} else if (int_flag) {
1008+
obj->attributes[attr_id] = atoi(argv[i++]);
1009+
} else if (bool_flag) {
1010+
obj->set_bool_attribute(attr_id, atoi(argv[i++]) != 0);
1011+
} else if (true_flag) {
1012+
obj->set_bool_attribute(attr_id, true);
1013+
} else if (false_flag) {
1014+
obj->set_bool_attribute(attr_id, false);
1015+
} else {
1016+
obj->attributes[attr_id] = Const::from_string(std::string(argv[i++]));
1017+
}
1018+
1019+
return TCL_OK;
1020+
}
1021+
1022+
static int tcl_get_param(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
1023+
{
1024+
int i;
1025+
bool string_flag = false, int_flag = false;
1026+
for (i = 1; i < argc; i++) {
1027+
FLAG(string)
1028+
FLAG(int)
1029+
break;
1030+
}
1031+
1032+
if ((i != argc - 3) ||
1033+
(string_flag + int_flag > 1))
1034+
ERROR("bad usage: expected \"get_param [-string|-int] <module> <cellid> <paramname>")
1035+
1036+
IdString mod_id, cell_id, param_id;
1037+
mod_id = RTLIL::escape_id(argv[i++]);
1038+
cell_id = RTLIL::escape_id(argv[i++]);
1039+
param_id = RTLIL::escape_id(argv[i++]);
1040+
1041+
RTLIL::Module *mod = yosys_design->module(mod_id);
1042+
if (!mod)
1043+
ERROR("module not found")
1044+
1045+
RTLIL::Cell *cell = mod->cell(cell_id);
1046+
if (!cell)
1047+
ERROR("object not found")
1048+
1049+
if (!cell->hasParam(param_id))
1050+
ERROR("parameter missing")
1051+
1052+
const RTLIL::Const &value = cell->getParam(param_id);
1053+
1054+
if (string_flag) {
1055+
Tcl_SetResult(interp, (char *) value.decode_string().c_str(), TCL_VOLATILE);
1056+
} else if (int_flag) {
1057+
if (value.size() > 32)
1058+
ERROR("value too large")
1059+
1060+
Tcl_SetResult(interp, (char *) std::to_string(value.as_int()).c_str(), TCL_VOLATILE);
1061+
} else {
1062+
Tcl_SetResult(interp, (char *) value.as_string().c_str(), TCL_VOLATILE);
1063+
}
1064+
return TCL_OK;
1065+
}
1066+
1067+
static int tcl_set_param(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
1068+
{
1069+
int i;
1070+
bool string_flag = false, int_flag = false;
1071+
for (i = 1; i < argc; i++) {
1072+
FLAG(string)
1073+
FLAG(int)
1074+
break;
1075+
}
1076+
1077+
if ((i != argc - 4) ||
1078+
(string_flag + int_flag > 1))
1079+
ERROR("bad usage: expected \"get_param [-string|-int] <module> <cellid> <paramname> <value>")
1080+
1081+
IdString mod_id, cell_id, param_id;
1082+
mod_id = RTLIL::escape_id(argv[i++]);
1083+
cell_id = RTLIL::escape_id(argv[i++]);
1084+
param_id = RTLIL::escape_id(argv[i++]);
1085+
1086+
RTLIL::Module *mod = yosys_design->module(mod_id);
1087+
if (!mod)
1088+
ERROR("module not found")
1089+
1090+
RTLIL::Cell *cell = mod->cell(cell_id);
1091+
if (!cell)
1092+
ERROR("object not found")
1093+
1094+
if (string_flag) {
1095+
cell->setParam(param_id, Const(std::string(argv[i++])));
1096+
} else if (int_flag) {
1097+
cell->setParam(param_id, Const(atoi(argv[i++])));
1098+
} else {
1099+
cell->setParam(param_id, Const::from_string(std::string(argv[i++])));
1100+
}
1101+
return TCL_OK;
1102+
}
1103+
8321104
int yosys_tcl_iterp_init(Tcl_Interp *interp)
8331105
{
8341106
if (Tcl_Init(interp)!=TCL_OK)
8351107
log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno()));
8361108
Tcl_CreateCommand(interp, "yosys", tcl_yosys_cmd, NULL, NULL);
1109+
Tcl_CreateCommand(interp, "rtlil::get_attr", tcl_get_attr, NULL, NULL);
1110+
Tcl_CreateCommand(interp, "rtlil::has_attr", tcl_has_attr, NULL, NULL);
1111+
Tcl_CreateCommand(interp, "rtlil::set_attr", tcl_set_attr, NULL, NULL);
1112+
Tcl_CreateCommand(interp, "rtlil::get_param", tcl_get_param, NULL, NULL);
1113+
Tcl_CreateCommand(interp, "rtlil::set_param", tcl_set_param, NULL, NULL);
1114+
1115+
// TODO:
1116+
//
1117+
// port_list
1118+
// wire_list
1119+
// cell_list
1120+
// wire_width
1121+
//
1122+
// add_wire
1123+
// add_cell
1124+
// rename_wire
1125+
// rename_cell
1126+
// remove
1127+
//
1128+
// SigSpec land
1129+
//
1130+
// get_conn
1131+
// set_conn
1132+
// unpack
1133+
// pack
1134+
8371135
return TCL_OK ;
8381136
}
8391137

0 commit comments

Comments
 (0)