@@ -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+
8321104int 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