@@ -1145,30 +1145,156 @@ void UhdmImporter::import_module(const module_inst* uhdm_module) {
11451145 name_map[var_name] = wire;
11461146 add_src_attribute (wire->attributes , var);
11471147
1148- // Add wiretype attribute for struct types
1148+ // Import attributes (e.g., (* keep *))
1149+ if (auto variables = any_cast<const UHDM ::variables*>(var)) {
1150+ if (variables->Attributes ()) {
1151+ for (auto attr : *variables->Attributes ()) {
1152+ std::string attr_name = std::string (attr->VpiName ());
1153+ if (!attr_name.empty ()) {
1154+ // Set the attribute to 1 (standard practice for boolean attributes like keep)
1155+ wire->attributes [RTLIL::escape_id (attr_name)] = RTLIL::Const (1 );
1156+ if (mode_debug)
1157+ log (" UHDM: Added attribute '%s' to variable '%s'\n " , attr_name.c_str (), var_name.c_str ());
1158+ }
1159+ }
1160+ }
1161+ }
1162+
1163+ // Add wiretype and signed attributes
11491164 if (auto logic_var = dynamic_cast <const UHDM ::logic_var*>(var)) {
11501165 if (auto ref_typespec = logic_var->Typespec ()) {
1166+ // First check if we have a typedef name to use as wiretype
1167+ std::string wiretype_name;
1168+
1169+ // Check if the actual_typespec has a name (typedef name)
11511170 if (auto actual_typespec = ref_typespec->Actual_typespec ()) {
1152- if (actual_typespec->UhdmType () == uhdmstruct_typespec) {
1153- // Get the struct type name
1154- std::string type_name;
1155- if (!ref_typespec->VpiName ().empty ()) {
1156- type_name = ref_typespec->VpiName ();
1157- } else if (!actual_typespec->VpiName ().empty ()) {
1158- type_name = actual_typespec->VpiName ();
1159- }
1160-
1161- if (!type_name.empty ()) {
1162- wire->attributes [RTLIL::escape_id (" wiretype" )] = RTLIL::escape_id (type_name);
1163- log (" UHDM: Added wiretype attribute '\\ %s' to wire '%s'\n " , type_name.c_str (), wire->name .c_str ());
1171+ if (!actual_typespec->VpiName ().empty ()) {
1172+ wiretype_name = actual_typespec->VpiName ();
1173+ } else if (!ref_typespec->VpiName ().empty ()) {
1174+ wiretype_name = ref_typespec->VpiName ();
1175+ }
1176+
1177+ // Add wiretype attribute for any typedef'd type
1178+ if (!wiretype_name.empty ()) {
1179+ wire->attributes [RTLIL::escape_id (" wiretype" )] = RTLIL::escape_id (wiretype_name);
1180+ log (" UHDM: Added wiretype attribute '\\ %s' to wire '%s'\n " , wiretype_name.c_str (), wire->name .c_str ());
1181+ }
1182+
1183+ // Check for signed attribute
1184+ bool is_signed = false ;
1185+ switch (actual_typespec->UhdmType ()) {
1186+ case uhdmlogic_typespec:
1187+ if (auto logic_ts = dynamic_cast <const UHDM ::logic_typespec*>(actual_typespec)) {
1188+ is_signed = logic_ts->VpiSigned ();
1189+ log (" UHDM: Variable '%s' logic_typespec VpiSigned=%d\n " , var_name.c_str (), is_signed);
1190+ }
1191+ break ;
1192+ case uhdmint_typespec:
1193+ if (auto int_ts = dynamic_cast <const UHDM ::int_typespec*>(actual_typespec)) {
1194+ is_signed = int_ts->VpiSigned ();
1195+ log (" UHDM: Variable '%s' int_typespec VpiSigned=%d\n " , var_name.c_str (), is_signed);
1196+ }
1197+ break ;
1198+ default :
1199+ break ;
1200+ }
1201+
1202+ if (is_signed) {
1203+ wire->is_signed = true ;
1204+ log (" UHDM: Variable '%s' is signed, setting is_signed=true\n " , var_name.c_str ());
1205+ }
1206+ }
1207+ }
1208+
1209+ // Handle initial expression if present
1210+ if (logic_var->Expr ()) {
1211+ log (" UHDM: Variable '%s' has initial expression\n " , var_name.c_str ());
1212+ RTLIL ::SigSpec init_value = import_expression (logic_var->Expr ());
1213+ if (init_value.size () > 0 ) {
1214+ // Resize the init_value to match the wire width
1215+ RTLIL ::SigSpec lhs (wire);
1216+ if (init_value.size () != lhs.size ()) {
1217+ int orig_size = init_value.size ();
1218+ // Need to resize - check if wire is signed for proper extension
1219+ if (wire->is_signed && init_value.size () < lhs.size ()) {
1220+ // Sign extend
1221+ init_value.extend_u0 (lhs.size (), true );
1222+ } else {
1223+ // Zero extend or truncate
1224+ init_value.extend_u0 (lhs.size (), false );
11641225 }
1226+ log (" UHDM: Resized initial value from %d bits to %d bits for variable '%s'\n " ,
1227+ orig_size, lhs.size (), var_name.c_str ());
11651228 }
1229+
1230+ // Create an initial process to assign the value
1231+ RTLIL ::Process* proc = module ->addProcess (NEW_ID );
1232+ proc->root_case .actions .push_back (RTLIL::SigSig (lhs, init_value));
1233+ proc->root_case .compare .clear ();
1234+ proc->root_case .switches .clear ();
1235+
1236+ // Add sync rule for initial
1237+ RTLIL ::SyncRule* sync = new RTLIL ::SyncRule;
1238+ sync->type = RTLIL ::STa; // Always
1239+ sync->signal = RTLIL::SigSpec ();
1240+ sync->actions .push_back (RTLIL::SigSig (lhs, init_value));
1241+ proc->syncs .push_back (sync);
1242+
1243+ add_src_attribute (proc->attributes , var);
1244+ log (" UHDM: Created initial assignment for variable '%s'\n " , var_name.c_str ());
11661245 }
11671246 }
11681247 }
11691248
11701249 log (" UHDM: Created wire '%s' for variable\n " , wire->name .c_str ());
11711250 } else {
1251+ // Wire already exists, but check if we need to handle initial expression
1252+ RTLIL ::Wire* existing_wire = module ->wire (wire_id);
1253+ if (existing_wire) {
1254+ wire_map[var] = existing_wire;
1255+ name_map[var_name] = existing_wire;
1256+
1257+ // Handle initial expression for existing wire
1258+ if (auto logic_var = dynamic_cast <const UHDM ::logic_var*>(var)) {
1259+ if (logic_var->Expr ()) {
1260+ log (" UHDM: Existing variable '%s' has initial expression\n " , var_name.c_str ());
1261+ RTLIL ::SigSpec init_value = import_expression (logic_var->Expr ());
1262+ if (init_value.size () > 0 ) {
1263+ // Resize the init_value to match the wire width
1264+ RTLIL ::SigSpec lhs (existing_wire);
1265+ if (init_value.size () != lhs.size ()) {
1266+ int orig_size = init_value.size ();
1267+ // Need to resize - check if wire is signed for proper extension
1268+ if (existing_wire->is_signed && init_value.size () < lhs.size ()) {
1269+ // Sign extend
1270+ init_value.extend_u0 (lhs.size (), true );
1271+ } else {
1272+ // Zero extend or truncate
1273+ init_value.extend_u0 (lhs.size (), false );
1274+ }
1275+ log (" UHDM: Resized initial value from %d bits to %d bits for existing variable '%s'\n " ,
1276+ orig_size, lhs.size (), var_name.c_str ());
1277+ }
1278+
1279+ // Create an initial process to assign the value
1280+ RTLIL ::Process* proc = module ->addProcess (NEW_ID );
1281+ proc->root_case .actions .push_back (RTLIL::SigSig (lhs, init_value));
1282+ proc->root_case .compare .clear ();
1283+ proc->root_case .switches .clear ();
1284+
1285+ // Add sync rule for initial
1286+ RTLIL ::SyncRule* sync = new RTLIL ::SyncRule;
1287+ sync->type = RTLIL ::STa; // Always
1288+ sync->signal = RTLIL::SigSpec ();
1289+ sync->actions .push_back (RTLIL::SigSig (lhs, init_value));
1290+ proc->syncs .push_back (sync);
1291+
1292+ add_src_attribute (proc->attributes , var);
1293+ log (" UHDM: Created initial assignment for existing variable '%s'\n " , var_name.c_str ());
1294+ }
1295+ }
1296+ }
1297+ }
11721298 log (" UHDM: Variable '%s' already exists as wire, skipping\n " , var_name.c_str ());
11731299 }
11741300 }
@@ -1403,12 +1529,9 @@ void UhdmImporter::import_module(const module_inst* uhdm_module) {
14031529 // Finalize module
14041530 module ->fixup_ports ();
14051531
1406- // Check if module is empty (no processes, cells, or memories) and mark as blackbox if so
1407- if (module ->processes .empty () && module ->cells_ .empty () && module ->memories .empty ()) {
1408- // This is an empty module, mark it as blackbox
1409- module ->set_bool_attribute (ID ::blackbox);
1410- log (" UHDM: Module %s has no implementation, marking as blackbox\n " , module ->name .c_str ());
1411- }
1532+ // NOTE: Blackbox detection is done after hierarchy import in import_design()
1533+ // We don't mark modules as blackbox here because cells may be added later
1534+ // during hierarchy traversal
14121535
14131536 // Restore saved instance context
14141537 current_instance = saved_instance;
0 commit comments