{ "cells": [ { "cell_type": "markdown", "id": "6d0b2a72-c65b-49cd-a4b8-c69d4bf260c3", "metadata": {}, "source": [ "# Yosys inference of memories\n", "\n", "This example demonstrates direct inference of a dual port (simplex) memory description into a FPGA hard memory block (here: Lattice ECP5 DP16KD primitive).\n", "It requires a recent (>= v0.12) release of yosys using the improved memory mapping." ] }, { "cell_type": "code", "execution_count": 1, "id": "59fbfc7e-75cf-4f83-b781-92e09b546ada", "metadata": {}, "outputs": [], "source": [ "import sys\n", "sys.path.insert(0, '../../')" ] }, { "cell_type": "code", "execution_count": 2, "id": "bdf2ad89-5861-4c93-938a-4f412aad1639", "metadata": {}, "outputs": [], "source": [ "from myirl.emulation.myhdl import *\n", "from myirl.test.test_array import r1w1, SigArray" ] }, { "cell_type": "markdown", "id": "5211999a-42a9-48ce-b0dc-2b914a53051c", "metadata": {}, "source": [ "## Simple read and write port memory\n", "\n", "This implementation uses bypass logic when a write is occuring during a read from the same address." ] }, { "cell_type": "code", "execution_count": 3, "id": "07333c2c-a76d-4f76-a566-b8024b28c66e", "metadata": {}, "outputs": [], "source": [ "@block\n", "def r1w1(\n", " clk : ClkSignal,\n", " we : Signal,\n", " addr_r: Signal,\n", " addr_w: Signal,\n", " din: Signal,\n", " dout: Signal.Output,\n", " ram : SigArray,\n", " MODE = False, # Conditional compilation flag w/o type annotation\n", " DWIDTH=16, AWIDTH=10,\n", " TRANSPARENCY = False\n", " ) -> IRL:\n", "\n", " print(\"CALLED MEMORY INSTANCE\", DWIDTH)\n", " \n", " if TRANSPARENCY:\n", " @always(clk.posedge)\n", " def mem_rw_transparent():\n", " if we and addr_w == addr_r:\n", " dout.next = din #Forward\n", " else:\n", " dout.next = ram[addr_r][DWIDTH:]\n", "\n", " if we:\n", " ram[addr_w].next = din\n", " else:\n", " @always(clk.posedge)\n", " def mem_rw():\n", " dout.next = ram[addr_r][DWIDTH:]\n", " \n", " if we:\n", " ram[addr_w].next = din \n", " \n", " return instances()\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "59b9b9b3-5d70-4c65-8f23-0b215578bb6d", "metadata": {}, "outputs": [], "source": [ "def memtest(MODE = 0, STYLE = 1, data_w=16, addr_w=6, mem = r1w1, TRANSPARENT = True):\n", " c = ClkSignal(name = 'clk')\n", " c.init = True\n", " wren = Signal(bool(), name = 'we')\n", " ra, wa = [ Signal(intbv()[addr_w:]) for n in ['addr_write', 'addr_read'] ]\n", " a, q = [ Signal(intbv()[data_w:]) for n in ['a', 'q'] ]\n", "\n", " ram_data = SigArray([ intbv(v)[data_w:] for v in range(2 ** addr_w)],\n", " name='ram_sig', init=True)\n", "\n", " inst = mem(clk=c, we=wren, addr_r=ra, addr_w=wa, din=a, dout=q, MODE=False, ram = ram_data,\n", " AWIDTH=addr_w, DWIDTH=data_w, TRANSPARENCY = TRANSPARENT)\n", "\n", " return inst" ] }, { "cell_type": "code", "execution_count": null, "id": "e89ab554-780e-4135-9b63-7c42d3e59b1d", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "id": "84f0e9a4-c1b8-4a16-9cb3-2d9a5eca90ff", "metadata": {}, "source": [ "## Mapping to hardware\n", "\n", "**Note** myIRL inference does *not yet* detect built-in transparency, (redundant) FFs will be inferred." ] }, { "cell_type": "code", "execution_count": 5, "id": "76ac7892-4770-4572-9b81-e223b30f44ae", "metadata": {}, "outputs": [], "source": [ "from myirl.targets import pyosys" ] }, { "cell_type": "code", "execution_count": 6, "id": "d66a9a6e-5a44-4d65-8727-6914593c587f", "metadata": {}, "outputs": [], "source": [ "DATA_WIDTH = 32" ] }, { "cell_type": "markdown", "id": "c9ad20ea-155e-4435-8159-41e511879e96", "metadata": {}, "source": [ "Elaborate memory unit and emit CXXRTL code:" ] }, { "cell_type": "code", "execution_count": 7, "id": "a6a11195-13f9-46eb-8666-be3a0795c77b", "metadata": {}, "outputs": [], "source": [ "def convert(dw, aw = 7):\n", "\n", " tgt = pyosys.RTLIL(\"memtest%d\" % dw)\n", "\n", " MEM = r1w1\n", "\n", " tb = memtest(data_w=dw, mem = MEM, addr_w = aw, TRANSPARENT = True)\n", " d = tb.elab(tgt, elab_all = True)\n", " d = d[0]\n", " d.run(\"hierarchy -check\")\n", " d.run(\"stat\", capture = None)\n", " d.run(\"write_rtlil mem8.il\")\n", " d.run(\"debug memory -nomap; debug opt\")\n", " \n", " return d" ] }, { "cell_type": "code", "execution_count": 8, "id": "2b1503a5-a4bc-4d91-9fa6-3593fdc4eb1a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CALLED MEMORY INSTANCE 32\n", "Creating process 'r1w1/mem_rw_transparent' with sensitivity (clk'rising,)\n", "\u001b[32m Adding module with name `r1w1` \u001b[0m\n", " DEBUG: SKIP ARRAYTYPE `ram` : \n", " DEBUG SLICE READ MEMORY to dout AWIDTH:7 DWIDTH:32\n", "\u001b[7;35m [Component 'meminit/meminit'] blackbox not returning instances \u001b[0m\n", "DEBUG ADD ROM 7:32\n", "\u001b[7;34m PARAM PRIORITY --> 48 \u001b[0m\n", "\u001b[7;34m PARAM WORDS --> 128 \u001b[0m\n", "\u001b[7;34m PARAM ABITS --> 7 \u001b[0m\n", "\u001b[7;34m PARAM WIDTH --> 32 \u001b[0m\n", "\u001b[7;34m PARAM MEMID --> $mem_ram_sig \u001b[0m\n", "\u001b[7;35m [Component 'memrd/memrd'] blackbox not returning instances \u001b[0m\n", "\u001b[7;34m PARAM CLK_ENABLE --> False \u001b[0m\n", "\u001b[7;34m PARAM CLK_POLARITY --> True \u001b[0m\n", "\u001b[7;34m PARAM TRANSPARENT --> False \u001b[0m\n", "\u001b[7;34m PARAM ABITS --> 7 \u001b[0m\n", "\u001b[7;34m PARAM WIDTH --> 32 \u001b[0m\n", "\u001b[7;34m PARAM MEMID --> $mem_ram_sig \u001b[0m\n", " DEBUG SLICE WRITE MEMORY to ram_sig AWIDTH:7 DWIDTH:32\n", "\u001b[7;35m [Component 'memwr/memwr'] blackbox not returning instances \u001b[0m\n", "\u001b[7;34m PARAM CLK_ENABLE --> True \u001b[0m\n", "\u001b[7;34m PARAM CLK_POLARITY --> True \u001b[0m\n", "\u001b[7;34m PARAM PRIORITY --> 48 \u001b[0m\n", "\u001b[7;34m PARAM ABITS --> 7 \u001b[0m\n", "\u001b[7;34m PARAM WIDTH --> 32 \u001b[0m\n", "\u001b[7;34m PARAM MEMID --> $mem_ram_sig \u001b[0m\n", "DEBUG TOP LEVEL WRITE MEM ram_sig\n", "\u001b[7;34m FINALIZE implementation `r1w1` of `r1w1` \u001b[0m\n", "\n", "-- Running command `tee -q hierarchy -top \\r1w1' --\n", "\n", "-- Running command `tee -q hierarchy -check' --\n", "\n", "-- Running command `stat' --\n", "\n", "3. Printing statistics.\n", "\n", "=== r1w1 ===\n", "\n", " Number of wires: 17\n", " Number of wire bits: 338\n", " Number of public wires: 7\n", " Number of public wire bits: 112\n", " Number of memories: 1\n", " Number of memory bits: 4096\n", " Number of processes: 0\n", " Number of cells: 7\n", " $and 1\n", " $dff 1\n", " $eq 1\n", " $meminit 1\n", " $memrd 1\n", " $memwr 1\n", " $mux 1\n", "\n", "\n", "-- Running command `tee -q write_rtlil mem8.il' --\n", "\n", "-- Running command `tee -q debug memory -nomap; debug opt' --\n", "\n", "6. Executing OPT pass (performing simple optimizations).\n", "\n", "6.1. Executing OPT_EXPR pass (perform const folding).\n", "Optimizing module r1w1.\n", "\n", "6.2. Executing OPT_MERGE pass (detect identical cells).\n", "Finding identical cells in module `\\r1w1'.\n", "Removed a total of 0 cells.\n", "\n", "6.3. Executing OPT_MUXTREE pass (detect dead branches in mux trees).\n", "Running muxtree optimizer on module \\r1w1..\n", " Creating internal representation of mux trees.\n", " No muxes found in this module.\n", "Removed 0 multiplexer ports.\n", "\n", "6.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).\n", " Optimizing cells in module \\r1w1.\n", "Performed a total of 0 changes.\n", "\n", "6.5. Executing OPT_MERGE pass (detect identical cells).\n", "Finding identical cells in module `\\r1w1'.\n", "Removed a total of 0 cells.\n", "\n", "6.6. Executing OPT_DFF pass (perform DFF optimizations).\n", "\n", "6.7. Executing OPT_CLEAN pass (remove unused cells and wires).\n", "Finding unused cells or wires in module \\r1w1..\n", "\n", "6.8. Executing OPT_EXPR pass (perform const folding).\n", "Optimizing module r1w1.\n", "\n", "6.9. Finished OPT passes. (There is nothing left to do.)\n" ] } ], "source": [ "d = convert(DATA_WIDTH, 7)" ] }, { "cell_type": "markdown", "id": "e29d7ee2-7003-4352-baa9-47245ac428e4", "metadata": {}, "source": [ "## Testing hardware generation\n", "\n", "Note: Post map simulation may require external memory models of blackbox Vendor Primitives." ] }, { "cell_type": "code", "execution_count": 9, "id": "9556f719-072e-4ef7-a633-e3029ec36b1f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "-- Running command `ls' --\n", "\n", "1 modules:\n", " r1w1\n", "\n", "-- Running command `tee -q read_verilog -lib -specify /usr/share/yosys/ecp5/cells_sim.v /usr/share/yosys/ecp5/cells_bb.v' --\n", "\n", "-- Running command `tee -q memory_libmap -lib /usr/share/yosys/ecp5/brams.txt' --\n", "\n", "-- Running command `tee -q techmap -map /usr/share/yosys/ecp5/brams_map.v' --\n", "\n", "-- Running command `tee -q memory_libmap -lib /usr/share/yosys/ecp5/lutrams.txt' --\n", "\n", "-- Running command `tee -q techmap -map /usr/share/yosys/ecp5/lutrams_map.v' --\n", "\n", "-- Running command `tee -q opt_clean' --\n", "\n", "-- Running command `stat' --\n", "\n", "14. Printing statistics.\n", "\n", "=== r1w1 ===\n", "\n", " Number of wires: 12\n", " Number of wire bits: 183\n", " Number of public wires: 6\n", " Number of public wire bits: 80\n", " Number of memories: 0\n", " Number of memory bits: 0\n", " Number of processes: 0\n", " Number of cells: 6\n", " $and 1\n", " $dff 1\n", " $dffe 1\n", " $eq 1\n", " $mux 1\n", " DP16KD 1\n", "\n", "\n", "-- Running command `tee -q write_rtlil mapped.il' --\n", "\n", "-- Running command `show -format dot -prefix memtest32 *' --\n", "\n", "16. Generating Graphviz representation of design.\n", "Writing dot description to `memtest32.dot'.\n", "Dumping module r1w1 to page 1.\n" ] } ], "source": [ "TECHMAP = '/usr/share/yosys'\n", "\n", "def synth_ecp5(d, libmap = True):\n", " # Read blackbox cells for awareness of DP16KD:\n", " d.run(\"read_verilog -lib -specify %s/ecp5/cells_sim.v %s/ecp5/cells_bb.v\" % (TECHMAP, TECHMAP))\n", "\n", " if libmap: # New libmap procedure\n", " d.run(\"memory_libmap -lib %s/ecp5/brams.txt\" % TECHMAP) \n", " else:\n", " # First try DP16KD mapping:\n", " d.run(\"memory_bram -rules %s/ecp5/brams.txt\" % TECHMAP)\n", " \n", " d.run(\"techmap -map %s/ecp5/brams_map.v\" % TECHMAP)\n", "\n", " # Remaining (addr_w <= 8 bit) to LUT RAM:\n", " if libmap:\n", " d.run(\"memory_libmap -lib %s/ecp5/lutrams.txt\" % TECHMAP)\n", " else:\n", " d.run(\"memory_bram -rules %s/ecp5/lutrams.txt\" % TECHMAP)\n", " \n", " d.run(\"techmap -map %s/ecp5/lutrams_map.v\" % TECHMAP)\n", " d.run(\"opt_clean\")\n", " \n", "def synth_gatemate(d, libmap = True):\n", " d.run(\"read_verilog -lib -specify %s/gatemate/cells_sim.v %s/gatemate/cells_bb.v\" % (TECHMAP, TECHMAP))\n", "\n", " if libmap: # New libmap procedure\n", " d.run(\"memory_libmap -lib %s/gatemate/brams.txt\" % TECHMAP) \n", " else:\n", " d.run(\"memory_bram -rules %s/gatemate/brams.txt\" % TECHMAP)\n", " d.run(\"techmap -map %s/gatemate/brams_map.v\" % TECHMAP)\n", "\n", " d.run(\"opt\")\n", " \n", "d.run(\"ls\", capture = None)\n", "\n", "synth_ecp5(d)\n", "d.run(\"stat\", capture = None)\n", "\n", "d.run(\"write_rtlil mapped.il\")\n", "\n", "d.display_rtl(selection = '*', fmt = 'dot')" ] }, { "cell_type": "code", "execution_count": 10, "id": "39da7529-9cbe-4085-87f1-4811bcb1dcfb", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " \n", " \n", " \n", "\n", "r1w1\n", "\n", "r1w1\n", "\n", "\n", "n7\n", "\n", "addr_r\n", "\n", "\n", "\n", "c21\n", "\n", "A\n", "\n", "B\n", "\n", "$270\n", "$eq\n", "\n", "Y\n", "\n", "\n", "\n", "n7:e->c21:w\n", "\n", "\n", "\n", "\n", "\n", "x13\n", "\n", "5:5 - 0:0\n", "\n", "\n", "\n", "n7:e->x13:w\n", "\n", "\n", "\n", "\n", "\n", "x14\n", "\n", "6:6 - 0:0\n", "\n", "\n", "\n", "n7:e->x14:w\n", "\n", "\n", "\n", "\n", "\n", "x20\n", "\n", "0:0 - 0:0\n", "\n", "\n", "\n", "n7:e->x20:w\n", "\n", "\n", "\n", "\n", "\n", "x21\n", "\n", "1:1 - 0:0\n", "\n", "\n", "\n", "n7:e->x21:w\n", "\n", "\n", "\n", "\n", "\n", "x22\n", "\n", "2:2 - 0:0\n", "\n", "\n", "\n", "n7:e->x22:w\n", "\n", "\n", "\n", "\n", "\n", "x23\n", "\n", "3:3 - 0:0\n", "\n", "\n", "\n", "n7:e->x23:w\n", "\n", "\n", "\n", "\n", "\n", "x24\n", "\n", "4:4 - 0:0\n", "\n", "\n", "\n", "n7:e->x24:w\n", "\n", "\n", "\n", "\n", "\n", "n8\n", "\n", "addr_w\n", "\n", "\n", "\n", "n8:e->c21:w\n", "\n", "\n", "\n", "\n", "\n", "x1\n", "\n", "5:5 - 0:0\n", "\n", "\n", "\n", "n8:e->x1:w\n", "\n", "\n", "\n", "\n", "\n", "x2\n", "\n", "6:6 - 0:0\n", "\n", "\n", "\n", "n8:e->x2:w\n", "\n", "\n", "\n", "\n", "\n", "x6\n", "\n", "0:0 - 0:0\n", "\n", "\n", "\n", "n8:e->x6:w\n", "\n", "\n", "\n", "\n", "\n", "x7\n", "\n", "1:1 - 0:0\n", "\n", "\n", "\n", "n8:e->x7:w\n", "\n", "\n", "\n", "\n", "\n", "x8\n", "\n", "2:2 - 0:0\n", "\n", "\n", "\n", "n8:e->x8:w\n", "\n", "\n", "\n", "\n", "\n", "x9\n", "\n", "3:3 - 0:0\n", "\n", "\n", "\n", "n8:e->x9:w\n", "\n", "\n", "\n", "\n", "\n", "x10\n", "\n", "4:4 - 0:0\n", "\n", "\n", "\n", "n8:e->x10:w\n", "\n", "\n", "\n", "\n", "\n", "n9\n", "\n", "clk\n", "\n", "\n", "\n", "c17\n", "\n", "CLK\n", "\n", "D\n", "\n", "EN\n", "\n", "$269\n", "$dffe\n", "\n", "Q\n", "\n", "\n", "\n", "n9:e->c17:w\n", "\n", "\n", "\n", "\n", "\n", "c23\n", "\n", "CLK\n", "\n", "D\n", "\n", "$276\n", "$dff\n", "\n", "Q\n", "\n", "\n", "\n", "n9:e->c23:w\n", "\n", "\n", "\n", "\n", "\n", "c142\n", "\n", "ADA0\n", "\n", "ADA1\n", "\n", "ADA10\n", "\n", "ADA11\n", "\n", "ADA12\n", "\n", "ADA13\n", "\n", "ADA2\n", "\n", "ADA3\n", "\n", "ADA4\n", "\n", "ADA5\n", "\n", "ADA6\n", "\n", "ADA7\n", "\n", "ADA8\n", "\n", "ADA9\n", "\n", "ADB0\n", "\n", "ADB1\n", "\n", "ADB10\n", "\n", "ADB11\n", "\n", "ADB12\n", "\n", "ADB13\n", "\n", "ADB2\n", "\n", "ADB3\n", "\n", "ADB4\n", "\n", "ADB5\n", "\n", "ADB6\n", "\n", "ADB7\n", "\n", "ADB8\n", "\n", "ADB9\n", "\n", "CEA\n", "\n", "CEB\n", "\n", "CLKA\n", "\n", "CLKB\n", "\n", "CSA0\n", "\n", "CSA1\n", "\n", "CSA2\n", "\n", "CSB0\n", "\n", "CSB1\n", "\n", "CSB2\n", "\n", "DIA0\n", "\n", "DIA1\n", "\n", "DIA10\n", "\n", "DIA11\n", "\n", "DIA12\n", "\n", "DIA13\n", "\n", "DIA14\n", "\n", "DIA15\n", "\n", "DIA16\n", "\n", "DIA17\n", "\n", "DIA2\n", "\n", "DIA3\n", "\n", "DIA4\n", "\n", "DIA5\n", "\n", "DIA6\n", "\n", "DIA7\n", "\n", "DIA8\n", "\n", "DIA9\n", "\n", "DIB0\n", "\n", "DIB1\n", "\n", "DIB10\n", "\n", "DIB11\n", "\n", "DIB12\n", "\n", "DIB13\n", "\n", "DIB14\n", "\n", "DIB15\n", "\n", "DIB16\n", "\n", "DIB17\n", "\n", "DIB2\n", "\n", "DIB3\n", "\n", "DIB4\n", "\n", "DIB5\n", "\n", "DIB6\n", "\n", "DIB7\n", "\n", "DIB8\n", "\n", "DIB9\n", "\n", "OCEA\n", "\n", "OCEB\n", "\n", "RSTA\n", "\n", "RSTB\n", "\n", "WEA\n", "\n", "WEB\n", "\n", "$mem_ram_sig.0.0\n", "DP16KD\n", "\n", "DOA0\n", "\n", "DOA1\n", "\n", "DOA10\n", "\n", "DOA11\n", "\n", "DOA12\n", "\n", "DOA13\n", "\n", "DOA14\n", "\n", "DOA15\n", "\n", "DOA16\n", "\n", "DOA17\n", "\n", "DOA2\n", "\n", "DOA3\n", "\n", "DOA4\n", "\n", "DOA5\n", "\n", "DOA6\n", "\n", "DOA7\n", "\n", "DOA8\n", "\n", "DOA9\n", "\n", "DOB0\n", "\n", "DOB1\n", "\n", "DOB10\n", "\n", "DOB11\n", "\n", "DOB12\n", "\n", "DOB13\n", "\n", "DOB14\n", "\n", "DOB15\n", "\n", "DOB16\n", "\n", "DOB17\n", "\n", "DOB2\n", "\n", "DOB3\n", "\n", "DOB4\n", "\n", "DOB5\n", "\n", "DOB6\n", "\n", "DOB7\n", "\n", "DOB8\n", "\n", "DOB9\n", "\n", "\n", "\n", "n9:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "n9:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "n10\n", "\n", "din\n", "\n", "\n", "\n", "n10:e->c17:w\n", "\n", "\n", "\n", "\n", "\n", "x33\n", "\n", "0:0 - 0:0\n", "\n", "\n", "\n", "n10:e->x33:w\n", "\n", "\n", "\n", "\n", "\n", "x34\n", "\n", "1:1 - 0:0\n", "\n", "\n", "\n", "n10:e->x34:w\n", "\n", "\n", "\n", "\n", "\n", "x35\n", "\n", "10:10 - 0:0\n", "\n", "\n", "\n", "n10:e->x35:w\n", "\n", "\n", "\n", "\n", "\n", "x36\n", "\n", "11:11 - 0:0\n", "\n", "\n", "\n", "n10:e->x36:w\n", "\n", "\n", "\n", "\n", "\n", "x37\n", "\n", "12:12 - 0:0\n", "\n", "\n", "\n", "n10:e->x37:w\n", "\n", "\n", "\n", "\n", "\n", "x38\n", "\n", "13:13 - 0:0\n", "\n", "\n", "\n", "n10:e->x38:w\n", "\n", "\n", "\n", "\n", "\n", "x39\n", "\n", "14:14 - 0:0\n", "\n", "\n", "\n", "n10:e->x39:w\n", "\n", "\n", "\n", "\n", "\n", "x40\n", "\n", "15:15 - 0:0\n", "\n", "\n", "\n", "n10:e->x40:w\n", "\n", "\n", "\n", "\n", "\n", "x41\n", "\n", "16:16 - 0:0\n", "\n", "\n", "\n", "n10:e->x41:w\n", "\n", "\n", "\n", "\n", "\n", "x42\n", "\n", "17:17 - 0:0\n", "\n", "\n", "\n", "n10:e->x42:w\n", "\n", "\n", "\n", "\n", "\n", "x43\n", "\n", "2:2 - 0:0\n", "\n", "\n", "\n", "n10:e->x43:w\n", "\n", "\n", "\n", "\n", "\n", "x44\n", "\n", "3:3 - 0:0\n", "\n", "\n", "\n", "n10:e->x44:w\n", "\n", "\n", "\n", "\n", "\n", "x45\n", "\n", "4:4 - 0:0\n", "\n", "\n", "\n", "n10:e->x45:w\n", "\n", "\n", "\n", "\n", "\n", "x46\n", "\n", "5:5 - 0:0\n", "\n", "\n", "\n", "n10:e->x46:w\n", "\n", "\n", "\n", "\n", "\n", "x47\n", "\n", "6:6 - 0:0\n", "\n", "\n", "\n", "n10:e->x47:w\n", "\n", "\n", "\n", "\n", "\n", "x48\n", "\n", "7:7 - 0:0\n", "\n", "\n", "\n", "n10:e->x48:w\n", "\n", "\n", "\n", "\n", "\n", "x49\n", "\n", "8:8 - 0:0\n", "\n", "\n", "\n", "n10:e->x49:w\n", "\n", "\n", "\n", "\n", "\n", "x50\n", "\n", "9:9 - 0:0\n", "\n", "\n", "\n", "n10:e->x50:w\n", "\n", "\n", "\n", "\n", "\n", "x51\n", "\n", "18:18 - 0:0\n", "\n", "\n", "\n", "n10:e->x51:w\n", "\n", "\n", "\n", "\n", "\n", "x52\n", "\n", "19:19 - 0:0\n", "\n", "\n", "\n", "n10:e->x52:w\n", "\n", "\n", "\n", "\n", "\n", "x53\n", "\n", "28:28 - 0:0\n", "\n", "\n", "\n", "n10:e->x53:w\n", "\n", "\n", "\n", "\n", "\n", "x54\n", "\n", "29:29 - 0:0\n", "\n", "\n", "\n", "n10:e->x54:w\n", "\n", "\n", "\n", "\n", "\n", "x55\n", "\n", "30:30 - 0:0\n", "\n", "\n", "\n", "n10:e->x55:w\n", "\n", "\n", "\n", "\n", "\n", "x56\n", "\n", "31:31 - 0:0\n", "\n", "\n", "\n", "n10:e->x56:w\n", "\n", "\n", "\n", "\n", "\n", "x61\n", "\n", "20:20 - 0:0\n", "\n", "\n", "\n", "n10:e->x61:w\n", "\n", "\n", "\n", "\n", "\n", "x62\n", "\n", "21:21 - 0:0\n", "\n", "\n", "\n", "n10:e->x62:w\n", "\n", "\n", "\n", "\n", "\n", "x63\n", "\n", "22:22 - 0:0\n", "\n", "\n", "\n", "n10:e->x63:w\n", "\n", "\n", "\n", "\n", "\n", "x64\n", "\n", "23:23 - 0:0\n", "\n", "\n", "\n", "n10:e->x64:w\n", "\n", "\n", "\n", "\n", "\n", "x65\n", "\n", "24:24 - 0:0\n", "\n", "\n", "\n", "n10:e->x65:w\n", "\n", "\n", "\n", "\n", "\n", "x66\n", "\n", "25:25 - 0:0\n", "\n", "\n", "\n", "n10:e->x66:w\n", "\n", "\n", "\n", "\n", "\n", "x67\n", "\n", "26:26 - 0:0\n", "\n", "\n", "\n", "n10:e->x67:w\n", "\n", "\n", "\n", "\n", "\n", "x68\n", "\n", "27:27 - 0:0\n", "\n", "\n", "\n", "n10:e->x68:w\n", "\n", "\n", "\n", "\n", "\n", "n11\n", "\n", "dout\n", "\n", "\n", "\n", "n12\n", "\n", "we\n", "\n", "\n", "\n", "c22\n", "\n", "A\n", "\n", "B\n", "\n", "$273\n", "$and\n", "\n", "Y\n", "\n", "\n", "\n", "n12:e->c22:w\n", "\n", "\n", "\n", "\n", "\n", "n12:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "n12:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "n12:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "n12:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v0\n", "\n", "1'1\n", "\n", "\n", "\n", "v0:e->c17:w\n", "\n", "\n", "\n", "\n", "\n", "c25\n", "\n", "A\n", "\n", "B\n", "\n", "S\n", "\n", "$277\n", "$mux\n", "\n", "Y\n", "\n", "\n", "\n", "c17:e->c25:w\n", "\n", "\n", "\n", "\n", "\n", "c21:e->c22:w\n", "\n", "\n", "\n", "\n", "\n", "c22:e->c23:w\n", "\n", "\n", "\n", "\n", "\n", "c23:e->c25:w\n", "\n", "\n", "\n", "\n", "\n", "c25:e->n11:w\n", "\n", "\n", "\n", "\n", "\n", "v3\n", "\n", "1'0\n", "\n", "\n", "\n", "v3:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v4\n", "\n", "1'0\n", "\n", "\n", "\n", "v4:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v5\n", "\n", "1'0\n", "\n", "\n", "\n", "v5:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v11\n", "\n", "1'0\n", "\n", "\n", "\n", "v11:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v12\n", "\n", "1'0\n", "\n", "\n", "\n", "v12:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v15\n", "\n", "1'0\n", "\n", "\n", "\n", "v15:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v16\n", "\n", "1'0\n", "\n", "\n", "\n", "v16:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v17\n", "\n", "1'0\n", "\n", "\n", "\n", "v17:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v18\n", "\n", "1'0\n", "\n", "\n", "\n", "v18:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v19\n", "\n", "1'0\n", "\n", "\n", "\n", "v19:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v25\n", "\n", "1'1\n", "\n", "\n", "\n", "v25:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v26\n", "\n", "1'1\n", "\n", "\n", "\n", "v26:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v27\n", "\n", "1'0\n", "\n", "\n", "\n", "v27:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v28\n", "\n", "1'0\n", "\n", "\n", "\n", "v28:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v29\n", "\n", "1'0\n", "\n", "\n", "\n", "v29:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v30\n", "\n", "1'0\n", "\n", "\n", "\n", "v30:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v31\n", "\n", "1'0\n", "\n", "\n", "\n", "v31:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v32\n", "\n", "1'0\n", "\n", "\n", "\n", "v32:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v57\n", "\n", "1'x\n", "\n", "\n", "\n", "v57:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v58\n", "\n", "1'x\n", "\n", "\n", "\n", "v58:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v59\n", "\n", "1'x\n", "\n", "\n", "\n", "v59:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v60\n", "\n", "1'x\n", "\n", "\n", "\n", "v60:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v105\n", "\n", "1'0\n", "\n", "\n", "\n", "v105:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v106\n", "\n", "1'1\n", "\n", "\n", "\n", "v106:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v107\n", "\n", "1'0\n", "\n", "\n", "\n", "v107:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v108\n", "\n", "1'0\n", "\n", "\n", "\n", "v108:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v109\n", "\n", "1'1\n", "\n", "\n", "\n", "v109:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "v110\n", "\n", "1'0\n", "\n", "\n", "\n", "v110:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "x69\n", "\n", "0:0 - 0:0\n", "\n", "\n", "\n", "c142:e->x69:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x70\n", "\n", "0:0 - 1:1\n", "\n", "\n", "\n", "c142:e->x70:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x71\n", "\n", "0:0 - 10:10\n", "\n", "\n", "\n", "c142:e->x71:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x72\n", "\n", "0:0 - 11:11\n", "\n", "\n", "\n", "c142:e->x72:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x73\n", "\n", "0:0 - 12:12\n", "\n", "\n", "\n", "c142:e->x73:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x74\n", "\n", "0:0 - 13:13\n", "\n", "\n", "\n", "c142:e->x74:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x75\n", "\n", "0:0 - 14:14\n", "\n", "\n", "\n", "c142:e->x75:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x76\n", "\n", "0:0 - 15:15\n", "\n", "\n", "\n", "c142:e->x76:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x77\n", "\n", "0:0 - 16:16\n", "\n", "\n", "\n", "c142:e->x77:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x78\n", "\n", "0:0 - 17:17\n", "\n", "\n", "\n", "c142:e->x78:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x79\n", "\n", "0:0 - 2:2\n", "\n", "\n", "\n", "c142:e->x79:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x80\n", "\n", "0:0 - 3:3\n", "\n", "\n", "\n", "c142:e->x80:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x81\n", "\n", "0:0 - 4:4\n", "\n", "\n", "\n", "c142:e->x81:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x82\n", "\n", "0:0 - 5:5\n", "\n", "\n", "\n", "c142:e->x82:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x83\n", "\n", "0:0 - 6:6\n", "\n", "\n", "\n", "c142:e->x83:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x84\n", "\n", "0:0 - 7:7\n", "\n", "\n", "\n", "c142:e->x84:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x85\n", "\n", "0:0 - 8:8\n", "\n", "\n", "\n", "c142:e->x85:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x86\n", "\n", "0:0 - 9:9\n", "\n", "\n", "\n", "c142:e->x86:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x87\n", "\n", "0:0 - 18:18\n", "\n", "\n", "\n", "c142:e->x87:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x88\n", "\n", "0:0 - 19:19\n", "\n", "\n", "\n", "c142:e->x88:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x89\n", "\n", "0:0 - 28:28\n", "\n", "\n", "\n", "c142:e->x89:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x90\n", "\n", "0:0 - 29:29\n", "\n", "\n", "\n", "c142:e->x90:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x91\n", "\n", "0:0 - 30:30\n", "\n", "\n", "\n", "c142:e->x91:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x92\n", "\n", "0:0 - 31:31\n", "\n", "\n", "\n", "c142:e->x92:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x93\n", "\n", "0:0 - 32:32\n", "\n", "\n", "\n", "c142:e->x93:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x94\n", "\n", "0:0 - 33:33\n", "\n", "\n", "\n", "c142:e->x94:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x95\n", "\n", "0:0 - 34:34\n", "\n", "\n", "\n", "c142:e->x95:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x96\n", "\n", "0:0 - 35:35\n", "\n", "\n", "\n", "c142:e->x96:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x97\n", "\n", "0:0 - 20:20\n", "\n", "\n", "\n", "c142:e->x97:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x98\n", "\n", "0:0 - 21:21\n", "\n", "\n", "\n", "c142:e->x98:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x99\n", "\n", "0:0 - 22:22\n", "\n", "\n", "\n", "c142:e->x99:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x100\n", "\n", "0:0 - 23:23\n", "\n", "\n", "\n", "c142:e->x100:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x101\n", "\n", "0:0 - 24:24\n", "\n", "\n", "\n", "c142:e->x101:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x102\n", "\n", "0:0 - 25:25\n", "\n", "\n", "\n", "c142:e->x102:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x103\n", "\n", "0:0 - 26:26\n", "\n", "\n", "\n", "c142:e->x103:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x104\n", "\n", "0:0 - 27:27\n", "\n", "\n", "\n", "c142:e->x104:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x1:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x2:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x6:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x7:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x8:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x9:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x10:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x13:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x14:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x20:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x21:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x22:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x23:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x24:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x33:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x34:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x35:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x36:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x37:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x38:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x39:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x40:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x41:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x42:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x43:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x44:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x45:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x46:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x47:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x48:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x49:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x50:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x51:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x52:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x53:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x54:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x55:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x56:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x61:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x62:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x63:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x64:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x65:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x66:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x67:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "x68:e->c142:w\n", "\n", "\n", "\n", "\n", "\n", "\n", "n2\n", "\n", "\n", "\n", "\n", "x69:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x70:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x71:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x72:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x73:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x74:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x75:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x76:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x77:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x78:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x79:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x80:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x81:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x82:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x83:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x84:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x85:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x86:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x87:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x88:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x89:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x90:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x91:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x92:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "n4\n", "\n", "$278\n", "\n", "\n", "\n", "x93:e->n4:w\n", "\n", "\n", "\n", "\n", "\n", "x94:e->n4:w\n", "\n", "\n", "\n", "\n", "\n", "x95:e->n4:w\n", "\n", "\n", "\n", "\n", "\n", "x96:e->n4:w\n", "\n", "\n", "\n", "\n", "\n", "x97:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x98:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x99:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x100:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x101:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x102:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x103:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x104:e->n2:w\n", "\n", "\n", "\n", "\n", "\n", "x111\n", "\n", "31:0 - 31:0\n", "\n", "\n", "\n", "x111:e->n4:w\n", "\n", "\n", "\n", "\n", "\n", "n2:e->c25:w\n", "\n", "\n", "\n", "\n", "\n", "n2:e->x111:w\n", "\n", "\n", "\n", "\n", "\n", "\\n\n", "\n", "\n", "\n", "\n", "
\n", " " ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from yosys import display\n", "display.display_dot(\"memtest%d\" % DATA_WIDTH)" ] }, { "cell_type": "code", "execution_count": 11, "id": "424093b1-9c91-49b2-b525-33a0939dc641", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "-- Running command `ls; check' --\n", "\n", "17. Executing CHECK pass (checking for obvious problems).\n", "Found and reported 0 problems.\n", "\n", "-- Running command `hierarchy -check' --\n", "\n", "18. Executing HIERARCHY pass (managing design hierarchy).\n", "\n", "-- Running command `write_verilog test1_mapped.v' --\n", "\n", "19. Executing Verilog backend.\n", "\n", "19.1. Executing BMUXMAP pass.\n", "\n", "19.2. Executing DEMUXMAP pass.\n" ] } ], "source": [ "d.write_verilog(\"test1\")" ] }, { "cell_type": "markdown", "id": "5cf85270-c521-4460-b6ae-14dbc92f564a", "metadata": {}, "source": [ "Define a few custom targets:" ] }, { "cell_type": "code", "execution_count": 12, "id": "bcf8521e-7c7e-43a3-98bf-7b628e8e7f60", "metadata": {}, "outputs": [], "source": [ "class CustomTarget(pyosys.RTLIL):\n", " def __init__(self, *args):\n", " super().__init__(*args)\n", " print(\"Selecting %s\" % self.name)\n", " self.debug = True\n", " \n", " def finalize(self, top):\n", " print(\"FINALIZE\")\n", " tname = top.name\n", " design = self._design\n", " design.run(\"hierarchy -top %s\" % tname)\n", " self.synth(design)\n", " design.run('stat', capture = None)\n", " # self.write_cxxrtl(top)\n", "\n", "class GateMateTarget(CustomTarget):\n", " name = \"GateMate\"\n", " \n", " def synth(self, design):\n", " return synth_gatemate(design)\n", "\n", "class ECP5Target(CustomTarget):\n", " name = \"LatticeECP5\"\n", " \n", " def synth(self, design):\n", " design.run(\"read_verilog ../library/tech/lattice/ecp5u/DP16KD.v\")\n", " return synth_ecp5(design) " ] }, { "cell_type": "markdown", "id": "ab796c97-2e63-4f39-9c92-3b976c8dc996", "metadata": {}, "source": [ "Then run post-map simulation on one of them.\n", "\n", "**Note**: For the ECP5 target, you need a *synthesizeable* variant of the `DP16KD.v` entity, or co-simulate using iverilog (currently not integrated into the pyrite simulator API). Let's try the GateMateTarget for now (which includes primitive whitebox models)." ] }, { "cell_type": "code", "execution_count": 13, "id": "291334d1-3f61-4e99-a7c9-70eedd754d1a", "metadata": {}, "outputs": [], "source": [ "import simulation\n", "from yosys.simulator import CXXRTL\n", "\n", "@simulation.sim.testbench(CXXRTL, time_unit = 'ns', target_class = GateMateTarget)\n", "def tb_memtest(MODE = 0, STYLE = 1, data_w=16, addr_w=7, mem = r1w1):\n", " \n", " ClkSignal = simulation.ClkSignal\n", " Signal = simulation.Signal\n", "\n", " c = ClkSignal(name = 'clk')\n", " c.init = True\n", " \n", " M = (1 << (data_w - 1))\n", "\n", " wren = Signal(bool(), name = 'we')\n", " ra, wa = [ Signal(intbv()[addr_w:]) for n in ['addr_write', 'addr_read'] ]\n", " a, q = [ Signal(intbv()[data_w:]) for n in ['a', 'q'] ]\n", "\n", " ram_sig = SigArray([intbv(M | v)[data_w:] for v in range(2 ** addr_w)],\n", " name='ram_sig', init=True)\n", "\n", " # print(ram_sig[0].size())\n", "\n", " inst = mem(clk=c,\n", " we=wren,\n", " addr_r=ra, addr_w=wa, din=a, dout=q, MODE=False, ram = ram_sig,\n", " AWIDTH=addr_w, DWIDTH=data_w,\n", " TRANSPARENCY = True)\n", "\n", " @simulation.always(simulation.delay(2))\n", " def clkgen():\n", " c.next = ~c\n", "\n", " def write(addr, data):\n", " print(\"WRITE\", addr, data)\n", " yield c.negedge\n", " wa.next = addr\n", " a.next = data\n", " wren.next = True\n", " yield c.negedge\n", " wren.next = False\n", "\n", " def write_verify(addr, data, value):\n", " print(\"WRITE VERIFY\", addr)\n", " yield c.negedge\n", " wa.next = addr\n", " a.next = data\n", " wren.next = True\n", " yield c.negedge\n", " # print(\"DEBUG Q\", bin(int(q)))\n", " assert int(q) == value\n", " wren.next = False\n", "\n", " @simulation.sequence\n", " def stim():\n", " ra.next = 0x20\n", " wa.next = 0x00\n", "\n", " # Write and verify that we're not bypassing:\n", " # i.e. the value is expected to be the initial one\n", " yield from write_verify(0x00, 0xaa, M | 0x20)\n", " ra.next = 0x00\n", " yield c.negedge\n", " # Now make sure we're getting the written value\n", " assert int(q) == 0xaa\n", "\n", " # ra == wa, verify transparency bypass:\n", " ra.next = 0x40\n", " yield from write_verify(0x40, 0x55, 0x55)\n", " yield c.negedge\n", " ra.next = 0x00\n", " yield c.negedge\n", " assert int(q) == 0xaa\n", " ra.next = 0x40\n", " yield c.negedge\n", " assert int(q) == 0x55\n", " ra.next = 0x1a\n", " yield c.negedge\n", " assert int(q) == M | 0x1a # Initial\n", "\n", " print(\"SIM DONE\")\n", "\n", " return simulation.instances()\n" ] }, { "cell_type": "code", "execution_count": 14, "id": "07794cf3-cc46-4ac4-8345-02ed2d26adc4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['r1w1_s1_s1_s7_s7_s32_s32_s128_0_32_7_1']" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r1w1.ctx.components" ] }, { "cell_type": "code", "execution_count": 15, "id": "9e5a271d-e9ba-4398-a4ce-55f1d33c3cf4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[32m Module r1w1: Existing instance r1w1, rename to r1w1_1 \u001b[0m\n", "CALLED MEMORY INSTANCE 10\n", "Creating process 'r1w1/mem_rw_transparent' with sensitivity (clk'rising,)\n", "DEBUG: Skip non-simulation type \n", "DEBUG: Skip non-simulation type \n", "DEBUG: Skip non-simulation type \n", "DEBUG: Skip non-simulation type \n", "DEBUG: Skip non-simulation type \n", "DEBUG: Skip non-simulation type \n" ] } ], "source": [ "t = tb_memtest(data_w = 10)" ] }, { "cell_type": "code", "execution_count": 16, "id": "845b6d71-645a-46d5-a46f-c83a339cf776", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Selecting GateMate\n", "DEBUG DUMMY GET s_72ae\n", "\u001b[32m Adding module with name `r1w1_1` \u001b[0m\n", " DEBUG: SKIP ARRAYTYPE `ram` : \n", " DEBUG SLICE READ MEMORY to dout AWIDTH:7 DWIDTH:10\n", "DEBUG ADD ROM 7:10\n", "\u001b[7;34m PARAM PRIORITY --> 48 \u001b[0m\n", "\u001b[7;34m PARAM WORDS --> 128 \u001b[0m\n", "\u001b[7;34m PARAM ABITS --> 7 \u001b[0m\n", "\u001b[7;34m PARAM WIDTH --> 10 \u001b[0m\n", "\u001b[7;34m PARAM MEMID --> $mem_ram_sig \u001b[0m\n", "\u001b[7;34m PARAM CLK_ENABLE --> False \u001b[0m\n", "\u001b[7;34m PARAM CLK_POLARITY --> True \u001b[0m\n", "\u001b[7;34m PARAM TRANSPARENT --> False \u001b[0m\n", "\u001b[7;34m PARAM ABITS --> 7 \u001b[0m\n", "\u001b[7;34m PARAM WIDTH --> 10 \u001b[0m\n", "\u001b[7;34m PARAM MEMID --> $mem_ram_sig \u001b[0m\n", " DEBUG SLICE WRITE MEMORY to ram_sig AWIDTH:7 DWIDTH:10\n", "\u001b[7;34m PARAM CLK_ENABLE --> True \u001b[0m\n", "\u001b[7;34m PARAM CLK_POLARITY --> True \u001b[0m\n", "\u001b[7;34m PARAM PRIORITY --> 48 \u001b[0m\n", "\u001b[7;34m PARAM ABITS --> 7 \u001b[0m\n", "\u001b[7;34m PARAM WIDTH --> 10 \u001b[0m\n", "\u001b[7;34m PARAM MEMID --> $mem_ram_sig \u001b[0m\n", "DEBUG TOP LEVEL WRITE MEM ram_sig\n", "FINALIZE\n", "Dumping module `\\r1w1'.\n", "\n", "-- Running command `tee -q hierarchy -top r1w1_1' --\n", "\n", "-- Running command `tee -q read_verilog -lib -specify /usr/share/yosys/gatemate/cells_sim.v /usr/share/yosys/gatemate/cells_bb.v' --\n", "\n", "-- Running command `tee -q memory_libmap -lib /usr/share/yosys/gatemate/brams.txt' --\n", "\n", "-- Running command `tee -q techmap -map /usr/share/yosys/gatemate/brams_map.v' --\n", "\n", "-- Running command `tee -q opt' --\n", "\n", "-- Running command `stat' --\n", "\n", "26. Printing statistics.\n", "\n", "=== r1w1_1 ===\n", "\n", " Number of wires: 10\n", " Number of wire bits: 58\n", " Number of public wires: 6\n", " Number of public wire bits: 36\n", " Number of memories: 1\n", " Number of memory bits: 1280\n", " Number of processes: 0\n", " Number of cells: 7\n", " $and 1\n", " $dff 1\n", " $eq 1\n", " $meminit 1\n", " $memrd 1\n", " $memwr 1\n", " $mux 1\n", "\n", "\n", "-- Running command `tee -q debug memory -nomap' --\n", "\n", "-- Running command `write_rtlil top.il' --\n", "\n", "28. Executing RTLIL backend.\n", "Output filename: top.il\n", "\n", "-- Running command `show -format dot -prefix r1w1_1 *' --\n", "\n", "29. Generating Graphviz representation of design.\n", "Writing dot description to `r1w1_1.dot'.\n", "Dumping module r1w1_1 to page 1.\n", "DEBUG DUMMY GET s_72ae\n", "Tolerate exception: Module with name `r1w1_1` already existing\n", "Compiling /tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516.pyx because it changed.\n", "[1/1] Cythonizing /tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516.pyx\n", "running build_ext\n", "building 'r1w1_1_1516' extension\n", "creating build/temp.linux-x86_64-3.9/tmp/myirl_r1w1_td9ph_lc\n", "x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -DCOSIM_NAMESPACE=r1w1_1_1516 -I../../myirl/../ -I/tmp/myirl_r1w1_td9ph_lc/ -I/usr/share/yosys/include -I/usr/include/python3.9 -c /tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516.cpp -o build/temp.linux-x86_64-3.9/tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516.o\n", "x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -DCOSIM_NAMESPACE=r1w1_1_1516 -I../../myirl/../ -I/tmp/myirl_r1w1_td9ph_lc/ -I/usr/share/yosys/include -I/usr/include/python3.9 -c /tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516_rtl.cpp -o build/temp.linux-x86_64-3.9/tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516_rtl.o\n", "x86_64-linux-gnu-g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fwrapv -O2 -Wl,-z,relro -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.9/tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516.o build/temp.linux-x86_64-3.9/tmp/myirl_r1w1_td9ph_lc/r1w1_1_1516_rtl.o -o build/lib.linux-x86_64-3.9/r1w1_1_1516.cpython-39-x86_64-linux-gnu.so\n", "copying build/lib.linux-x86_64-3.9/r1w1_1_1516.cpython-39-x86_64-linux-gnu.so -> \n", "Open for writing: tb_memtest.vcd\n", "\u001b[7;35m CXXRTL context: SKIP INTERFACE ITEM `ram` \u001b[0m\n", "\u001b[7;35m CXXRTL context: SKIP INTERFACE ITEM `MODE` \u001b[0m\n", "\u001b[7;35m CXXRTL context: SKIP INTERFACE ITEM `DWIDTH` \u001b[0m\n", "\u001b[7;35m CXXRTL context: SKIP INTERFACE ITEM `AWIDTH` \u001b[0m\n", "\u001b[7;35m CXXRTL context: SKIP INTERFACE ITEM `TRANSPARENCY` \u001b[0m\n", "WRITE VERIFY 0\n", "WRITE VERIFY 64\n", "SIM DONE\n", "DEBUG STOP PROCESS stim\n" ] } ], "source": [ "t.debug()\n", "t.run(100)\n", "# t.design.run(\"write_rtlil memtest.il\")" ] }, { "cell_type": "markdown", "id": "eab18935-198d-4913-abaf-fef452893867", "metadata": {}, "source": [ "# Duplex read, single write\n", "\n", "**Attention**: The pyosys API may crash the notebook without warning (terminate the kernel) when the yosys-abc utility is not present. May be the case in the Binder setup." ] }, { "cell_type": "code", "execution_count": 17, "id": "ad6d1f72-9ef2-4a1b-bfc2-3c6d798f45db", "metadata": {}, "outputs": [], "source": [ "# ! [ `which yosys-abc` ] || sudo apt-get install yosys-ghdl" ] }, { "cell_type": "code", "execution_count": 18, "id": "8822ff8e-8c41-4a8b-a5b2-412464d70b91", "metadata": {}, "outputs": [], "source": [ "@block\n", "def r2w1_gated(\n", " clk : ClkSignal,\n", " re\t: (Signal, bool),\n", " we\t: Signal,\n", " addr_r0: Signal,\n", " addr_r1: Signal,\n", " addr_w: Signal,\n", " din: Signal,\n", " dout0: Signal.Output,\n", " dout1: Signal.Output,\n", " ram_data : list,\n", " MODE = False, # Conditional compilation flag w/o type annotation\n", " DWIDTH=16, AWIDTH=10\n", " ) -> IRL:\n", "\n", " ram = SigArray(ram_data, name='ram_sig', init=True)\n", "\n", " @always(clk.posedge)\n", " def mem_r2w():\n", " dout1.next = ram[addr_r1]\n", " if re:\n", " dout0.next = ram[addr_r0]\n", " if we:\n", " ram[addr_w].next = din\n", "\n", " return instances()\n" ] }, { "cell_type": "code", "execution_count": 19, "id": "1a606901-cf08-44cb-bd12-fb768581bf53", "metadata": {}, "outputs": [], "source": [ "@simulation.sim.testbench(CXXRTL, time_unit = 'ns', target_class = ECP5Target)\n", "def tb_memtest2(MODE = 0, STYLE = 1, data_w=16, addr_w=6, mem = r2w1_gated):\n", " c = simulation.ClkSignal(name = 'clk')\n", " c.init = True\n", " rden = simulation.Signal(bool(), name = 're')\n", " wren = simulation.Signal(bool(), name = 'we')\n", " ra, rb, wa = [ simulation.Signal(intbv()[addr_w:]) for _ in range(3) ]\n", " a, q0, q1 = [ simulation.Signal(intbv()[data_w:]) for n in ['a', 'q0', 'q1'] ]\n", "\n", " ram_data = [ intbv(v)[data_w:] for v in range(2 ** addr_w)]\n", "\n", " inst = mem(clk=c,\n", " re=rden,\n", " we=wren,\n", " addr_r0=ra,\n", " addr_r1=rb,\n", " addr_w=wa, din=a,\n", " dout0=q0, dout1=q1,\n", " MODE=False, ram_data = ram_data,\n", " AWIDTH=addr_w, DWIDTH=data_w)\n", "\n", " @simulation.always(simulation.delay(2))\n", " def clkgen():\n", " c.next = ~c\n", "\n", " @simulation.sequence\n", " def stim():\n", " rb.next = 0xfa\n", " ra.next = 0xfa\n", " wa.next = 0x20\n", " wren.next = False\n", " yield simulation.delay(5)\n", " yield c.negedge\n", " assert int(q1) == 0xfa\n", " assert int(q0) != 0xfa\n", " rden.next = True\n", " yield c.negedge\n", " ra.next = 0xaa\n", " rden.next = False\n", "\n", " wren.next = True\n", " a.next = 0x44\n", " yield c.negedge\n", " wren.next = False\n", " yield c.negedge\n", " assert int(q0) == 0xfa\n", " yield c.negedge\n", " rb.next = 0x20\n", " print(int(q0), int(q1))\n", " yield c.negedge\n", " print(int(q0), int(q1))\n", " assert int(q1) == 0x44\n", "\n", " print(\"SIM DONE\")\n", "\n", " return simulation.instances()\n" ] }, { "cell_type": "code", "execution_count": null, "id": "8c1d6582-82d6-4ef6-89e0-9b1bce8f4223", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Creating process 'r2w1_gated/mem_r2w' with sensitivity (clk'rising,)\n", "DEBUG: Skip non-simulation type \n", "DEBUG: Skip non-simulation type \n", "Selecting LatticeECP5\n", "DEBUG DUMMY GET s_bb42\n", "\u001b[32m Adding module with name `r2w1_gated` \u001b[0m\n", " DEBUG: SKIP NON-SIGNAL ARGUMENT `ram_data` : \n", " DEBUG SLICE READ MEMORY to dout1 AWIDTH:9 DWIDTH:16\n" ] } ], "source": [ "dw = 16\n", "\n", "MEM = r2w1_gated\n", "\n", "tb = tb_memtest2(data_w=dw, mem = MEM, addr_w = 9)\n", "tb._force_compile = True\n", "# tb.debug()\n", "# tb.run(200)\n" ] }, { "cell_type": "code", "execution_count": null, "id": "39ebbd5f-bc53-4c70-8599-4683bf845e24", "metadata": {}, "outputs": [], "source": [ "tb.design.run(\"write_rtlil r2w1.il\", capture = None)" ] }, { "cell_type": "code", "execution_count": null, "id": "a4097464-7e63-43e8-ae4d-f2f1a519ad32", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.2" } }, "nbformat": 4, "nbformat_minor": 5 }