From: Luke Kenneth Casson Leighton Date: Thu, 1 Apr 2021 21:34:50 +0000 (+0100) Subject: move pre_pnr cocotb sim to soc-cocotb-sim directory X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4cc4e398fc2abb8ee5ded5696e8a9ba5a70f51c0;p=soc-cocotb-sim.git move pre_pnr cocotb sim to soc-cocotb-sim directory --- diff --git a/ls180/pre_pnr/.gitignore b/ls180/pre_pnr/.gitignore new file mode 100644 index 0000000..c63d72e --- /dev/null +++ b/ls180/pre_pnr/.gitignore @@ -0,0 +1,2 @@ +mem*.init +sim_build_iverilog/ diff --git a/ls180/pre_pnr/Makefile b/ls180/pre_pnr/Makefile new file mode 100644 index 0000000..330c788 --- /dev/null +++ b/ls180/pre_pnr/Makefile @@ -0,0 +1,18 @@ +ifeq ($(SIM),) + $(error Use one of the run_*.sh scripts to run cocotb test bench) +endif + +TOPLEVEL_LANG := verilog + +# within soc repo, as submodule, this works after "make ls180" +# is run inside the litex/florent subdirectory +VERILOG_SOURCES := \ + ../../litex/florent/libresoc.v \ + ../../litex/florent/ls180.v \ +# END VERILOG_SOURCES + +TOPLEVEL := ls180 +MODULE := test + +include $(shell cocotb-config --makefiles)/Makefile.sim + diff --git a/ls180/pre_pnr/README.md b/ls180/pre_pnr/README.md new file mode 100644 index 0000000..0f06209 --- /dev/null +++ b/ls180/pre_pnr/README.md @@ -0,0 +1,17 @@ +# Usage + +Cocotb is Makefile based. In order to support different configuration and +simulators, run scripts are provided that call the Makefile: + +* run_iverilator.sh: Run pre-layout testbench with Icarus Verilog. +* clean.sh: clean up all outputs. + +# Dependency + +* cocotb: `pip install cocotb` +* c4m-jtag: install according to HDL workflow +* iverilog: `apt install iverilog` +* `../libresoc.v`, `../ls180.v`: run `make ls180_verilog` in soc directory, + `make ls180` in parent directory. + Version with SRAMs is currently not supported. + diff --git a/ls180/pre_pnr/clean.sh b/ls180/pre_pnr/clean.sh new file mode 100755 index 0000000..04882ff --- /dev/null +++ b/ls180/pre_pnr/clean.sh @@ -0,0 +1,3 @@ +#!/bin/sh +rm -fr results_*.xml sim_build_* + diff --git a/ls180/pre_pnr/idcode.svf b/ls180/pre_pnr/idcode.svf new file mode 100644 index 0000000..994e9c8 --- /dev/null +++ b/ls180/pre_pnr/idcode.svf @@ -0,0 +1,4 @@ +!Loading device with 'idcode' instruction. +SIR 4 TDI (1); +SDR 32 TDI (00000000) TDO (000018FF) ; + diff --git a/ls180/pre_pnr/run_iverilog.sh b/ls180/pre_pnr/run_iverilog.sh new file mode 100755 index 0000000..147dc60 --- /dev/null +++ b/ls180/pre_pnr/run_iverilog.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +touch mem.init mem_1.init mem_2.init mem_3.init mem_4.init +# Only run test in reset state as running CPU takes too much time to simulate +make \ + SIM=icarus \ + COCOTB_RESULTS_FILE=results_iverilog.xml \ + COCOTB_HDL_TIMEUNIT=100ps \ + TESTCASE="idcode_reset,idcodesvf_reset" \ + SIM_BUILD=sim_build_iverilog + + diff --git a/ls180/pre_pnr/test.py b/ls180/pre_pnr/test.py new file mode 100644 index 0000000..c73790b --- /dev/null +++ b/ls180/pre_pnr/test.py @@ -0,0 +1,117 @@ +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import Timer +from cocotb.utils import get_sim_steps +from cocotb.binary import BinaryValue + +from c4m.cocotb.jtag.c4m_jtag import JTAG_Master +from c4m.cocotb.jtag.c4m_jtag_svfcocotb import SVF_Executor + +# +# Helper functions +# + +def setup_sim(dut, *, clk_period, run): + """Initialize CPU and setup clock""" + + clk_steps = get_sim_steps(clk_period, "ns") + cocotb.fork(Clock(dut.sys_clk, clk_steps).start()) + + dut.sys_rst <= 1 + dut.sys_clk <= 0 + if run: + yield Timer(int(10.5*clk_steps)) + dut.sys_rst <= 0 + yield Timer(int(5*clk_steps)) + +def setup_jtag(dut, *, tck_period): + # Make this a generator + if False: + yield Timer(0) + return JTAG_Master(dut.jtag_tck, dut.jtag_tms, + dut.jtag_tdi, dut.jtag_tdo, + clk_period=tck_period, + ir_width=4) + +def execute_svf(dut, *, jtag, svf_filename): + jtag_svf = SVF_Executor(jtag) + with open(svf_filename, "r") as f: + svf_deck = f.read() + yield jtag_svf.run(svf_deck, p=dut._log.info) + +# +# IDCODE using JTAG_master +# + +def idcode(dut, *, jtag): + yield jtag.idcode() + result1 = jtag.result + dut._log.info("IDCODE1: {}".format(result1)) + assert(result1 == BinaryValue("00000000000000000001100011111111")) + + yield jtag.idcode() + result2 = jtag.result + dut._log.info("IDCODE2: {}".format(result2)) + + assert(result1 == result2) + +@cocotb.test() +def idcode_reset(dut): + dut._log.info("Running IDCODE test; cpu in reset...") + + clk_period = 100 # 10MHz + tck_period = 300 # 3MHz + + yield from setup_sim(dut, clk_period=clk_period, run=False) + jtag = yield from setup_jtag(dut, tck_period = tck_period) + + yield from idcode(dut, jtag=jtag) + + dut._log.info("IDCODE test completed") + +@cocotb.test() +def idcode_run(dut): + dut._log.info("Running IDCODE test; cpu running...") + + clk_period = 100 # 10MHz + tck_period = 300 # 3MHz + + yield from setup_sim(dut, clk_period=clk_period, run=True) + jtag = yield from setup_jtag(dut, tck_period = tck_period) + + yield from idcode(dut, jtag=jtag) + + dut._log.info("IDCODE test completed") + +# +# Read IDCODE from SVF file +# + +@cocotb.test() +def idcodesvf_reset(dut): + dut._log.info("Running IDCODE through SVF test; cpu in reset...") + + clk_period = 100 # 10MHz + tck_period = 300 # 3MHz + + yield from setup_sim(dut, clk_period=clk_period, run=False) + jtag = yield from setup_jtag(dut, tck_period = tck_period) + + yield from execute_svf(dut, jtag=jtag, svf_filename="idcode.svf") + + dut._log.info("IDCODE test completed") + +@cocotb.test() +def idcode_run(dut): + dut._log.info("Running IDCODE through test; cpu running...") + + clk_period = 100 # 10MHz + tck_period = 300 # 3MHz + + yield from setup_sim(dut, clk_period=clk_period, run=True) + jtag = yield from setup_jtag(dut, tck_period = tck_period) + + yield from execute_svf(dut, jtag=jtag, svf_filename="idcode.svf") + + dut._log.info("IDCODE test completed") +