configure: add configurable i/o
diff --git a/.github/workflows/user_project_ci.yml b/.github/workflows/user_project_ci.yml index 12d29e9..4f4f52a 100644 --- a/.github/workflows/user_project_ci.yml +++ b/.github/workflows/user_project_ci.yml
@@ -60,7 +60,7 @@ - name: fetch verilog and build config run: | - python -m pip install requests PyYAML + python -m pip install requests PyYAML Jinja2 python configure.py --create-user-config - name: harden tiny_user_project
diff --git a/configure.py b/configure.py index ff5d954..6b63250 100755 --- a/configure.py +++ b/configure.py
@@ -9,36 +9,29 @@ import sys import csv import re - +import jinja2 def load_yaml(yaml_file): with open(yaml_file, "r") as stream: return (yaml.safe_load(stream)) -tiny_user_project_v = '''// generated by configure.py -`default_nettype none - -module tiny_user_project( - input [`MPRJ_IO_PADS-1:0] io_in, - output [`MPRJ_IO_PADS-1:0] io_out, - output [`MPRJ_IO_PADS-1:0] io_oeb -); - -// pass input and output pins defined in user_defines.v -{module_name} mod ( - io_in[19:12], - io_out[27:20] -); -// all output enabled -assign io_oeb[27:20] = 8'b0; - -endmodule // tiny_user_project - -`default_nettype wire''' - -def write_user_config(module_name, sources): +def write_user_config(module_name, sources, io_ranges): + env = jinja2.Environment( + loader = jinja2.FileSystemLoader('verilog/rtl') + ) + top_module_template = env.get_template('tiny_user_project.v.jinja2') with open('verilog/rtl/tiny_user_project.v', 'w') as fh: - fh.write(tiny_user_project_v.format(module_name=module_name)) + fh.write(top_module_template.render( + module_name=module_name, + io_in_range=io_ranges[0], + io_out_range=io_ranges[1] + )) + user_defines_template = env.get_template('user_defines.v.jinja2') + with open('verilog/rtl/user_defines.v', 'w') as fh: + fh.write(user_defines_template.render( + io_in_range=io_ranges[0], + io_out_range=io_ranges[1] + )) with open('openlane/tiny_user_project/config.json', 'r') as fh: config_json = json.load(fh) sources.append('verilog/rtl/defines.v') @@ -128,6 +121,10 @@ else: return yaml['project']['top_module'] +def get_io_ranges(yaml, gpio_base=5): + input_range = (gpio_base, gpio_base+len(yaml['documentation']['inputs'])) + output_range = (input_range[1], input_range[1]+len(yaml['documentation']['outputs'])) + return (input_range, output_range) def get_stats(): with open('runs/wokwi/reports/metrics.csv') as f: @@ -177,4 +174,5 @@ source_files = get_project_source(config) top_module = get_top_module(config) assert top_module != 'top' - write_user_config(top_module, source_files) + io_ranges = get_io_ranges(config) + write_user_config(top_module, source_files, io_ranges)
diff --git a/openlane/tiny_user_project/config.json b/openlane/tiny_user_project/config.json index 897d83d..3829399 100644 --- a/openlane/tiny_user_project/config.json +++ b/openlane/tiny_user_project/config.json
@@ -2,10 +2,10 @@ "DESIGN_NAME": "tiny_user_project", "DESIGN_IS_CORE": 0, "VERILOG_FILES": [ - "dir::../../verilog/rtl/defines.v", - "dir::../../verilog/rtl/cells.v", - "dir::../../verilog/rtl/user_module.v", - "dir::../../verilog/rtl/tiny_user_project.v" + "dir::../../verilog/rtl/user_module_334445762078310996.v", + "dir::../../verilog/rtl/cells.v", + "dir::../../verilog/rtl/defines.v", + "dir::../../verilog/rtl/tiny_user_project.v" ], "CLOCK_PERIOD": 10, "CLOCK_PORT": "", @@ -14,20 +14,24 @@ "DIE_AREA": "0 0 250 250", "PL_BASIC_PLACEMENT": 1, "PL_TARGET_DENSITY": 0.55, - "VDD_NETS": ["vccd1"], - "GND_NETS": ["vssd1"], + "VDD_NETS": [ + "vccd1" + ], + "GND_NETS": [ + "vssd1" + ], "DIODE_INSERTION_STRATEGY": 4, "RUN_CVC": 1, "RUN_KLAYOUT_XOR": 0, "RUN_KLAYOUT_DRC": 0, "pdk::sky130*": { - "DECAP_CELL": [ - "sky130_fd_sc_hd__decap_3", - "sky130_fd_sc_hd__decap_4", - "sky130_fd_sc_hd__decap_6", - "sky130_fd_sc_hd__decap_8", - "sky130_ef_sc_hd__decap_12" - ], + "DECAP_CELL": [ + "sky130_fd_sc_hd__decap_3", + "sky130_fd_sc_hd__decap_4", + "sky130_fd_sc_hd__decap_6", + "sky130_fd_sc_hd__decap_8", + "sky130_ef_sc_hd__decap_12" + ], "RT_MAX_LAYER": "met4" }, "pdk::gf180mcuC": { @@ -35,4 +39,4 @@ "RT_MAX_LAYER": "Metal4", "SYNTH_MAX_FANOUT": 4 } -} +} \ No newline at end of file
diff --git a/verilog/rtl/tiny_user_project.v b/verilog/rtl/tiny_user_project.v index f8e3149..d00e184 100644 --- a/verilog/rtl/tiny_user_project.v +++ b/verilog/rtl/tiny_user_project.v
@@ -1,6 +1,9 @@ -// generated by configure.py +// Copyright 2022 Google LLC. +// SPDX-License-Identifier: Apache-2.0 `default_nettype none +// tiny_user_project top module instance +// generated by configure.py module tiny_user_project( input [`MPRJ_IO_PADS-1:0] io_in, output [`MPRJ_IO_PADS-1:0] io_out, @@ -9,11 +12,11 @@ // pass input and output pins defined in user_defines.v user_module_334445762078310996 mod ( - io_in[19:12], - io_out[27:20] + io_in[12:5], + io_out[20:13] ); // all output enabled -assign io_oeb[27:20] = 8'b0; +assign io_oeb[20:13] = 8'b0; endmodule // tiny_user_project
diff --git a/verilog/rtl/tiny_user_project.v.jinja2 b/verilog/rtl/tiny_user_project.v.jinja2 new file mode 100644 index 0000000..8dc53cc --- /dev/null +++ b/verilog/rtl/tiny_user_project.v.jinja2
@@ -0,0 +1,23 @@ +// Copyright 2022 Google LLC. +// SPDX-License-Identifier: Apache-2.0 +`default_nettype none + +// tiny_user_project top module instance +// generated by configure.py +module tiny_user_project( + input [`MPRJ_IO_PADS-1:0] io_in, + output [`MPRJ_IO_PADS-1:0] io_out, + output [`MPRJ_IO_PADS-1:0] io_oeb +); + +// pass input and output pins defined in user_defines.v +{{ module_name }} mod ( + io_in[{{ io_in_range[1] - 1 }}:{{ io_in_range[0] }}], + io_out[{{ io_out_range[1] - 1 }}:{{ io_out_range[0] }}] +); +// all output enabled +assign io_oeb[{{ io_out_range[1] - 1 }}:{{ io_out_range[0] }}] = 8'b0; + +endmodule // tiny_user_project + +`default_nettype wire \ No newline at end of file
diff --git a/verilog/rtl/user_defines.v b/verilog/rtl/user_defines.v index 7a38e03..c749b72 100644 --- a/verilog/rtl/user_defines.v +++ b/verilog/rtl/user_defines.v
@@ -52,34 +52,33 @@ // up in a state that can be used immediately without depending on // the management SoC to run a startup program to configure the GPIOs. -`define USER_CONFIG_GPIO_5_INIT `GPIO_MODE_INVALID -`define USER_CONFIG_GPIO_6_INIT `GPIO_MODE_INVALID -`define USER_CONFIG_GPIO_7_INIT `GPIO_MODE_INVALID -`define USER_CONFIG_GPIO_8_INIT `GPIO_MODE_INVALID -`define USER_CONFIG_GPIO_9_INIT `GPIO_MODE_INVALID -`define USER_CONFIG_GPIO_10_INIT `GPIO_MODE_INVALID -`define USER_CONFIG_GPIO_11_INIT `GPIO_MODE_INVALID +// tiny_user_project i/o +// generated by configure.py -// tinytapeout project input + +`define USER_CONFIG_GPIO_5_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL +`define USER_CONFIG_GPIO_6_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL +`define USER_CONFIG_GPIO_7_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL +`define USER_CONFIG_GPIO_8_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL +`define USER_CONFIG_GPIO_9_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL +`define USER_CONFIG_GPIO_10_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL +`define USER_CONFIG_GPIO_11_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL `define USER_CONFIG_GPIO_12_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL -`define USER_CONFIG_GPIO_13_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL -`define USER_CONFIG_GPIO_14_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL -`define USER_CONFIG_GPIO_15_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL -`define USER_CONFIG_GPIO_16_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL -`define USER_CONFIG_GPIO_17_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL -`define USER_CONFIG_GPIO_18_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL -`define USER_CONFIG_GPIO_19_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL - -// tinytapeout project output +`define USER_CONFIG_GPIO_13_INIT `GPIO_MODE_USER_STD_OUTPUT +`define USER_CONFIG_GPIO_14_INIT `GPIO_MODE_USER_STD_OUTPUT +`define USER_CONFIG_GPIO_15_INIT `GPIO_MODE_USER_STD_OUTPUT +`define USER_CONFIG_GPIO_16_INIT `GPIO_MODE_USER_STD_OUTPUT +`define USER_CONFIG_GPIO_17_INIT `GPIO_MODE_USER_STD_OUTPUT +`define USER_CONFIG_GPIO_18_INIT `GPIO_MODE_USER_STD_OUTPUT +`define USER_CONFIG_GPIO_19_INIT `GPIO_MODE_USER_STD_OUTPUT `define USER_CONFIG_GPIO_20_INIT `GPIO_MODE_USER_STD_OUTPUT -`define USER_CONFIG_GPIO_21_INIT `GPIO_MODE_USER_STD_OUTPUT -`define USER_CONFIG_GPIO_22_INIT `GPIO_MODE_USER_STD_OUTPUT -`define USER_CONFIG_GPIO_23_INIT `GPIO_MODE_USER_STD_OUTPUT -`define USER_CONFIG_GPIO_24_INIT `GPIO_MODE_USER_STD_OUTPUT -`define USER_CONFIG_GPIO_25_INIT `GPIO_MODE_USER_STD_OUTPUT -`define USER_CONFIG_GPIO_26_INIT `GPIO_MODE_USER_STD_OUTPUT -`define USER_CONFIG_GPIO_27_INIT `GPIO_MODE_USER_STD_OUTPUT - +`define USER_CONFIG_GPIO_21_INIT `GPIO_MODE_INVALID +`define USER_CONFIG_GPIO_22_INIT `GPIO_MODE_INVALID +`define USER_CONFIG_GPIO_23_INIT `GPIO_MODE_INVALID +`define USER_CONFIG_GPIO_24_INIT `GPIO_MODE_INVALID +`define USER_CONFIG_GPIO_25_INIT `GPIO_MODE_INVALID +`define USER_CONFIG_GPIO_26_INIT `GPIO_MODE_INVALID +`define USER_CONFIG_GPIO_27_INIT `GPIO_MODE_INVALID `define USER_CONFIG_GPIO_28_INIT `GPIO_MODE_INVALID `define USER_CONFIG_GPIO_29_INIT `GPIO_MODE_INVALID `define USER_CONFIG_GPIO_30_INIT `GPIO_MODE_INVALID @@ -91,4 +90,4 @@ `define USER_CONFIG_GPIO_36_INIT `GPIO_MODE_INVALID `define USER_CONFIG_GPIO_37_INIT `GPIO_MODE_INVALID -`endif // __USER_DEFINES_H +`endif // __USER_DEFINES_H \ No newline at end of file
diff --git a/verilog/rtl/user_defines.v.jinja2 b/verilog/rtl/user_defines.v.jinja2 new file mode 100644 index 0000000..c935c87 --- /dev/null +++ b/verilog/rtl/user_defines.v.jinja2
@@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`ifndef __USER_DEFINES_H +// User GPIO initial configuration parameters +`define __USER_DEFINES_H + +// deliberately erroneous placeholder value; user required to config GPIO's to other +`define GPIO_MODE_INVALID 13'hXXXX + +// Authoritive source of these MODE defs is: caravel/verilog/rtl/user_defines.v +// Useful GPIO mode values. These match the names used in defs.h. +// +`define GPIO_MODE_MGMT_STD_INPUT_NOPULL 13'h0403 +`define GPIO_MODE_MGMT_STD_INPUT_PULLDOWN 13'h0c01 +`define GPIO_MODE_MGMT_STD_INPUT_PULLUP 13'h0801 +`define GPIO_MODE_MGMT_STD_OUTPUT 13'h1809 +`define GPIO_MODE_MGMT_STD_BIDIRECTIONAL 13'h1801 +`define GPIO_MODE_MGMT_STD_ANALOG 13'h000b + +`define GPIO_MODE_USER_STD_INPUT_NOPULL 13'h0402 +`define GPIO_MODE_USER_STD_INPUT_PULLDOWN 13'h0c00 +`define GPIO_MODE_USER_STD_INPUT_PULLUP 13'h0800 +`define GPIO_MODE_USER_STD_OUTPUT 13'h1808 +`define GPIO_MODE_USER_STD_BIDIRECTIONAL 13'h1800 +`define GPIO_MODE_USER_STD_OUT_MONITORED 13'h1802 +`define GPIO_MODE_USER_STD_ANALOG 13'h000a + +// The power-on configuration for GPIO 0 to 4 is fixed and cannot be +// modified (allowing the SPI and debug to always be accessible unless +// overridden by a flash program). + +// The values below can be any of the standard types defined above, +// or they can be any 13-bit value if the user wants a non-standard +// startup state for the GPIO. By default, every GPIO from 5 to 37 +// is set to power up as an input controlled by the management SoC. +// Users may want to redefine these so that the user project powers +// up in a state that can be used immediately without depending on +// the management SoC to run a startup program to configure the GPIOs. + +// tiny_user_project i/o +// generated by configure.py + +{% for n in range(5, 38) -%} +{%- if io_in_range[0] <= n < io_in_range[1] %} +`define USER_CONFIG_GPIO_{{ n }}_INIT `GPIO_MODE_USER_STD_INPUT_NOPULL +{%- elif io_out_range[0] <= n < io_out_range[1] %} +`define USER_CONFIG_GPIO_{{ n }}_INIT `GPIO_MODE_USER_STD_OUTPUT +{%- else %} +`define USER_CONFIG_GPIO_{{ n }}_INIT `GPIO_MODE_INVALID +{%- endif -%} +{% endfor %} + +`endif // __USER_DEFINES_H