blob: 79e64ee554231ecec93800ec61fd091ed0266dd9 [file] [log] [blame]
Rupert Swarbricka23dfec2020-09-07 10:01:28 +01001# Copyright lowRISC contributors.
2# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3# SPDX-License-Identifier: Apache-2.0
4
5import logging as log
6import sys
Philipp Wagnerad629e32021-10-04 20:58:46 +01007import os
Rupert Swarbricka23dfec2020-09-07 10:01:28 +01008
9from CfgJson import load_hjson
10
Cindy Chenf59a6b32021-03-29 11:05:13 -070011import FormalCfg
Michael Schaffnera42582d2021-11-03 13:43:11 -070012import CdcCfg
Eunchan Kimf2f85bd2022-07-13 14:56:26 -070013import RdcCfg
Rupert Swarbricka23dfec2020-09-07 10:01:28 +010014import LintCfg
15import SimCfg
16import SynCfg
17
18
19def _load_cfg(path, initial_values):
20 '''Worker function for make_cfg.
21
22 initial_values is passed to load_hjson (see documentation there).
23
24 Returns a pair (cls, hjson_data) on success or raises a RuntimeError on
25 failure.
26
27 '''
Philipp Wagner6b7a4352021-10-06 15:46:57 +010028 # Set the `self_dir` template variable to the path of the currently
29 # processed Hjson file.
30 assert 'self_dir' in initial_values
31 initial_values['self_dir'] = os.path.dirname(path)
32
Rupert Swarbricka23dfec2020-09-07 10:01:28 +010033 # Start by loading up the hjson file and any included files
34 hjson_data = load_hjson(path, initial_values)
35
36 # Look up the value of flow in the loaded data. This is a required field,
37 # and tells us what sort of FlowCfg to make.
38 flow = hjson_data.get('flow')
39 if flow is None:
40 raise RuntimeError('{!r}: No value for the "flow" key. Are you sure '
41 'this is a dvsim configuration file?'
42 .format(path))
43
44 classes = [
Eunchan Kimf2f85bd2022-07-13 14:56:26 -070045 RdcCfg.RdcCfg,
Michael Schaffnera42582d2021-11-03 13:43:11 -070046 CdcCfg.CdcCfg,
Rupert Swarbricka23dfec2020-09-07 10:01:28 +010047 LintCfg.LintCfg,
48 SynCfg.SynCfg,
Cindy Chenf59a6b32021-03-29 11:05:13 -070049 FormalCfg.FormalCfg,
Rupert Swarbricka23dfec2020-09-07 10:01:28 +010050 SimCfg.SimCfg
51 ]
52 found_cls = None
53 known_types = []
54 for cls in classes:
55 assert cls.flow is not None
56 known_types.append(cls.flow)
57 if cls.flow == flow:
58 found_cls = cls
59 break
60 if found_cls is None:
61 raise RuntimeError('{}: Configuration file sets "flow" to {!r}, but '
62 'this is not a known flow (known: {}).'
63 .format(path, flow, ', '.join(known_types)))
64
65 return (found_cls, hjson_data)
66
67
68def _make_child_cfg(path, args, initial_values):
69 try:
70 cls, hjson_data = _load_cfg(path, initial_values)
71 except RuntimeError as err:
72 log.error(str(err))
73 sys.exit(1)
74
75 # Since this is a child configuration (from some primary configuration),
76 # make sure that we aren't ourselves a primary configuration. We don't need
77 # multi-level hierarchies and this avoids circular dependencies.
78 if 'use_cfgs' in hjson_data:
79 raise RuntimeError('{}: Configuration file has use_cfgs, but is '
80 'itself included from another configuration.'
81 .format(path))
82
83 # Call cls as a constructor. Note that we pass None as the mk_config
84 # argument: this is not supposed to load anything else.
85 return cls(path, hjson_data, args, None)
86
87
88def make_cfg(path, args, proj_root):
89 '''Make a flow config by loading the config file at path
90
91 args is the arguments passed to the dvsim.py tool and proj_root is the top
92 of the project.
93
94 '''
Philipp Wagnerad629e32021-10-04 20:58:46 +010095 initial_values = {
96 'proj_root': proj_root,
97 'self_dir': os.path.dirname(path),
98 }
Rupert Swarbricka23dfec2020-09-07 10:01:28 +010099 if args.tool is not None:
100 initial_values['tool'] = args.tool
101
102 try:
103 cls, hjson_data = _load_cfg(path, initial_values)
104 except RuntimeError as err:
105 log.error(str(err))
106 sys.exit(1)
107
108 def factory(child_path):
109 child_ivs = initial_values.copy()
110 child_ivs['flow'] = hjson_data['flow']
111 return _make_child_cfg(child_path, args, child_ivs)
112
113 return cls(path, hjson_data, args, factory)