blob: 419dfc9fd9f1b582fce51cfa408aca0e65420f5f [file] [log] [blame]
Pirmin Vogel67240592020-12-16 13:54:29 +01001#!/usr/bin/env python3
2# Copyright lowRISC contributors.
3# Licensed under the Apache License, Version 2.0, see LICENSE for details.
4# SPDX-License-Identifier: Apache-2.0
5r"""FuseSoC wrapper for Top Module Generator
6
7This wrapper is called by FuseSoC. It extracts the arguments for topgen from the auto-generated
8GAPI file and creates a core file for the generated sources.
9"""
10import sys
11import yaml
12import subprocess
13import os
14
15try:
16 from yaml import CSafeLoader as YamlLoader, CSafeDumper as YamlDumper
17except ImportError:
18 from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper
19
20
21def _check_gapi(gapi):
22 if 'cores' not in gapi:
23 print("Key 'cores' not found in GAPI structure. "
24 "Install a compatible version with "
25 "'pip3 install --user -r python-requirements.txt'.")
26 return False
27 return True
28
29
30def write_core(core_filepath, generated_core):
31 with open(core_filepath, 'w') as f:
32 # FuseSoC requires this line to appear first in the YAML file.
33 # Inserting this line through the YAML serializer requires ordered dicts
34 # to be used everywhere, which is annoying syntax-wise on Python <3.7,
35 # where native dicts are not sorted.
36 f.write('CAPI=2:\n')
37 yaml.dump(generated_core,
38 f,
39 encoding="utf-8",
Pirmin Vogel67240592020-12-16 13:54:29 +010040 Dumper=YamlDumper)
41 print("Core file written to %s" % (core_filepath, ))
42
43
44def main():
45
46 # Extract arguments from GAPI file.
47 gapi_filepath = sys.argv[1]
48 with open(gapi_filepath) as f:
49 gapi = yaml.load(f, Loader=YamlLoader)
50
51 if not _check_gapi(gapi):
52 sys.exit(1)
53
54 files_root = ""
55 if 'files_root' in gapi:
56 files_root = gapi['files_root']
57
58 topname = ""
59 if 'parameters' in gapi and 'topname' in gapi['parameters']:
60 topname = gapi['parameters']['topname']
61
62 reg_only = ""
63 if 'parameters' in gapi and 'reg-only' in gapi['parameters']:
64 reg_only = gapi['parameters']['reg-only']
65
66 # Call topgen.
67 files_data = files_root + "/hw/" + topname + "/data/"
68 files_out = os.getcwd()
69 cmd = [files_root + "/util/topgen.py", # "--verbose",
70 "-t", files_data + topname + ".hjson",
Pirmin Vogel67240592020-12-16 13:54:29 +010071 "-o", files_out]
72 try:
73 print("Running topgen.")
74 subprocess.run(cmd,
75 check=True,
76 stdout=subprocess.PIPE,
77 stderr=subprocess.STDOUT,
78 universal_newlines=True)
79
80 except subprocess.CalledProcessError as e:
81 print("topgen failed: " + str(e))
Philipp Wagner4fe07f92021-03-15 11:06:11 +000082 print(e.stdout)
Pirmin Vogel67240592020-12-16 13:54:29 +010083 sys.exit(1)
84
85 # Create core files.
86 print("Creating core files.")
87
88 # For some cores such IP package files, we need a separate dependency for the register file.
89 # Combining this with the generated topgen core file below leads to cyclic dependencies. For
90 # example, flash_ctrl depends on topgen but also on pwrmgr_pkg which depends on
91 # pwrmgr_reg_pkg generated by topgen.
92 if reg_only:
Michael Schaffner43ce8d52021-02-10 17:04:57 -080093 for ip in ['alert_handler', 'clkmgr', 'flash_ctrl', 'pinmux', 'pwrmgr',
Pirmin Vogel67240592020-12-16 13:54:29 +010094 'rstmgr', 'rv_plic']:
95 core_filepath = os.path.abspath('generated-%s.core' % ip)
96 name = 'lowrisc:ip:%s_reggen' % ip,
97 files = ['ip/%s/rtl/autogen/%s_reg_pkg.sv' % (ip, ip),
98 'ip/%s/rtl/autogen/%s_reg_top.sv' % (ip, ip)]
99 generated_core = {
100 'name': '%s' % name,
101 'filesets': {
102 'files_rtl': {
103 'depend': [
104 'lowrisc:ip:tlul',
105 ],
106 'files': files,
107 'file_type': 'systemVerilogSource'
108 },
109 },
110 'targets': {
111 'default': {
112 'filesets': [
113 'files_rtl',
114 ],
115 },
116 },
117 }
118 write_core(core_filepath, generated_core)
119
120 else:
121 core_filepath = os.path.abspath('generated-topgen.core')
122 generated_core = {
123 'name': "lowrisc:systems:generated-topgen",
124 'filesets': {
125 'files_rtl': {
126 'depend': [
127 # flash_ctrl
128 'lowrisc:constants:top_pkg',
129 'lowrisc:prim:util',
130 'lowrisc:ip:lc_ctrl_pkg',
131 'lowrisc:ip:pwrmgr_pkg',
132 # rstmgr
133 'lowrisc:prim:clock_mux2',
134 # clkmgr
135 'lowrisc:prim:all',
136 'lowrisc:prim:clock_gating',
137 'lowrisc:prim:clock_buf',
138 'lowrisc:prim:clock_div',
139 # Top
140 # ast and sensor_ctrl not auto-generated, re-used from top_earlgrey
141 'lowrisc:systems:sensor_ctrl',
Timothy Chenea59ad32021-02-03 17:51:38 -0800142 'lowrisc:systems:ast_pkg',
Pirmin Vogel67240592020-12-16 13:54:29 +0100143 ],
144 'files': [
145 # IPs
146 'ip/clkmgr/rtl/autogen/clkmgr_pkg.sv',
147 'ip/clkmgr/rtl/autogen/clkmgr.sv',
148 'ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv',
149 'ip/flash_ctrl/rtl/autogen/flash_ctrl.sv',
150 'ip/rstmgr/rtl/autogen/rstmgr_pkg.sv',
151 'ip/rstmgr/rtl/autogen/rstmgr.sv',
152 'ip/rv_plic/rtl/autogen/rv_plic.sv',
153 # Top
154 'rtl/autogen/%s_rnd_cnst_pkg.sv' % topname,
155 'rtl/autogen/%s_pkg.sv' % topname,
156 'rtl/autogen/%s.sv' % topname,
157 ],
158 'file_type': 'systemVerilogSource'
159 },
160 },
161 'targets': {
162 'default': {
163 'filesets': [
164 'files_rtl',
165 ],
166 },
167 },
168 }
169 write_core(core_filepath, generated_core)
170
171 return 0
172
173
174if __name__ == "__main__":
175 main()