blob: b946b336e025fc0333e659470a6c336f21925aed [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.
Timothy Chen8adb20d2021-03-25 16:49:04 -070092 reg_top_suffix = {
93 'alert_handler': '',
94 'clkmgr': '',
95 'flash_ctrl': '_core',
96 'pinmux': '',
97 'pwrmgr': '',
98 'rstmgr': '',
99 'rv_plic': ''
100 }
101
Pirmin Vogel67240592020-12-16 13:54:29 +0100102 if reg_only:
Michael Schaffner43ce8d52021-02-10 17:04:57 -0800103 for ip in ['alert_handler', 'clkmgr', 'flash_ctrl', 'pinmux', 'pwrmgr',
Pirmin Vogel67240592020-12-16 13:54:29 +0100104 'rstmgr', 'rv_plic']:
105 core_filepath = os.path.abspath('generated-%s.core' % ip)
106 name = 'lowrisc:ip:%s_reggen' % ip,
107 files = ['ip/%s/rtl/autogen/%s_reg_pkg.sv' % (ip, ip),
Timothy Chen8adb20d2021-03-25 16:49:04 -0700108 'ip/%s/rtl/autogen/%s_reg_top.sv' % (ip, ip + reg_top_suffix[ip])]
Pirmin Vogel67240592020-12-16 13:54:29 +0100109 generated_core = {
110 'name': '%s' % name,
111 'filesets': {
112 'files_rtl': {
113 'depend': [
114 'lowrisc:ip:tlul',
115 ],
116 'files': files,
117 'file_type': 'systemVerilogSource'
118 },
119 },
120 'targets': {
121 'default': {
122 'filesets': [
123 'files_rtl',
124 ],
125 },
126 },
127 }
128 write_core(core_filepath, generated_core)
129
130 else:
Michael Schaffner93fe50c2021-03-31 16:25:42 -0700131 nameparts = topname.split('_')
132 if nameparts[0] == 'top' and len(nameparts) > 1:
133 chipname = 'chip_' + '_'.join(nameparts[1:])
134 else:
135 chipname = topname
136
Pirmin Vogel67240592020-12-16 13:54:29 +0100137 core_filepath = os.path.abspath('generated-topgen.core')
138 generated_core = {
139 'name': "lowrisc:systems:generated-topgen",
140 'filesets': {
141 'files_rtl': {
142 'depend': [
Michael Schaffner74c4ff22021-03-30 15:43:46 -0700143 # Ibex and OTBN constants
144 'lowrisc:ibex:ibex_pkg',
145 'lowrisc:ip:otbn_pkg',
Pirmin Vogel67240592020-12-16 13:54:29 +0100146 # flash_ctrl
147 'lowrisc:constants:top_pkg',
148 'lowrisc:prim:util',
149 'lowrisc:ip:lc_ctrl_pkg',
150 'lowrisc:ip:pwrmgr_pkg',
151 # rstmgr
152 'lowrisc:prim:clock_mux2',
153 # clkmgr
154 'lowrisc:prim:all',
155 'lowrisc:prim:clock_gating',
156 'lowrisc:prim:clock_buf',
157 'lowrisc:prim:clock_div',
Timothy Chenfa60a602021-03-23 14:29:40 -0700158 'lowrisc:ip:clkmgr_components',
Pirmin Vogel67240592020-12-16 13:54:29 +0100159 # Top
160 # ast and sensor_ctrl not auto-generated, re-used from top_earlgrey
161 'lowrisc:systems:sensor_ctrl',
Timothy Chenea59ad32021-02-03 17:51:38 -0800162 'lowrisc:systems:ast_pkg',
Michael Schaffner74c4ff22021-03-30 15:43:46 -0700163 # TODO: absorb this into AST longerm
164 'lowrisc:systems:clkgen_xil7series',
Pirmin Vogel67240592020-12-16 13:54:29 +0100165 ],
166 'files': [
167 # IPs
Pirmin Vogel67240592020-12-16 13:54:29 +0100168 'ip/clkmgr/rtl/autogen/clkmgr.sv',
169 'ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv',
170 'ip/flash_ctrl/rtl/autogen/flash_ctrl.sv',
171 'ip/rstmgr/rtl/autogen/rstmgr_pkg.sv',
172 'ip/rstmgr/rtl/autogen/rstmgr.sv',
173 'ip/rv_plic/rtl/autogen/rv_plic.sv',
174 # Top
175 'rtl/autogen/%s_rnd_cnst_pkg.sv' % topname,
176 'rtl/autogen/%s_pkg.sv' % topname,
177 'rtl/autogen/%s.sv' % topname,
Michael Schaffner74c4ff22021-03-30 15:43:46 -0700178 # TODO: this is not ideal. we should extract
179 # this info from the target configuration and
180 # possibly generate separate core files for this.
Michael Schaffner93fe50c2021-03-31 16:25:42 -0700181 'rtl/autogen/%s_cw305.sv' % chipname,
Pirmin Vogel67240592020-12-16 13:54:29 +0100182 ],
183 'file_type': 'systemVerilogSource'
184 },
185 },
186 'targets': {
187 'default': {
188 'filesets': [
189 'files_rtl',
190 ],
191 },
192 },
193 }
194 write_core(core_filepath, generated_core)
195
196 return 0
197
198
199if __name__ == "__main__":
200 main()