diff --git a/.github/actions/setup-openlane-nix/action.yaml b/.github/actions/setup-openlane-nix/action.yaml index bf58b47..af7d5ee 100644 --- a/.github/actions/setup-openlane-nix/action.yaml +++ b/.github/actions/setup-openlane-nix/action.yaml @@ -21,4 +21,4 @@ runs: extra-trusted-public-keys = openlane.cachix.org-1:qqdwh+QMNGmZAuyeQJTH9ErW57OWSvdtuwfBKdS254E= - name: Run OpenLane Smoke Test shell: bash - run: nix run github:efabless/openlane2 -- --smoke-test + run: nix run github:efabless/openlane2 -- --version diff --git a/.github/test_set.yaml b/.github/test_set.yaml index cff8b51..1603c3b 100644 --- a/.github/test_set.yaml +++ b/.github/test_set.yaml @@ -44,4 +44,11 @@ bus: - APB - AHB + - WISHBONE +- name: EF_I2C + url: https://github.com/efabless/EF_I2C.git + tests: + - i2c_write_read_test WriteReadRegsTest + bus: + - APB - WISHBONE \ No newline at end of file diff --git a/.github/workflows/run_IP.yaml b/.github/workflows/run_IP.yaml index 0af9711..af666a4 100644 --- a/.github/workflows/run_IP.yaml +++ b/.github/workflows/run_IP.yaml @@ -52,6 +52,17 @@ jobs: if: ${{ inputs.is-ip }} run: | git clone https://github.com/efabless/EF_UVM.git ${{ env.EF_UVM_PATH }} + - name: Install ip dependencies + run: | + cd ${{ env.IP_PATH }} + ls -la ip/ + if [ -f ip/dependencies.json ]; then + echo "ip dependencies exist!" + pip install ipmgr + ipm install-dep + else + echo "dependencies.json file not found, skipping install." + fi - name: Set Artifact Name id: set_artifact_name run: | @@ -65,6 +76,8 @@ jobs: with: path: ${{ env.MY_WORKSPACE }} name: ${{ steps.set_artifact_name.outputs.artifact_name }} + include-hidden-files: true + Prepare-Tests-Matrix: needs: ["Setup-Work-Space"] diff --git a/Makefile.test b/Makefile.test index 22a79ce..6ea5d31 100644 --- a/Makefile.test +++ b/Makefile.test @@ -1,3 +1,4 @@ +MAKEFLAGS += --warn-undefined-variables RED=\033[0;31m GREEN=\033[0;32m YELLOW=\033[0;33m @@ -7,12 +8,14 @@ UVM_PY_DIR = $(PWD) GRANDPARENT_DIR:="$(shell cd ../../; pwd)" DOCKER_IMAGE = efabless/dv:cocotb RUN_MERGE_COVERAGE := true -USER_ARGS = -u $(shell id -u $$USER):$(shell id -g $$USER) +IPM_DIR := $(HOME)/.ipm +USER_ARGS = -u $(shell id -u ${USER}):$(shell id -g ${USER}) OPENLANE_RUN = $(SIM_PATH)/openlane_run/ ifeq ($(ROOTLESS), 1) USER_ARGS = endif DOCKER_COCOTB_LIB_DIR := $(shell docker run $(USER_ARGS) --rm $(DOCKER_IMAGE) cocotb-config --lib-dir) +RANDOM_SEED_ARG = ifdef RANDOM_SEED RANDOM_SEED_ARG = -e RANDOM_SEED=$(RANDOM_SEED) endif @@ -28,11 +31,11 @@ run_$(1): $(USER_ARGS) \ -v "$(GRANDPARENT_DIR)":"$(GRANDPARENT_DIR)" \ -v "$(PDK_DIR)":"$(PDK_DIR)" \ + -v "$(IPM_DIR)":"$(IPM_DIR)" \ -e RTL_MACROS="$(RTL_MACROS)" \ -e VERILOG_SOURCES="$(VERILOG_SOURCES)" \ -e SIM_PATH="$(SIM_PATH)" \ -e UVM_PY_DIR="$(UVM_PY_DIR)" \ - -u $(id -u $USER):$(id -g $USER)\ $(DOCKER_IMAGE) /bin/sh -ec "cd $(UVM_PY_DIR) && iverilog -g2012 -Ttyp $(RTL_MACROS) $(VERILOG_SOURCES) -o $(SIM_PATH)/compilation/sim.vvp -s top"; \ fi @$(MAKE) create_top_py UVM_TEST=$(1) @@ -135,7 +138,7 @@ generate_gl: if [ ! -d "$(OPENLANE_RUN)/final" ]; then \ echo "Generating netlist with Yosys"; \ mkdir -p $(OPENLANE_RUN); \ - cd $(GRANDPARENT_DIR) && nix run github:efabless/openlane2 -- --save-views-to hdl/gl/synthesis --log-level WARNING -c DESIGN_NAME=$(DESIGN_NAME) -c VERILOG_FILES="$(PRE_SYS_FILES)" --force-run-dir $(OPENLANE_RUN) $(UVM_PY_DIR)/EF_UVM/openlane/openlane_synthesis.json; \ + cd $(GRANDPARENT_DIR) && nix run github:efabless/openlane2 -- --save-views-to hdl/gl/synthesis --log-level WARNING -c DESIGN_NAME=$(DESIGN_NAME) -c VERILOG_FILES="$(PRE_SYS_FILES)" -c PNR_SDC_FILE="$(UVM_PY_DIR)/EF_UVM/openlane/custom.sdc" --force-run-dir $(OPENLANE_RUN) $(UVM_PY_DIR)/EF_UVM/openlane/openlane_synthesis.json; \ fi; \ else \ echo "Skipping synthesis because SKIP_SYNTHESIS is defined"; \ diff --git a/bus_env/bus_agent/bus_apb_driver.py b/bus_env/bus_agent/bus_apb_driver.py index b849d87..b3a562a 100644 --- a/bus_env/bus_agent/bus_apb_driver.py +++ b/bus_env/bus_agent/bus_apb_driver.py @@ -64,6 +64,7 @@ async def read(self, addr): await self.drive_delay() self.vif.PENABLE.value = 1 await self.drive_delay() + await self.wait_ready() try: data = self.vif.PRDATA.value.integer except TypeError or ValueError: @@ -80,6 +81,7 @@ async def write(self, addr, data): await self.drive_delay() self.vif.PENABLE.value = 1 await self.drive_delay() + await self.wait_ready() self.end_of_trans() uvm_info(self.tag, "Finished APB write to addr " + hex(addr), UVM_HIGH) @@ -87,5 +89,7 @@ def end_of_trans(self): self.vif.PSEL.value = 0 self.vif.PENABLE.value = 0 - + async def wait_ready(self): + while self.vif.PREADY == 0: + await self.drive_delay() uvm_component_utils(bus_apb_driver) diff --git a/bus_env/bus_agent/bus_apb_monitor.py b/bus_env/bus_agent/bus_apb_monitor.py index 68f8a64..65ec088 100644 --- a/bus_env/bus_agent/bus_apb_monitor.py +++ b/bus_env/bus_agent/bus_apb_monitor.py @@ -12,6 +12,7 @@ class bus_apb_monitor(bus_base_monitor): def __init__(self, name="bus_apb_monitor", parent=None): super().__init__(name, parent) + self.counter = 0 async def run_phase(self, phase): await cocotb.start(self.watch_reset()) @@ -34,6 +35,7 @@ async def run_phase(self, phase): self.tag, f"APB protocol violation: SETUP cycle not followed by ENABLE cycle PENABLE={self.vif.PENABLE.value.binstr}", ) + await self.wait_ready() if tr.kind == bus_item.WRITE: tr.data = self.vif.PWDATA.value.integer else: @@ -46,6 +48,9 @@ async def run_phase(self, phase): ) tr.data = self.vif.PRDATA.value.binstr self.monitor_port.write(tr) + self.counter += 1 + # if self.counter > 40: + # uvm_fatal(self.tag, "sampled too many transactions") # update reg value #TODO: move this to the ref_model later # self.regs.write_reg_value(tr.addr, tr.data) uvm_info( @@ -68,5 +73,9 @@ async def sample_delay(self): await RisingEdge(self.vif.CLK) # await Timer(1, "NS") + async def wait_ready(self): + while self.vif.PREADY == 0: + await self.sample_delay() + uvm_component_utils(bus_apb_monitor) diff --git a/bus_env/bus_agent/bus_wb_monitor.py b/bus_env/bus_agent/bus_wb_monitor.py index ed7a553..09f37a3 100644 --- a/bus_env/bus_agent/bus_wb_monitor.py +++ b/bus_env/bus_agent/bus_wb_monitor.py @@ -2,7 +2,7 @@ from uvm.comps.uvm_monitor import UVMMonitor from uvm.tlm1.uvm_analysis_port import UVMAnalysisPort from uvm.base.uvm_config_db import UVMConfigDb -from cocotb.triggers import Timer, RisingEdge, FallingEdge +from cocotb.triggers import Timer, RisingEdge, FallingEdge, NextTimeStep from uvm.base.uvm_object_globals import UVM_HIGH, UVM_LOW from EF_UVM.bus_env.bus_item import bus_item from EF_UVM.bus_env.bus_agent.bus_base_monitor import bus_base_monitor @@ -68,8 +68,12 @@ async def recieve_transaction(self): and self.vif.stb_i.value.binstr == "1" ): break - while self.vif.ack_o.value == 0: - await self.sample_delay() + while True: + await NextTimeStep() + if self.vif.ack_o.value == 0: + await self.sample_delay() + else: + break address = self.vif.adr_i.value.integer write = self.vif.we_i.value.integer if write: diff --git a/bus_env/bus_item.py b/bus_env/bus_item.py index 661fd4e..998a98c 100644 --- a/bus_env/bus_item.py +++ b/bus_env/bus_item.py @@ -23,7 +23,7 @@ def __init__(self, name="bus_item"): super().__init__(name) self.tag = name self.addr = 0 # bit - self.rand("addr", range(0, 0xFFF)) + self.rand("addr", range(0, 0xFFFF)) self.data = 0 # logic self.rand("data", range(0, 0xFFFF)) self.kind = bus_item.READ # kind_e @@ -46,7 +46,9 @@ def convert2string(self): def do_clone(self): t = bus_item() - t.copy(self) + t.kind = self.kind + t.addr = self.addr + t.data = self.data return t def do_compare(self, tr): diff --git a/bus_env/bus_regs.py b/bus_env/bus_regs.py index 59bdb20..a63d594 100644 --- a/bus_env/bus_regs.py +++ b/bus_env/bus_regs.py @@ -41,7 +41,10 @@ def init_regs(self): self.irq_exist = False if "flags" in self.data and len(self.data["flags"]) > 0: size = len(self.data["flags"]) - irq_regs_offset = self.data["info"]["irq_reg_offset"] + try: + irq_regs_offset = self.data["info"]["irq_reg_offset"] + except KeyError: + irq_regs_offset = 0xFF00 reg_im = { "name": "im", "offset": irq_regs_offset + 0x0, @@ -88,10 +91,25 @@ def init_regs(self): self.data["registers"].append(reg_ris) self.data["registers"].append(reg_icr) self.irq_exist = True - + + if True: # assume clock gating is always true + reg_clk_g = { + "name": "CLKGATE", + "offset": 0xFF10, + "size": 1, + "mode": "w", + "fifo": True, # as we can't read it + "bit_access": "no", + "val": 0, + "delayed_val": 0, + } + self.data["registers"].append(reg_clk_g) if "fifos" in self.data and len(self.data["fifos"]) > 0: fifo_count = 0 - fifos_regs_offset = self.data["info"]["fifo_reg_offset"] + try: + fifos_regs_offset = self.data["info"]["fifo_reg_offset"] + except KeyError: + fifos_regs_offset = 0xFE00 for fifo in self.data["fifos"]: fifo_name = fifo["name"] reg_size = fifo["address_width"] diff --git a/openlane/openlane_synthesis.json b/openlane/openlane_synthesis.json index 92416fd..dd4459c 100644 --- a/openlane/openlane_synthesis.json +++ b/openlane/openlane_synthesis.json @@ -9,5 +9,7 @@ "Checker.YosysSynthChecks", "openroad.staprepnr" ] - } -} \ No newline at end of file + }, + "ERROR_ON_UNMAPPED_CELLS": false, + "ERROR_ON_SYNTH_CHECKS": false +}