1212import re
1313from pathlib import Path
1414from typing import Dict , Set , Tuple , Optional
15- from jsonschema import validate
16- from jsonschema .exceptions import ValidationError
1715import json5
1816from apio .utils import proto_util
1917from apio .common .apio_console import cout , cerror
2018from apio .common .proto .apio_definitions_pb2 import (
2119 BoardDefinition ,
2220 FpgaDefinition ,
21+ ProgrammerDefinition ,
2322)
2423
2524# -- Boards definitions file name.
3231PROGRAMMERS_JSONC = "programmers.jsonc"
3332
3433# -- A regex for validating boards, fpgas, and programmers ids.
35- ID_FORMAT = re .compile (r"^[a-z][a-z0-9-]*$" )
36-
37-
38- # -- JSON schema for validating a single fpga definition in fpga.jsonc.
39- # -- The fields 'part-num' and 'size' are for information only.
40- FPGA_SCHEMA = schema = {
41- "$schema" : "http://json-schema.org/draft-07/schema#" ,
42- "type" : "object" ,
43- "properties" : {
44- "part-num" : {"type" : "string" },
45- "arch" : {
46- "type" : "string" ,
47- "enum" : ["ice40" , "ecp5" , "gowin" , "xilinx" ],
48- },
49- "size" : {"type" : "string" },
50- "ice40-params" : {
51- "type" : "object" ,
52- "properties" : {
53- "type" : {"type" : "string" },
54- "package" : {"type" : "string" },
55- },
56- "required" : ["type" , "package" ],
57- "additionalProperties" : False ,
58- },
59- "ecp5-params" : {
60- "type" : "object" ,
61- "properties" : {
62- "type" : {"type" : "string" },
63- "package" : {"type" : "string" },
64- "speed" : {"type" : "string" },
65- },
66- "required" : ["type" , "package" , "speed" ],
67- "additionalProperties" : False ,
68- },
69- "gowin-params" : {
70- "type" : "object" ,
71- "properties" : {
72- "yosys-family" : {"type" : "string" },
73- "nextpnr-family" : {"type" : "string" },
74- "packer-device" : {"type" : "string" },
75- },
76- "required" : ["yosys-family" , "nextpnr-family" , "packer-device" ],
77- "additionalProperties" : False ,
78- },
79- "xilinx-params" : {
80- "type" : "object" ,
81- "properties" : {
82- "family" : {"type" : "string" },
83- "yosys-arch" : {"type" : "string" },
84- "package" : {"type" : "string" },
85- "speed" : {"type" : "string" },
86- },
87- "required" : ["family" , "yosys-arch" , "package" , "speed" ],
88- "additionalProperties" : False ,
89- },
90- },
91- "required" : ["part-num" , "arch" , "size" ],
92- "additionalProperties" : False ,
93- }
94-
95-
96- # -- JSON schema for validating a single programmer definition in
97- # -- programmers.jsonc.
98- PROGRAMMER_SCHEMA = {
99- "$schema" : "http://json-schema.org/draft-07/schema#" ,
100- "type" : "object" ,
101- "required" : ["command" , "args" ],
102- "properties" : {"command" : {"type" : "string" }, "args" : {"type" : "string" }},
103- "additionalProperties" : False ,
104- }
34+ DEFINITION_ID_FORMAT = re .compile (r"^[a-z][a-z0-9-]*$" )
10535
10636
10737class ApioDefinitions :
10838 """Contains the apio definitions in the form of json dictionaries."""
10939
11040 # pylint: disable=too-many-instance-attributes
111- # pylint: disable=too-many-locals
11241
11342 def __init__ (
11443 self ,
@@ -146,7 +75,7 @@ def __init__(
14675 # -- Validate boards definitions. Optional project custom definition
14776 # -- supersede apio standard definitions.
14877 for board_id in self .boards :
149- if not ID_FORMAT .match (board_id ):
78+ if not DEFINITION_ID_FORMAT .match (board_id ):
15079 cerror (f"Board id has an invalid format: { board_id } " )
15180 sys .exit (1 )
15281
@@ -169,7 +98,7 @@ def __init__(
16998
17099 # -- Validate fpgas definitions.
171100 for fpga_id , fpga_definition in self .fpgas .items ():
172- if not ID_FORMAT .match (fpga_id ):
101+ if not DEFINITION_ID_FORMAT .match (fpga_id ):
173102 cerror (f"FPGA id has an invalid format: { fpga_id } " )
174103 sys .exit (1 )
175104 proto_util .check_is_required (fpga_definition , "part_num" )
@@ -185,25 +114,27 @@ def __init__(
185114
186115 # -- Load programmers definitions. Optional project custom definition
187116 # -- supersede apio standard definitions.
188- self . programmers , self .custom_programmers_ids = self ._load_definitions (
117+ programmers_json , self .custom_programmers_ids = self ._load_definitions (
189118 PROGRAMMERS_JSONC ,
190119 self ._package_definitions_dir ,
191120 self ._project_definitions_dir ,
192121 )
193122
123+ # -- Convert the programmers definition dicts to FpgaDefinition protos.
124+ self .programmers : Dict [str , ProgrammerDefinition ] = {}
125+ for programmer_id , definition_dict in programmers_json .items ():
126+ definition = proto_util .proto_from_json_dict (
127+ definition_dict ,
128+ ProgrammerDefinition ,
129+ f"Failed to parse programmer definition '{ programmer_id } " ,
130+ )
131+ self .programmers [programmer_id ] = definition
132+
194133 # -- Validate programmers definitions.
195- for programmer_id , programmer_info in self .programmers . items () :
196- if not ID_FORMAT .match (programmer_id ):
134+ for programmer_id in self .programmers :
135+ if not DEFINITION_ID_FORMAT .match (programmer_id ):
197136 cerror (f"Programmer id has an invalid format: { programmer_id } " )
198137 sys .exit (1 )
199- try :
200- validate (instance = programmer_info , schema = PROGRAMMER_SCHEMA )
201- except ValidationError as e :
202- cerror (
203- f"Invalid programmer definition [{ programmer_id } ]: "
204- f"{ e .message } "
205- )
206- sys .exit (1 )
207138
208139 # -- Check references from boards to fpga and programmers
209140 for board_id , board_definition in self .boards .items ():
0 commit comments