33import  yaml 
44import  logging 
55import  pprint 
6+ import  json 
67
78pp  =  pprint .PrettyPrinter (indent = 2 )
89logging .basicConfig (level = logging .INFO , format = "%(levelname)s:: %(message)s" )
@@ -276,14 +277,15 @@ def load_instructions(
276277
277278                        # Process RV64 encoding 
278279                        rv64_match  =  rv64_encoding .get ("match" )
280+                         rv32_match  =  rv32_encoding .get ("match" )
281+ 
279282                        if  rv64_match :
280283                            instr_dict [name ] =  {
281284                                "match" : rv64_match 
282285                            }  # RV64 gets the default name 
283286
284-                         # Process RV32 encoding with a _rv32 suffix 
285-                         rv32_match  =  rv32_encoding .get ("match" )
286-                         if  rv32_match :
287+                         if  rv32_match  and  rv32_match  !=  rv64_match :
288+                             # Process RV32 encoding with a _rv32 suffix 
287289                            instr_dict [f"{ name }  ] =  {"match" : rv32_match }
288290
289291                        continue   # Skip the rest of the loop as we've already added the encodings 
@@ -441,11 +443,7 @@ def load_csrs(csr_root, enabled_extensions, include_all=False, target_arch="RV64
441443                else :
442444                    addr_int  =  int (addr_to_use , 0 )
443445
444-                 # For BOTH architecture, add suffix to RV32-specific CSRs 
445-                 if  target_arch  ==  "BOTH"  and  base  ==  32 :
446-                     csrs [addr_int ] =  f"{ name .upper ()}  
447-                 else :
448-                     csrs [addr_int ] =  name .upper ()
446+                 csrs [addr_int ] =  name .upper ()
449447            except  Exception  as  e :
450448                logging .error (f"Error parsing address { addr_to_use } { path } { e }  )
451449                address_errors  +=  1 
@@ -468,6 +466,124 @@ def load_csrs(csr_root, enabled_extensions, include_all=False, target_arch="RV64
468466    return  csrs 
469467
470468
469+ def  load_exception_codes (
470+     ext_dir , enabled_extensions = None , include_all = False , resolved_codes_file = None 
471+ ):
472+     """Load exception codes from extension YAML files or pre-resolved JSON file.""" 
473+     exception_codes  =  []
474+     found_extensions  =  0 
475+     found_files  =  0 
476+ 
477+     if  enabled_extensions  is  None :
478+         enabled_extensions  =  []
479+     # If we have a resolved codes file, use it instead of processing YAML files 
480+     if  resolved_codes_file  and  os .path .exists (resolved_codes_file ):
481+         try :
482+             with  open (resolved_codes_file , encoding = "utf-8" ) as  f :
483+                 resolved_codes  =  json .load (f )
484+ 
485+             for  code  in  resolved_codes :
486+                 num  =  code .get ("num" )
487+                 name  =  code .get ("name" )
488+                 if  num  is  not None  and  name  is  not None :
489+                     sanitized_name  =  (
490+                         name .lower ()
491+                         .replace (" " , "_" )
492+                         .replace ("/" , "_" )
493+                         .replace ("-" , "_" )
494+                     )
495+                     exception_codes .append ((num , sanitized_name ))
496+ 
497+             logging .info (
498+                 f"Loaded { len (exception_codes )} { resolved_codes_file }  
499+             )
500+ 
501+             # Sort by exception code number and deduplicate 
502+             seen_nums  =  set ()
503+             unique_codes  =  []
504+             for  num , name  in  sorted (exception_codes , key = lambda  x : x [0 ]):
505+                 if  num  not  in seen_nums :
506+                     seen_nums .add (num )
507+                     unique_codes .append ((num , name ))
508+ 
509+             return  unique_codes 
510+ 
511+         except  Exception  as  e :
512+             logging .error (
513+                 f"Error loading resolved codes file { resolved_codes_file } { e }  
514+             )
515+             # Fall back to processing YAML files 
516+ 
517+     for  dirpath , _ , filenames  in  os .walk (ext_dir ):
518+         for  fname  in  filenames :
519+             if  not  fname .endswith (".yaml" ):
520+                 continue 
521+ 
522+             found_files  +=  1 
523+             path  =  os .path .join (dirpath , fname )
524+ 
525+             try :
526+                 with  open (path , encoding = "utf-8" ) as  f :
527+                     data  =  yaml .safe_load (f )
528+ 
529+                 if  not  isinstance (data , dict ) or  data .get ("kind" ) !=  "extension" :
530+                     continue 
531+ 
532+                 found_extensions  +=  1 
533+                 ext_name  =  data .get ("name" , "unnamed" )
534+ 
535+                 # Skip extension filtering if include_all is True 
536+                 if  not  include_all :
537+                     # Filter by extension requirements 
538+                     definedBy  =  data .get ("definedBy" )
539+                     if  definedBy :
540+                         meets_req  =  parse_extension_requirements (definedBy )
541+                         if  not  meets_req (enabled_extensions ):
542+                             continue 
543+ 
544+                     # Check if excluded 
545+                     excludedBy  =  data .get ("excludedBy" )
546+                     if  excludedBy :
547+                         exclusion_check  =  parse_extension_requirements (excludedBy )
548+                         if  exclusion_check (enabled_extensions ):
549+                             continue 
550+ 
551+                 # Get exception codes 
552+                 for  code  in  data .get ("exception_codes" , []):
553+                     num  =  code .get ("num" )
554+                     name  =  code .get ("name" )
555+ 
556+                     if  num  is  not None  and  name  is  not None :
557+                         sanitized_name  =  (
558+                             name .lower ()
559+                             .replace (" " , "_" )
560+                             .replace ("/" , "_" )
561+                             .replace ("-" , "_" )
562+                         )
563+                         exception_codes .append ((num , sanitized_name ))
564+ 
565+             except  Exception  as  e :
566+                 logging .error (f"Error processing file { path } { e }  )
567+ 
568+     if  found_extensions  >  0 :
569+         logging .info (
570+             f"Found { found_extensions } { found_files }  
571+         )
572+         logging .info (f"Added { len (exception_codes )}  )
573+     else :
574+         logging .warning (f"No extension definitions found in { ext_dir }  )
575+ 
576+     # Sort by exception code number and deduplicate 
577+     seen_nums  =  set ()
578+     unique_codes  =  []
579+     for  num , name  in  sorted (exception_codes , key = lambda  x : x [0 ]):
580+         if  num  not  in seen_nums :
581+             seen_nums .add (num )
582+             unique_codes .append ((num , name ))
583+ 
584+     return  unique_codes 
585+ 
586+ 
471587def  parse_match (match_str ):
472588    """ 
473589    Convert the bit pattern string to an integer. 
0 commit comments