Skip to content

Commit

Permalink
added CI for defaults updating
Browse files Browse the repository at this point in the history
  • Loading branch information
marwaneltoukhy committed Oct 8, 2023
1 parent d0fab89 commit 71a2050
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 9 deletions.
28 changes: 27 additions & 1 deletion .github/workflows/update_defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,30 @@ jobs:
curl -o $GITHUB_WORKSPACE/tmp_default_content/README.md -L https://raw.githubusercontent.com/efabless/$repo_name/main/README.md
curl -o $GITHUB_WORKSPACE/tmp_default_content/gds/$gds_name.gds -L https://raw.githubusercontent.com/efabless/$repo_name/main/gds/$gds_name.gds
python3 $GITHUB_WORKSPACE/checks/defaults_check.py -i $GITHUB_WORKSPACE/tmp_default_content -d $GITHUB_WORKSPACE/_default_content
python3 $GITHUB_WORKSPACE/checks/defaults_check.py -i $GITHUB_WORKSPACE/tmp_default_content -d $GITHUB_WORKSPACE/_default_content -t ${{ matrix.design_types }} > $GITHUB_WORKSPACE/defaults.log
vio=$(grep -c "clean" $GITHUB_WORKSPACE/defaults.log)
if [[ $vio -gt 0 ]];
then
cp $GITHUB_WORKSPACE/tmp_default_content/README.md $GITHUB_WORKSPACE/_default_content/README_${{ matrix.design_types }}.md
cp $GITHUB_WORKSPACE/tmp_default_content/gds/$gds_name.gds $GITHUB_WORKSPACE/_default_content/gds/$gds_name.gds
echo "UPDATE_DEFAULTS=1" >> $GITHUB_ENV
else
echo "UPDATE_DEFAULTS=0" >> $GITHUB_ENV
echo No Updates
fi
- name: Create Pull Request
if: ${{ env.UPDATE_DEFAULTS == '1' }}
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: "[BOT] Update Default files"
body: |
This is an automated PR.
See the individual commits for details.
commit-message: |
[BOT] Update Default files
branch: update-branch
delete-branch: true
18 changes: 18 additions & 0 deletions _default_content/README_analog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Caravel Analog User

