@@ -2762,56 +2762,27 @@ def maybe_abort_no_space(err, step_label):
27622762 if install_precheck :
27632763 step_num = 8 if not only_mode else ""
27642764 console .print (f"\n [bold]Step { step_num } :[/bold] Installing precheck..." )
2765- precheck_dir = Path .home () / 'mpw_precheck'
27662765
2767- # Check if already installed
2768- is_installed = precheck_dir .exists () and (precheck_dir / '.git' ).exists ()
2769-
2770- if is_installed and not overwrite :
2771- console .print ("[green]✓[/green] Precheck already installed" )
2766+ if shutil .which ('docker' ) is None :
2767+ had_errors = True
2768+ console .print ("[red]✗[/red] Docker not found. Install Docker Desktop to pull the precheck image." )
27722769 elif dry_run :
2773- if is_installed :
2774- console .print ("[dim]Would reinstall mpw_precheck [--overwrite][/dim]" )
2775- else :
2776- console .print ("[dim]Would install mpw_precheck[/dim]" )
2770+ console .print ("[dim]Would pull chipfoundry/mpw_precheck:latest[/dim]" )
27772771 else :
27782772 try :
2779- if precheck_dir .exists () and overwrite :
2780- console .print (f"[cyan]Removing existing { precheck_dir } ...[/cyan]" )
2781- shutil .rmtree (precheck_dir )
2782-
2783- if not precheck_dir .exists ():
2784- console .print ("[cyan]Cloning mpw_precheck...[/cyan]" )
2785- subprocess .run (
2786- ['git' , 'clone' , '--depth=1' , 'https://github.com/chipfoundry/mpw_precheck.git' , str (precheck_dir )],
2787- check = True ,
2788- capture_output = True ,
2789- text = True
2790- )
2791- console .print ("[green]✓[/green] Precheck cloned successfully" )
2792-
2793- if shutil .which ('docker' ) is None :
2794- had_errors = True
2795- console .print ("[red]✗[/red] Docker not found. Install Docker Desktop to pull the precheck image." )
2796- console .print ("[dim]Precheck repo cloned, but Docker image was not pulled.[/dim]" )
2797- else :
2798- console .print ("[cyan]Pulling precheck Docker image...[/cyan]" )
2799- subprocess .run (
2800- ['docker' , 'pull' , 'chipfoundry/mpw_precheck:latest' ],
2801- check = True ,
2802- capture_output = True
2803- )
2804- console .print ("[green]✓[/green] Precheck Docker image ready" )
2805-
2773+ console .print ("[cyan]Pulling precheck Docker image...[/cyan]" )
2774+ subprocess .run (
2775+ ['docker' , 'pull' , 'chipfoundry/mpw_precheck:latest' ],
2776+ check = True ,
2777+ capture_output = True
2778+ )
2779+ console .print ("[green]✓[/green] Precheck Docker image ready" )
28062780 except subprocess .CalledProcessError as e :
28072781 maybe_abort_no_space (e , "Precheck install" )
28082782 had_errors = True
2809- console .print (f"[red]✗[/red] Failed to install precheck: { e } " )
2783+ console .print (f"[red]✗[/red] Failed to pull precheck image : { e } " )
28102784 if e .stderr :
28112785 console .print (f"[dim]{ e .stderr } [/dim]" )
2812- except OSError as e :
2813- had_errors = True
2814- console .print (f"[red]✗[/red] Failed to install precheck: { e } " )
28152786
28162787 # Summary
28172788 console .print ("\n " + "=" * 60 )
@@ -3216,21 +3187,22 @@ def repo_update(project_root, repo_owner, repo_name, branch, dry_run):
32163187
32173188@main .command ('precheck' )
32183189@click .option ('--project-root' , type = click .Path (exists = True , file_okay = False ), help = 'Path to the project directory (defaults to current directory)' )
3219- @click .option ('--disable-lvs' , is_flag = True , help = 'Disable LVS check and run specific checks only' )
3190+ @click .option ('--skip-checks' , multiple = True , help = 'Checks to skip (can be specified multiple times)' )
3191+ @click .option ('--magic-drc' , is_flag = True , help = 'Include Magic DRC check (optional, off by default)' )
32203192@click .option ('--checks' , multiple = True , help = 'Specific checks to run (can be specified multiple times)' )
32213193@click .option ('--dry-run' , is_flag = True , help = 'Show the command without running' )
3222- def precheck (project_root , disable_lvs , checks , dry_run ):
3223- """Run mpw_precheck validation on the project.
3194+ def precheck (project_root , skip_checks , magic_drc , checks , dry_run ):
3195+ """Run precheck validation on the project.
32243196
3225- This runs the MPW (Multi-Project Wafer) precheck tool to validate
3226- your design before submission.
3197+ This runs the cf- precheck tool to validate your design before
3198+ submission.
32273199
32283200 Examples:
3229- cf precheck # Run all checks
3230- cf precheck --disable-lvs # Skip LVS, run specific checks
3231- cf precheck --checks license --checks makefile # Run specific checks
3201+ cf precheck # Run all checks
3202+ cf precheck --skip-checks lvs # Skip LVS check
3203+ cf precheck --magic-drc # Include optional Magic DRC
3204+ cf precheck --checks topcell_check # Run specific checks only
32323205 """
3233- # If .cf/project.json exists in cwd, use it as default project_root
32343206 cwd_root , _ = get_project_json_from_cwd ()
32353207 if not project_root and cwd_root :
32363208 project_root = cwd_root
@@ -3239,20 +3211,17 @@ def precheck(project_root, disable_lvs, checks, dry_run):
32393211
32403212 project_root_path = Path (project_root )
32413213
3242- # Check if project is initialized (allow graceful return)
32433214 if not check_project_initialized (project_root_path , 'precheck' , dry_run = dry_run , allow_graceful = True ):
32443215 console .print (f"[red]✗[/red] Project not initialized. Please run 'cf init' first." )
32453216 console .print ("[yellow]Dependencies are required before running precheck.[/yellow]" )
32463217 return
32473218
32483219 project_json_path = project_root_path / '.cf' / 'project.json'
32493220
3250- # Check project type - GPIO config not needed for openframe
32513221 with open (project_json_path , 'r' ) as f :
32523222 project_data = json .load (f )
32533223 project_type = project_data .get ('project' , {}).get ('type' , 'digital' )
32543224
3255- # Check if GPIO configuration exists (not needed for openframe)
32563225 if project_type != 'openframe' :
32573226 gpio_config = get_gpio_config_from_project_json (str (project_json_path ))
32583227 if not gpio_config or len (gpio_config ) == 0 :
@@ -3261,10 +3230,8 @@ def precheck(project_root, disable_lvs, checks, dry_run):
32613230 console .print ("[cyan]Please run 'cf gpio-config' to configure GPIO settings first.[/cyan]" )
32623231 raise click .Abort ()
32633232
3264- precheck_root = Path .home () / 'mpw_precheck'
32653233 pdk_root = project_root_path / 'dependencies' / 'pdks'
32663234
3267- # Detect PDK from project.json
32683235 pdk = 'sky130A'
32693236 if project_json_path .exists ():
32703237 try :
@@ -3274,124 +3241,79 @@ def precheck(project_root, disable_lvs, checks, dry_run):
32743241 except :
32753242 pass
32763243
3277- # Check if precheck is installed
3278- if not precheck_root .exists ():
3279- console .print (f"[red]✗[/red] mpw_precheck not found at { precheck_root } " )
3280- console .print ("[yellow]Run 'cf setup --only-precheck' to install[/yellow]" )
3281- return
3282-
3283- # Check if PDK exists
32843244 if not (pdk_root / pdk ).exists ():
32853245 console .print (f"[red]✗[/red] PDK not found at { pdk_root / pdk } " )
32863246 console .print ("[yellow]Run 'cf setup --only-pdk' to install[/yellow]" )
32873247 return
32883248
3289- # Check Docker availability
3290- docker_available = shutil .which ('docker' ) is not None
3291- if not docker_available :
3249+ if shutil .which ('docker' ) is None :
32923250 console .print ("[red]✗[/red] Docker not found. Docker is required to run precheck." )
32933251 return
32943252
3295- # Build the checks list
3296- if checks :
3297- # User specified custom checks
3298- checks_list = list (checks )
3299- elif disable_lvs :
3300- # Default checks when LVS is disabled
3301- checks_list = [
3302- 'license' , 'makefile' , 'default' , 'documentation' , 'consistency' ,
3303- 'gpio_defines' , 'xor' , 'magic_drc' , 'klayout_feol' , 'klayout_beol' ,
3304- 'klayout_offgrid' , 'klayout_met_min_ca_density' ,
3305- 'klayout_pin_label_purposes_overlapping_drawing' , 'klayout_zeroarea'
3306- ]
3307- else :
3308- # All checks (default behavior)
3309- checks_list = []
3310-
3311- # Display configuration
3312- console .print ("\n " + "=" * 60 )
3313- console .print ("[bold cyan]MPW Precheck[/bold cyan]" )
3314- console .print (f"Project: [yellow]{ project_root_path } [/yellow]" )
3315- console .print (f"PDK: [yellow]{ pdk } [/yellow]" )
3316- if disable_lvs :
3317- console .print ("Mode: [yellow]LVS disabled[/yellow]" )
3318- if checks_list :
3319- console .print (f"Checks: [yellow]{ ', ' .join (checks_list )} [/yellow]" )
3320- else :
3321- console .print ("Checks: [yellow]All checks[/yellow]" )
3322- console .print ("=" * 60 + "\n " )
3323-
3324- # Build Docker command
3325- import getpass
3326- import pwd
3327-
3253+ pdk_path = pdk_root / pdk
33283254 user_id = os .getuid ()
33293255 group_id = os .getgid ()
33303256
3331- pdk_path = pdk_root / pdk
3332- pdkpath = pdk_path # Same as PDK_PATH in the Makefile
3333- ipm_dir = Path .home () / '.ipm'
3334-
3335- # Create .ipm directory if it doesn't exist
3336- if not ipm_dir .exists ():
3337- ipm_dir .mkdir (parents = True , exist_ok = True )
3338-
33393257 docker_cmd = [
33403258 'docker' , 'run' , '--rm' ,
3341- '-v' , f'{ precheck_root } :{ precheck_root } ' ,
33423259 '-v' , f'{ project_root_path } :{ project_root_path } ' ,
33433260 '-v' , f'{ pdk_root } :{ pdk_root } ' ,
3344- '-v' , f'{ ipm_dir } :{ ipm_dir } ' ,
3345- '-e' , f'INPUT_DIRECTORY={ project_root_path } ' ,
3346- '-e' , f'PDK_PATH={ pdk_path } ' ,
3347- '-e' , f'PDK_ROOT={ pdk_root } ' ,
3348- '-e' , f'PDKPATH={ pdkpath } ' ,
33493261 '-u' , f'{ user_id } :{ group_id } ' ,
33503262 'chipfoundry/mpw_precheck:latest' ,
3351- 'bash' , '-c' ,
3263+ 'cf-precheck' ,
3264+ '-i' , str (project_root_path ),
3265+ '-p' , str (pdk_path ),
3266+ '-c' , '/opt/caravel' ,
33523267 ]
33533268
3354- # Build the precheck command
3355- precheck_cmd = f'cd { precheck_root } ; python3 mpw_precheck.py --input_directory { project_root_path } --pdk_path { pdk_path } '
3269+ if magic_drc :
3270+ docker_cmd . append ( '--magic-drc' )
33563271
3357- if checks_list :
3358- precheck_cmd += ' ' + ' ' . join ( checks_list )
3272+ if skip_checks :
3273+ docker_cmd . extend ([ '--skip-checks' ] + list ( skip_checks ) )
33593274
3360- docker_cmd .append (precheck_cmd )
3275+ if checks :
3276+ docker_cmd .extend (list (checks ))
3277+
3278+ checks_display = ', ' .join (checks ) if checks else 'All checks'
3279+ console .print ("\n " + "=" * 60 )
3280+ console .print ("[bold cyan]CF Precheck[/bold cyan]" )
3281+ console .print (f"Project: [yellow]{ project_root_path } [/yellow]" )
3282+ console .print (f"PDK: [yellow]{ pdk } [/yellow]" )
3283+ if skip_checks :
3284+ console .print (f"Skipping: [yellow]{ ', ' .join (skip_checks )} [/yellow]" )
3285+ if magic_drc :
3286+ console .print ("Magic DRC: [yellow]enabled[/yellow]" )
3287+ console .print (f"Checks: [yellow]{ checks_display } [/yellow]" )
3288+ console .print ("=" * 60 + "\n " )
33613289
33623290 if dry_run :
33633291 console .print ("[bold yellow]Dry run - would execute:[/bold yellow]\n " )
33643292 console .print ("[dim]" + ' ' .join (docker_cmd ) + "[/dim]" )
33653293 return
33663294
3367- # Run precheck
3368- console .print ("[cyan]Running mpw_precheck...[/cyan]" )
3295+ console .print ("[cyan]Running cf-precheck...[/cyan]\n " )
33693296
33703297 try :
3371- # Use Popen for better signal handling
33723298 process = subprocess .Popen (
33733299 docker_cmd ,
3374- cwd = str (precheck_root ),
33753300 preexec_fn = os .setsid if os .name != 'nt' else None
33763301 )
33773302
3378- # Wait for process to complete
33793303 returncode = process .wait ()
33803304
3381- console .print ("" ) # Add newline
3305+ console .print ("" )
33823306 if returncode == 0 :
33833307 console .print ("[green]✓[/green] Precheck passed!" )
3384- elif returncode == - 2 or returncode == 130 : # SIGINT
3308+ elif returncode == - 2 or returncode == 130 :
33853309 console .print ("[yellow]⚠[/yellow] Precheck interrupted by user" )
33863310 sys .exit (130 )
33873311 else :
3388- console .print (f"[red]✗[/red] Precheck failed with exit code { returncode } " )
3389- console .print (f"[yellow]Check the output above for details[/yellow]" )
3312+ console .print (f"[red]✗[/red] Precheck failed (exit code { returncode } )" )
33903313 sys .exit (returncode )
33913314
33923315 except KeyboardInterrupt :
33933316 console .print ("\n [yellow]⚠[/yellow] Precheck interrupted by user" )
3394- # Try to stop the Docker container gracefully
33953317 try :
33963318 if os .name != 'nt' :
33973319 os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
0 commit comments