33import glob
44import csv
55import os
6+ import fcntl
67import subprocess
78from typing import Callable , Optional
89from hwcomponents import ComponentModel , action
@@ -15,11 +16,17 @@ def _clean_tmp_dir():
1516 os .path .dirname (os .path .abspath (__file__ )), "cacti_inputs_outputs"
1617 )
1718 os .makedirs (temp_dir , exist_ok = True )
18- # If there's more than 200 files in the directory, remove the oldest ones
19- files = sorted (glob .glob (temp_dir ), key = os .path .getctime , reverse = True )
19+ files = sorted (
20+ [f for f in glob .glob (os .path .join (temp_dir , "*" )) if not f .endswith (".lock" )],
21+ key = os .path .getctime ,
22+ reverse = True ,
23+ )
2024 if len (files ) > 200 :
2125 for file in files [200 :]:
22- os .remove (file )
26+ try :
27+ os .remove (file )
28+ except OSError :
29+ pass
2330 return temp_dir
2431
2532
@@ -533,6 +540,7 @@ def _call_cacti(
533540 input_path = os .path .join (temp_dir , input_name )
534541 output_path = os .path .join (temp_dir , input_name + "cacti.log" )
535542 output_path_csv = os .path .join (temp_dir , input_name + ".out" )
543+ lock_path = os .path .join (temp_dir , input_name + ".lock" )
536544
537545 def read_csv_results (output_path_csv ):
538546 with open (output_path_csv , "r" ) as f :
@@ -546,41 +554,47 @@ def read_csv_results(output_path_csv):
546554 float (row [" Random cycle time (ns)" ]) * 1e-9 ,
547555 )
548556
549- if os .path .exists (output_path_csv ):
557+ with open (lock_path , "w" ) as lock_file :
558+ fcntl .flock (lock_file , fcntl .LOCK_EX )
550559 try :
551- return read_csv_results (output_path_csv )
552- except Exception as e :
553- self .logger .warning (
554- f"Error reading CACTI output file { output_path_csv } : { e } "
560+ if os .path .exists (output_path_csv ):
561+ try :
562+ return read_csv_results (output_path_csv )
563+ except Exception as e :
564+ self .logger .warning (
565+ f"Error reading CACTI output file { output_path_csv } : { e } "
566+ )
567+ pass
568+
569+ with open (input_path , "w" ) as f :
570+ f .write ("" .join (cfg ))
571+
572+ self .logger .info (f"Calling CACTI with input path { input_path } " )
573+ self .logger .info (f"CACTI output will be written to { output_path } " )
574+
575+ cacti_dir = _get_cacti_dir (self .logger )
576+
577+ exec_list = ["./cacti" , "-infile" , input_path ]
578+ self .logger .info (
579+ f"Calling: cd { cacti_dir } ; { ' ' .join (exec_list )} >> { output_path } 2>&1"
555580 )
556- pass
557-
558- with open (input_path , "w" ) as f :
559- f .write ("" .join (cfg ))
560-
561- self .logger .info (f"Calling CACTI with input path { input_path } " )
562- self .logger .info (f"CACTI output will be written to { output_path } " )
563-
564- cacti_dir = _get_cacti_dir (self .logger )
581+ with open (output_path , "w" ) as out :
582+ result = subprocess .call (
583+ exec_list ,
584+ cwd = cacti_dir ,
585+ stdout = out ,
586+ stderr = subprocess .STDOUT ,
587+ )
588+
589+ if result != 0 or not os .path .exists (output_path_csv ):
590+ raise Exception (
591+ f"CACTI failed with exit code { result } . Please check { output_path } for CACTI output. "
592+ f"Run command: cd { cacti_dir } ; { ' ' .join (exec_list )} >> { output_path } 2>&1"
593+ )
565594
566- exec_list = ["./cacti" , "-infile" , input_path ]
567- self .logger .info (
568- f"Calling: cd { cacti_dir } ; { ' ' .join (exec_list )} >> { output_path } 2>&1"
569- )
570- result = subprocess .call (
571- exec_list ,
572- cwd = cacti_dir ,
573- stdout = open (output_path , "w" ),
574- stderr = subprocess .STDOUT ,
575- )
576-
577- if result != 0 or not os .path .exists (output_path_csv ):
578- raise Exception (
579- f"CACTI failed with exit code { result } . Please check { output_path } for CACTI output. "
580- f"Run command: cd { cacti_dir } ; { ' ' .join (exec_list )} >> { output_path } 2>&1"
581- )
582-
583- return read_csv_results (output_path_csv )
595+ return read_csv_results (output_path_csv )
596+ finally :
597+ fcntl .flock (lock_file , fcntl .LOCK_UN )
584598
585599
586600class SRAM (_Memory ):
0 commit comments