[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![CI](https://github.com/efabless/caravel_user_project_analog/actions/workflows/user_project_ci.yml/badge.svg)](https://github.com/efabless/caravel_user_project_analog/actions/workflows/user_project_ci.yml) [![Caravan Build](https://github.com/efabless/caravel_user_project_analog/actions/workflows/caravan_build.yml/badge.svg)](https://github.com/efabless/caravel_user_project_analog/actions/workflows/caravan_build.yml)

---

| :exclamation: Important Note |
|-----------------------------------------|

## Please fill in your project documentation in this README.md file


:warning: | Use this sample project for analog user projects.
:---: | :---

---

Refer to [README](docs/source/index.rst) for this sample project documentation.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
| :exclamation: Important Note |
|-----------------------------------------|

## Please fill in your project documentation in this README.md file
## Please fill in your project documentation in this README.md file

Refer to [README](docs/source/index.rst#section-quickstart) for a quickstart of how to use caravel_user_project

Refer to [README](docs/source/index.rst) for this sample project documentation.

Refer to the following [readthedocs](https://caravel-sim-infrastructure.readthedocs.io/en/latest/index.html) for how to add cocotb tests to your project.
240 changes: 240 additions & 0 deletions _default_content/README_openframe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
OpenFrame Project Example
=====================================

The OpenFrame Project Example is a user project designed to showcase how to use
the Caravel "OpenFrame" design, which is an alternative user project harness
chip that differs from the Caravel and Caravan designs by (1) having no integrated
SoC on chip, (2) allowing access to all GPIO controls, (3) maximizing the user
project area, and (4) minimizing the support circuitry to comprise only the
padframe, a power-on-reset circuit, and a digital ROM containing the 32-bit
project ID. The padframe design and placement of pins matches the Caravel and
Caravan chips. The pin types also remain the same, with power and ground pins
in the same positions, with the same power domains available. Pins which
previously had functions connected with the CPU (flash controller interface,
SPI interface, UART) use the same GPIO pads but allocate them to
general-purpose I/O for any purpose.

One reason for choosing the Openframe harness is to implement an alternative
SoC or implement an SoC with the user project integrated into the same level
of hierarchy. This project example demonstrates that approach, where the
VexRISC CPU from the Caravel and Caravan chips is replaced with a PicoRV32,
which is the same processor core that was used on the first Caravel design
from MPW-one. To facilitate testing, the design maintains the same
special-purpose pins used by Caravel and Caravan, such as (critially) the
flash controller and housekeeping SPI, so that the chip after fabrication
will be fully compatible with the development board shipped by Efabless
with the chips.

The primary difference between this Openframe project example and the
original MPW-one Caravel design is that there is no user project in the
middle, since the whole thing is now the user project. Interfaces that
existed between the SoC core and user project, such as the logic analyzer,
have no meaning in this context and are eliminated. The Wishbone address
space to the user project is eliminated, but the design is free to add
any additional Wishbone modules at any valid memory map location. The
GPIOs are no longer shared between the CPU and the user project. Each
GPIO is therefore configured individually, with a separate Wishbone
interface connecting to each one for configuration and I/O.

Otherwise, this project example does not seek to provide additional
components above and beyond what was already on the Caravel harness chip,
which includes the flash controller, UART, an SPI master, two counter/timers,
housekeeping SPI, and digital locked loop (DLL). It provides only one new
module that groups GPIO signals into a vector that can be written or read
at the same time; that module recovers the function of simultaneous GPIO
reads and writes that was handled in Caravel and Caravan by the housekeeping
module, but was eliminated by moving GPIO configuration to individual
Wishbone interfaces.

This README file provides basic information about the project's features,
configurations, and usage. Complete documentation can be found in the
file docs/caravel_openframe_datasheet.pdf. The datasheet does not contain
information about architecting or hardening the design.

Table of Contents
-----------------
- Module Overview
- Designing
- Building
- Submitting
- Contributing
- License

Module Overview
---------------

The OpenFrame project example is built around the PicoRV32 CPU from YosysHQ,
specifically the version which utilizes the Wishbone interface to communicate
with various modules. This project example includes the following IPs, listed
with their respective base addresses:

- RAM: 0x00000000
- FLASH: 0x10000000
- UART: 0x20000000
- GPIO: 0x21000000
- Counter Timer 0: 0x22000000
- Counter Timer 1: 0x23000000
- SPI Master: 0x24000000
- GPIO Vector: 0x25000000
- Flash Controller: 0x2D000000
- Debug Registers: 0x41000000

Additionally, the project includes a "housekeeping" module that is accessed
by SPI protocol for DLL configuration, chip information, and flash programming.
This IP is not accessible through the Wishbone bus in this version, but is
indirectly accessible by coupling internally to the SPI master.

Designing
---------

The main challenge of architecting an Openframe project is understanding
the GPIO pad interface, which is quite complicated. The Caravel and
Caravan designs purposefully kept details away from the end user. This
example presents a similar solution in which each GPIO pad is interfaced
by an independent Wishbone interface (gpio_wb.v). Each GPIO has I/O
similar to the user project connections on Caravel and Caravan, but with
a four-signal interface that adds the input disable pin (cpu_gpio_ieb)
to the common three-pin interface with output disable (cpu_gpio_oeb),
output (cpu_gpio_out), and input (cpu_gpio_in). The remaining configuration
options for the GPIO pad are handled through Wishbone writes. The
Wishbone interface additionally allows the three I/O signals to be
overridden by an internal register value.

Any additions to the Wishbone bus need to be added to the Wishbone
address interpreter (intercon_wb.v). Note that this has been done
differently for the GPIO modules so that all of the GPIO wishbone
instances (one per GPIO pin) can act as a single wishbone interface;
each instance decodes only its own address, and all GPIO instances
share the GPIO data bus and acknowledge signal.

Where on Caravel, the default configuration of each GPIO pin at power-up
is declared in a separate file, here the default configuration data is
kept as a parameter array (picosoc.v) and applied to each GPIO wishbone
instance.

The "cpu_gpio_*" pins on the GPIO wishbone interface (see above) define
a "standard function" for each GPIO pin (such as SPI master pins, UART
transmit/receive, etc.). Since many of these GPIO do not change
configuration (are always either input or output), the input and output
disables, and sometimes the output value, are fixed constant high or
low. For this purpose, each pad provides an individual pair of pins
"gpio_loopback_zero" and "gpio_loopback_one" that are placed next to
the pad and should be used for applying constant values to pad-related
signals.

The loopback constants can also be used to blanket disable specific
unneeded functions of the GPIO pins. In openframe_project_wrapper.v,
they have been used to disable the obscure inputs "gpio_analog_*"
(an interface to a switched-capacitor analog bus pair) and
"gpio_holdover" (related to a sleep state that possibly cannot be
achieved given the wiring inside the padframe).

The hierarchy of the Openframe project is:

Top level: openframe_project_wrapper.v. This must always be the name
of the top level cell, as it is what gets integrated into the Openframe
design to create the completed chip. The openframe_project_wrapper
module instantiates the SoC and ties off (or leaves unconnected) pins
unused by the SoC.

Second level: picosoc.v. This is the SoC definition. It instantiates
all of the blocks of the SoC as Wishbone components: The CPU
(picorv32_wb), the SPI flash controller (spimemio_wb), the UART
(simpleuart_wb), SRAM (mem_wb), and others. It defines all of the
wiring to the I/Os. It also defines a few modules that have not (by
design choice) been implemented as Wishbone components: The
housekeeping module (housekeeping), the DLL (digital_locked_loop), and
the clock and reset routing and synchronization (clock_routing).

Third level: All SoC modules.

Power domain considerations:

This design example connects the entire user project design to the
vccd1/vssd1 domain using power connection cells (with verilog,
layout, abstract, etc. views) that are treated as macros and placed
at the appropriate position in the layout to connect between the
padframe power pads and the power ring surrounding the synthesized
digital core. In general, however, it is preferable to connect
together as many domains as possible to maximize the amount of
current delivered to the project and minimize the amount of I-R
drop from the pads to any point in the core. The 3.3-5.0V domains
(vdda/vssa, vdda1/vssa1, vdda2/vssa2, vddio/vssio) should be kept
separate from the 1.8V domains (vccd/vssd, vccd1/vssd1, vccd2/vssd2),
but otherwise the user is encouraged to short together all the 1.8V
domains and optionally (if used) the 3.3V domains with the exception
of vddio/vssio, which is the ESD supply for the padframe and should
remain isolated.

Analog and mixed-signal designs:

Analog designs may make use of Openframe, but since there is no
Caravan-equivalent of Openframe with bare analog pads, any analog
signals in the Openframe design must connect to the GPIO pads, which
limits them to the voltage range of (vddio, vssio), and limits the
frequency to approximately 60MHz. All GPIOs connected to analog
signals must have the input and output buffers disabled.

The two choices of connections for analog signals to a GPIO pad are
(1) the analog_io[] pins, which connect to the pad through a resistor
and are the preferred connection, having some ESD protection; and
(2) the analog_noesd_io[] pins, which connect directly to the pad and
are very ESD sensitive. They should not be used unless the signal
in question cannot tolerate the voltage drop across the ESD protection
resistor on the analog_io[] pin.

Analog circuits that need 3.3V-5.0V compatible digital controls can
make use of the gpio_in_h digital inputs from the GPIO pins, which
are in the high voltage domain. However, there is no equivalent
GPIO high voltage output, so any outputs in a high voltage domain
must be level-shifted to 1.8V before connecting to a gpio_out[] pin.

Caravel board compatibility:

To keep compatibility with the caravel circuit board, projects should
note which pins connect on the board to other (potentially) driving
circuitry: Pins gpio[1] through gpio[4] connect to the FTDI chip (used
by the housekeeping SPI on Caravel, and which can theoretically be
placed into a high-impedence state through software). Pin gpio[38]
connects to the CMOS clock (which can be disabled to a high impedence
state with a jumper); pins gpio[39] to gpio[42] connect directly to
the SPI flash chip and can only be disconnected by desoldering the
SPI flash chip; and pin gpio[43] is connected to an LED. Pins gpio[5]
and gpio[6] connect to switches which allow them to be connected to
the FTDI (UART function) but will normally be in a high-impedence
state. All other GPIO pins connect only to header pins on the
development board.

Building
--------

For instructions on building (hardening) the OpenFrame Example project,
please refer to the [README](./README) containing the build notes.

This project example was built using locally installed tools and not
with docker. Instructions are specific to my local build environment
but hopefully with enough commentary to be more generally useful. It
should also be possible to build the project in the Efabless-recommended
docker environment.

Submitting
----------

(To be completed)

Contributing
------------

Bug fixes are always welcome. Enhancements will be considered if they
demonstrate some useful technique that can only be achieved with the
Openframe version. Otherwise, this project example is meant to be just
that---an example to learn from and build on for your own Openframe
project. The best way to contribute is to create your own open source
Openframe project for a ChipIgnite shuttle run.

License
-------

The Caravel Openframe harness chip design on which this example depends
is distributed under the Apache-2.0 license. This project example is
also distributed under the Apache-2.0 license (see the LICENSE file).
4 changes: 2 additions & 2 deletions check_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ def __init__(self, precheck_config, project_config):
super().__init__(precheck_config, project_config)

def run(self):
default_readme_result = defaults_check.has_default_readme(self.precheck_config['input_directory'], self.precheck_config['default_content'])
default_readme_result = defaults_check.has_default_readme(self.precheck_config['input_directory'], self.precheck_config['default_content'], self.project_config['type'])
if default_readme_result:
logging.info("{{README DEFAULT CHECK PASSED}} Project 'README.md' was modified and is not identical to the default 'README.md'")
else:
self.result = False
logging.warning("{{README DEFAULT CHECK FAILED}} Project 'README.md' was not modified and is identical to the default 'README.md'")

default_content_result = defaults_check.has_default_content(self.precheck_config['input_directory'], self.precheck_config['default_content'])
default_content_result = defaults_check.has_default_content(self.precheck_config['input_directory'], self.precheck_config['default_content'], self.project_config['type'])
if default_content_result:
logging.info("{{CONTENT DEFAULT CHECK PASSED}} Project 'gds' was modified and is not identical to the default 'gds'")
else:
Expand Down
11 changes: 6 additions & 5 deletions checks/defaults_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def get_updated_view(input_directory, name):
return get_view(name, input_directory)


def has_default_readme(input_directory, default_content_path):
default_content_path = default_content_path / 'README.md'
def has_default_readme(input_directory, default_content_path, project_type):
default_content_path = default_content_path / f'README_{project_type}.md'
input_directory = input_directory / 'README.md'
try:
df_readme_content = default_content_path.open(encoding='utf-8').read()
Expand All @@ -58,7 +58,7 @@ def has_default_readme(input_directory, default_content_path):
return True


def has_default_content(input_directory, default_content_path):
def has_default_content(input_directory, default_content_path, project_type):
result = True
for view in VIEWS:
try:
Expand Down Expand Up @@ -90,14 +90,15 @@ def has_default_content(input_directory, default_content_path):
parser = argparse.ArgumentParser(description="Runs a makefile check on a given file (looks for 'Makefile' if a directory is provided).")
parser.add_argument('--input_directory', '-i', required=False, default=default_input_directory, help='Input Directory')
parser.add_argument('--defaults_path', '-d', required=False, default=default_input_directory, help='Defaults Path')
parser.add_argument('--project_type', '-t', required=False, default=default_input_directory, help='Project type (digital, analog, openframe)')
args = parser.parse_args()

if has_default_readme(Path(args.input_directory), Path(args.defaults_path)):
if has_default_readme(Path(args.input_directory), Path(args.defaults_path), args.project_type):
logging.info("README Clean")
else:
logging.info("README Dirty")

if has_default_content(Path(args.input_directory), Path(args.defaults_path)):
if has_default_content(Path(args.input_directory), Path(args.defaults_path), args.project_type):
logging.info("Content Clean")
else:
logging.info("Content Dirty")

0 comments on commit 71a2050

Please sign in to comment.