11# SPDX-License-Identifier: BSD-2-Clause
2-
3- import os
4- import sys
5- import inspect
6- import importlib
72import argparse
8- import tomli
9- import jsonschema
10-
11- from . import ChipFlowError
12-
13-
14- def _get_cls_by_reference (reference , context ):
15- module_ref , _ , class_ref = reference .partition (":" )
16- try :
17- module_obj = importlib .import_module (module_ref )
18- except ModuleNotFoundError as e :
19- raise ChipFlowError (f"Module `{ module_ref } ` referenced by { context } is not found" )
20- try :
21- return getattr (module_obj , class_ref )
22- except AttributeError as e :
23- raise ChipFlowError (f"Module `{ module_ref } ` referenced by { context } does not define "
24- f"`{ class_ref } `" ) from None
25-
26-
27- def _ensure_chipflow_root ():
28- if "CHIPFLOW_ROOT" not in os .environ :
29- os .environ ["CHIPFLOW_ROOT" ] = os .getcwd ()
30- if os .environ ["CHIPFLOW_ROOT" ] not in sys .path :
31- sys .path .append (os .environ ["CHIPFLOW_ROOT" ])
32- return os .environ ["CHIPFLOW_ROOT" ]
33-
34-
35- config_schema = {
36- "$schema" : "https://json-schema.org/draft/2020-12/schema" ,
37- "$id" : "https://chipflow.io/meta/chipflow.toml.schema.json" ,
38- "title" : "chipflow.toml" ,
39- "type" : "object" ,
40- "required" : [
41- "chipflow"
42- ],
43- "properties" : {
44- "chipflow" : {
45- "type" : "object" ,
46- "required" : [
47- "steps" ,
48- "silicon"
49- ],
50- "additionalProperties" : False ,
51- "properties" : {
52- "project_name" : {
53- "type" : "string" ,
54- },
55- "top" : {
56- "type" : "object" ,
57- },
58- "steps" : {
59- "type" : "object" ,
60- },
61- "silicon" : {
62- "type" : "object" ,
63- "required" : [
64- "process" ,
65- "pad_ring" ,
66- "pads" ,
67- ],
68- "additionalProperties" : False ,
69- "properties" : {
70- "process" : {
71- "enum" : ["sky130" , "gf180" , "customer1" , "gf130bcd" , "ihp_sg13g2" ]
72- },
73- "pad_ring" : {
74- "enum" : ["caravel" , "cf20" , "pga144" ]
75- },
76- "pads" : { "$ref" : "#/$defs/pin" },
77- "clocks" : {
78- "type" : "object" ,
79- "patternPropertues" : {
80- ".+" : { "type" : "string" }
81- },
82- },
83- "reset" : { "type" : "string" },
84- "power" : {
85- "type" : "object" ,
86- "additionalProperties" : False ,
87- "patternProperties" : {
88- ".+" : {
89- "type" : "object" ,
90- "required" : [
91- "loc" ,
92- ],
93- "additionalProperties" : False ,
94- "properties" : {
95- "loc" : {
96- "type" : "string" ,
97- "pattern" : "^[NSWE]?[0-9]+$"
98- },
99- }
100- }
101- }
102- },
103-
104- },
105- },
106- },
107- },
108- },
109- "$defs" : {
110- "pin" : {
111- "type" : "object" ,
112- "additionalProperties" : False ,
113- "minProperties" : 1 ,
114- "patternProperties" : {
115- ".+" : {
116- "type" : "object" ,
117- "required" : [
118- "type" ,
119- "loc" ,
120- ],
121- "additionalProperties" : False ,
122- "properties" : {
123- "type" : {
124- "enum" : ["io" , "i" , "o" , "oe" , "clk" ]
125- },
126- "loc" : {
127- "type" : "string" ,
128- "pattern" : "^[NSWE]?[0-9]+$"
129- },
130- }
131- }
132- }
133- }
134- }
135- }
136-
137-
138- def _parse_config ():
139- chipflow_root = _ensure_chipflow_root ()
140- config_file = f"{ chipflow_root } /chipflow.toml"
141- return _parse_config_file (config_file )
3+ import inspect
4+ import sys
5+ import traceback
1426
7+ from pprint import pformat
1438
144- def _parse_config_file (config_file ):
145- with open (config_file , "rb" ) as f :
146- config_dict = tomli .load (f )
9+ from . import (
10+ ChipFlowError ,
11+ _get_cls_by_reference ,
12+ _ensure_chipflow_root ,
13+ _parse_config ,
14+ _parse_config_file
15+ )
16+ from .pin_lock import PinCommand
14717
148- try :
149- jsonschema .validate (config_dict , config_schema )
150- return config_dict
151- except jsonschema .ValidationError as e :
152- raise ChipFlowError (f"Syntax error in `chipflow.toml` at `{ '.' .join (e .path )} `: { e .message } " )
15318
19+ class UnexpectedError (ChipFlowError ):
20+ pass
15421
15522def run (argv = sys .argv [1 :]):
15623 config = _parse_config ()
15724
158- steps = {}
25+ commands = {}
26+ commands ["pin" ] = PinCommand (config )
27+
15928 for step_name , step_reference in config ["chipflow" ]["steps" ].items ():
16029 step_cls = _get_cls_by_reference (step_reference , context = f"step `{ step_name } `" )
16130 try :
162- steps [step_name ] = step_cls (config )
31+ commands [step_name ] = step_cls (config )
16332 except Exception :
16433 raise ChipFlowError (f"Encountered error while initializing step `{ step_name } ` "
16534 f"using `{ step_reference } `" )
16635
16736 parser = argparse .ArgumentParser ()
168- step_argument = parser .add_subparsers (dest = "step " , required = True )
169- for step_name , step_cls in steps .items ():
170- step_subparser = step_argument .add_parser (step_name , help = inspect .getdoc (step_cls ))
37+ command_argument = parser .add_subparsers (dest = "command " , required = True )
38+ for command_name , command in commands .items ():
39+ command_subparser = command_argument .add_parser (command_name , help = inspect .getdoc (command ))
17140 try :
172- step_cls .build_cli_parser (step_subparser )
41+ command .build_cli_parser (command_subparser )
17342 except Exception :
17443 raise ChipFlowError (f"Encountered error while building CLI argument parser for "
175- f"step `{ step_name } `" )
44+ f"step `{ command_name } `" )
17645
177- pins = parser .add_subparsers ("pins" )
178- lock = lock .add_subparsers ("lock" )
17946 args = parser .parse_args (argv )
180- try :
181- steps [args .step ].run_cli (args )
182- except ChipFlowError :
183- raise
184- except Exception :
185- raise ChipFlowError (f"Encountered error while running CLI for step `{ args .step } `" )
186-
18747
188- if __name__ == '__main__' :
189- run ()
48+ try :
49+ try :
50+ commands [args .command ].run_cli (args )
51+ except ChipFlowError :
52+ raise
53+ except Exception as e :
54+ raise UnexpectedError (
55+ f"Unexpected error, please report to ChipFlow:\n "
56+ f"args =\n { pformat (args )} \n "
57+ f"traceback =\n { '' .join (traceback .format_exception (e ))} "
58+ ) from e
59+ except ChipFlowError as e :
60+ cmd = args .command
61+ if hasattr (args , "action" ):
62+ cmd += f" { args .action } "
63+ print (f"Error while excuting `{ cmd } `: { e } " )
0 commit comments