Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Create annotation to allow inline readmem in Verilog #2107

Merged
merged 1 commit into from
Mar 9, 2021

Conversation

carlosedp
Copy link
Contributor

@carlosedp carlosedp commented Mar 8, 2021

This PR adds a new annotation allowing inline loading for memory files in Verilog code.

Below a sample code:

package utils

import chisel3._
import chisel3.experimental.{ChiselAnnotation, annotate}
import firrtl.annotations.{MemoryFileInlineAnnotation}

class DualPortRAM(words: Int = 1, width: Int = 32, memoryFile: String = "")
    extends Module {
  val addrWidth = chiselTypeOf((words * 1024).U)
  val io = IO(new Bundle {
    // Port 1
    val addr1 = Input(addrWidth)
    val addr2 = Input(addrWidth)
    val dataIn1 = Input(UInt(width.W))
    val we1 = Input(Bool())
    val dataOut1 = Output(UInt(width.W))
    val dataOut2 = Output(UInt(width.W))
  })
  println(s"Dual-port Memory Parameters:")
  println(s"  Size (words): $words")
  println(s"  Size (kb): " + words * width + " Kb")
  println(s"  Width: $width bit")
  println(s"  Addr Width: " + io.addr1.getWidth + " bit")

  val mem = SyncReadMem(words, UInt(width.W))
  annotate(new ChiselAnnotation {
    override def toFirrtl = MemoryFileInlineAnnotation(mem.toTarget, memoryFile)
  })

  // Port 1
  io.dataOut1 := mem.read(io.addr1)
  when(io.we1) {
    mem.write(io.addr1, io.dataIn1)
  }
  // Port 2
  io.dataOut2 := mem.read(io.addr2)
}

object DualPortRAMObj extends App {
  (new chisel3.stage.ChiselStage).emitVerilog(
    new DualPortRAM(16, width = 64, memoryFile = "sample.hex"),
    Array("-X", "verilog") ++ args
  )
}

Generated verilog:

module DualPortRAM(
  input         clock,
  input         reset,
  input  [14:0] io_addr1,
  input  [14:0] io_addr2,
  input  [63:0] io_dataIn1,
  input         io_we1,
  output [63:0] io_dataOut1,
  output [63:0] io_dataOut2
);
`ifdef RANDOMIZE_REG_INIT
  reg [31:0] _RAND_0;
  reg [31:0] _RAND_1;
`endif // RANDOMIZE_REG_INIT
  reg [63:0] mem [0:15]; // @[DualportRAM.scala 25:24]
  wire [63:0] mem_MPORT_data; // @[DualportRAM.scala 25:24]
  wire [3:0] mem_MPORT_addr; // @[DualportRAM.scala 25:24]
  wire [63:0] mem_MPORT_2_data; // @[DualportRAM.scala 25:24]
  wire [3:0] mem_MPORT_2_addr; // @[DualportRAM.scala 25:24]
  wire [63:0] mem_MPORT_1_data; // @[DualportRAM.scala 25:24]
  wire [3:0] mem_MPORT_1_addr; // @[DualportRAM.scala 25:24]
  wire  mem_MPORT_1_mask; // @[DualportRAM.scala 25:24]
  wire  mem_MPORT_1_en; // @[DualportRAM.scala 25:24]
  reg [3:0] mem_MPORT_addr_pipe_0;
  reg [3:0] mem_MPORT_2_addr_pipe_0;
  assign mem_MPORT_addr = mem_MPORT_addr_pipe_0;
  assign mem_MPORT_data = mem[mem_MPORT_addr]; // @[DualportRAM.scala 25:24]
  assign mem_MPORT_2_addr = mem_MPORT_2_addr_pipe_0;
  assign mem_MPORT_2_data = mem[mem_MPORT_2_addr]; // @[DualportRAM.scala 25:24]
  assign mem_MPORT_1_data = io_dataIn1;
  assign mem_MPORT_1_addr = io_addr1[3:0];
  assign mem_MPORT_1_mask = 1'h1;
  assign mem_MPORT_1_en = io_we1;
  assign io_dataOut1 = mem_MPORT_data; // @[DualportRAM.scala 31:15]
  assign io_dataOut2 = mem_MPORT_2_data; // @[DualportRAM.scala 36:15]
  always @(posedge clock) begin
    if (mem_MPORT_1_en & mem_MPORT_1_mask) begin
      mem[mem_MPORT_1_addr] <= mem_MPORT_1_data; // @[DualportRAM.scala 25:24]
    end
    mem_MPORT_addr_pipe_0 <= io_addr1[3:0];
    mem_MPORT_2_addr_pipe_0 <= io_addr2[3:0];
  end
// Register and memory initialization
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
  integer initvar;
`ifndef SYNTHESIS
`ifdef FIRRTL_BEFORE_INITIAL
`FIRRTL_BEFORE_INITIAL
`endif
initial begin
  `ifdef RANDOMIZE
    `ifdef INIT_RANDOM
      `INIT_RANDOM
    `endif
    `ifndef VERILATOR
      `ifdef RANDOMIZE_DELAY
        #`RANDOMIZE_DELAY begin end
      `else
        #0.002 begin end
      `endif
    `endif
`ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{`RANDOM}};
  mem_MPORT_addr_pipe_0 = _RAND_0[3:0];
  _RAND_1 = {1{`RANDOM}};
  mem_MPORT_2_addr_pipe_0 = _RAND_1[3:0];
`endif // RANDOMIZE_REG_INIT
  `endif // RANDOMIZE

initial begin
  $readmemh("sample.hex", mem);
end
end // initial
`ifdef FIRRTL_AFTER_INITIAL
`FIRRTL_AFTER_INITIAL
`endif
`endif // SYNTHESIS
endmodule

Generated Verilog file was synthesized on Yosys for testing. Output below:

Details
❯ docker run --rm -v $(PWD):/src -w /src ghdl/synth:beta yosys -p "read_verilog -sv DualPortRAM.v ; synth_ecp5 -json ram.json -top DualPortRAM"

 /----------------------------------------------------------------------------\
 |                                                                            |
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |                                                                            |
 |  Copyright (C) 2012 - 2020  Claire Wolf <claire@symbioticeda.com>          |
 |                                                                            |
 |  Permission to use, copy, modify, and/or distribute this software for any  |
 |  purpose with or without fee is hereby granted, provided that the above    |
 |  copyright notice and this permission notice appear in all copies.         |
 |                                                                            |
 |  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  |
 |  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF          |
 |  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR   |
 |  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    |
 |  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN     |
 |  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   |
 |  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.            |
 |                                                                            |
 \----------------------------------------------------------------------------/

 Yosys 0.9+3675 (git sha1 UNKNOWN, clang 7.0.1-8+deb10u2 -fPIC -Os)


-- Running command `read_verilog -sv DualPortRAM.v ; synth_ecp5 -json ram.json -top DualPortRAM' --

1. Executing Verilog-2005 frontend: DualPortRAM.v
Parsing SystemVerilog input from `DualPortRAM.v' to AST representation.
Generating RTLIL representation for module `\DualPortRAM'.
Successfully finished Verilog frontend.

2. Executing SYNTH_ECP5 pass.

2.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/cells_sim.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/cells_sim.v' to AST representation.
Generating RTLIL representation for module `\LUT4'.
Generating RTLIL representation for module `\$__ABC9_LUT5'.
Generating RTLIL representation for module `\$__ABC9_LUT6'.
Generating RTLIL representation for module `\$__ABC9_LUT7'.
Generating RTLIL representation for module `\L6MUX21'.
Generating RTLIL representation for module `\CCU2C'.
Generating RTLIL representation for module `\TRELLIS_RAM16X2'.
Generating RTLIL representation for module `\PFUMX'.
Generating RTLIL representation for module `\TRELLIS_DPR16X4'.
Generating RTLIL representation for module `\DPR16X4C'.
Generating RTLIL representation for module `\LUT2'.
Generating RTLIL representation for module `\TRELLIS_FF'.
Generating RTLIL representation for module `\TRELLIS_IO'.
Generating RTLIL representation for module `\INV'.
Generating RTLIL representation for module `\TRELLIS_SLICE'.
Generating RTLIL representation for module `\DP16KD'.
Generating RTLIL representation for module `\FD1P3AX'.
Generating RTLIL representation for module `\FD1P3AY'.
Generating RTLIL representation for module `\FD1P3BX'.
Generating RTLIL representation for module `\FD1P3DX'.
Generating RTLIL representation for module `\FD1P3IX'.
Generating RTLIL representation for module `\FD1P3JX'.
Generating RTLIL representation for module `\FD1S3AX'.
Generating RTLIL representation for module `\FD1S3AY'.
Generating RTLIL representation for module `\FD1S3BX'.
Generating RTLIL representation for module `\FD1S3DX'.
Generating RTLIL representation for module `\FD1S3IX'.
Generating RTLIL representation for module `\FD1S3JX'.
Generating RTLIL representation for module `\IFS1P3BX'.
Generating RTLIL representation for module `\IFS1P3DX'.
Generating RTLIL representation for module `\IFS1P3IX'.
Generating RTLIL representation for module `\IFS1P3JX'.
Generating RTLIL representation for module `\OFS1P3BX'.
Generating RTLIL representation for module `\OFS1P3DX'.
Generating RTLIL representation for module `\OFS1P3IX'.
Generating RTLIL representation for module `\OFS1P3JX'.
Generating RTLIL representation for module `\IB'.
Generating RTLIL representation for module `\IBPU'.
Generating RTLIL representation for module `\IBPD'.
Generating RTLIL representation for module `\OB'.
Generating RTLIL representation for module `\OBZ'.
Generating RTLIL representation for module `\OBZPU'.
Generating RTLIL representation for module `\OBZPD'.
Generating RTLIL representation for module `\OBCO'.
Generating RTLIL representation for module `\BB'.
Generating RTLIL representation for module `\BBPU'.
Generating RTLIL representation for module `\BBPD'.
Generating RTLIL representation for module `\ILVDS'.
Generating RTLIL representation for module `\OLVDS'.
Successfully finished Verilog frontend.

2.2. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/cells_bb.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/cells_bb.v' to AST representation.
Generating RTLIL representation for module `\MULT18X18D'.
Generating RTLIL representation for module `\ALU54B'.
Generating RTLIL representation for module `\EHXPLLL'.
Generating RTLIL representation for module `\DTR'.
Generating RTLIL representation for module `\OSCG'.
Generating RTLIL representation for module `\USRMCLK'.
Generating RTLIL representation for module `\JTAGG'.
Generating RTLIL representation for module `\DELAYF'.
Generating RTLIL representation for module `\DELAYG'.
Generating RTLIL representation for module `\IDDRX1F'.
Generating RTLIL representation for module `\IDDRX2F'.
Generating RTLIL representation for module `\IDDR71B'.
Generating RTLIL representation for module `\IDDRX2DQA'.
Generating RTLIL representation for module `\ODDRX1F'.
Generating RTLIL representation for module `\ODDRX2F'.
Generating RTLIL representation for module `\ODDR71B'.
Generating RTLIL representation for module `\OSHX2A'.
Generating RTLIL representation for module `\ODDRX2DQA'.
Generating RTLIL representation for module `\ODDRX2DQSB'.
Generating RTLIL representation for module `\TSHX2DQA'.
Generating RTLIL representation for module `\TSHX2DQSA'.
Generating RTLIL representation for module `\DQSBUFM'.
Generating RTLIL representation for module `\DDRDLLA'.
Generating RTLIL representation for module `\CLKDIVF'.
Generating RTLIL representation for module `\ECLKSYNCB'.
Generating RTLIL representation for module `\ECLKBRIDGECS'.
Generating RTLIL representation for module `\DCCA'.
Generating RTLIL representation for module `\DCUA'.
Generating RTLIL representation for module `\EXTREFB'.
Generating RTLIL representation for module `\PCSCLKDIV'.
Generating RTLIL representation for module `\PUR'.
Generating RTLIL representation for module `\GSR'.
Generating RTLIL representation for module `\SGSR'.
Generating RTLIL representation for module `\PDPW16KD'.
Successfully finished Verilog frontend.

2.3. Executing HIERARCHY pass (managing design hierarchy).

2.3.1. Analyzing design hierarchy..
Top module:  \DualPortRAM

2.3.2. Analyzing design hierarchy..
Top module:  \DualPortRAM
Removed 0 unused modules.

2.4. Executing PROC pass (convert processes to netlists).

2.4.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Found and cleaned up 1 empty switch in `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:213$155'.
Cleaned up 1 empty switch.

2.4.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
Marked 1 switch rules as full_case in process $proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:350$235 in module TRELLIS_FF.
Removed a total of 0 dead cases.

2.4.3. Executing PROC_PRUNE pass (remove redundant assignments in processes).
Removed 0 redundant assignments.
Promoted 7 assignments to connections.

2.4.4. Executing PROC_INIT pass (extract init attributes).
Found init rule in `\TRELLIS_FF.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$239'.
  Set init value: \Q = 1'0

2.4.5. Executing PROC_ARST pass (detect async resets in processes).

2.4.6. Executing PROC_MUX pass (convert decision trees to multiplexers).
Creating decoders for process `\TRELLIS_FF.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$239'.
Creating decoders for process `\TRELLIS_FF.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:350$235'.
     1/1: $0\Q[0:0]
Creating decoders for process `\DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$232'.
Creating decoders for process `\DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:285$211'.
     1/3: $0$memwr$\ram$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:287$210_EN[3:0]$214
     2/3: $0$memwr$\ram$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:287$210_DATA[3:0]$213
     3/3: $0$memwr$\ram$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:287$210_ADDR[3:0]$212
Creating decoders for process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$178'.
Creating decoders for process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:221$156'.
     1/3: $0$memwr$\mem$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:223$154_EN[3:0]$159
     2/3: $0$memwr$\mem$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:223$154_DATA[3:0]$158
     3/3: $0$memwr$\mem$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:223$154_ADDR[3:0]$157
Creating decoders for process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:213$155'.
Creating decoders for process `\DualPortRAM.$proc$DualPortRAM.v:36$4'.
     1/3: $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7
     2/3: $0$memwr$\mem$DualPortRAM.v:38$1_DATA[63:0]$6
     3/3: $0$memwr$\mem$DualPortRAM.v:38$1_ADDR[13:0]$5

2.4.7. Executing PROC_DLATCH pass (convert process syncs to latches).

2.4.8. Executing PROC_DFF pass (convert process syncs to FFs).
Creating register for signal `\TRELLIS_FF.\Q' using process `\TRELLIS_FF.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:350$235'.
  created $dff cell `$procdff$263' with positive edge clock.
Creating register for signal `\DPR16X4C.\i' using process `\DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$232'.
  created direct connection (no actual register cell created).
Creating register for signal `\DPR16X4C.$memwr$\ram$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:287$210_ADDR' using process `\DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:285$211'.
  created $dff cell `$procdff$264' with positive edge clock.
Creating register for signal `\DPR16X4C.$memwr$\ram$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:287$210_DATA' using process `\DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:285$211'.
  created $dff cell `$procdff$265' with positive edge clock.
Creating register for signal `\DPR16X4C.$memwr$\ram$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:287$210_EN' using process `\DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:285$211'.
  created $dff cell `$procdff$266' with positive edge clock.
Creating register for signal `\TRELLIS_DPR16X4.\i' using process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$178'.
  created direct connection (no actual register cell created).
Creating register for signal `\TRELLIS_DPR16X4.$memwr$\mem$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:223$154_ADDR' using process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:221$156'.
  created $dff cell `$procdff$267' with positive edge clock.
Creating register for signal `\TRELLIS_DPR16X4.$memwr$\mem$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:223$154_DATA' using process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:221$156'.
  created $dff cell `$procdff$268' with positive edge clock.
Creating register for signal `\TRELLIS_DPR16X4.$memwr$\mem$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:223$154_EN' using process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:221$156'.
  created $dff cell `$procdff$269' with positive edge clock.
Creating register for signal `\TRELLIS_DPR16X4.\muxwre' using process `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:213$155'.
  created direct connection (no actual register cell created).
Creating register for signal `\DualPortRAM.\mem_MPORT_addr_pipe_0' using process `\DualPortRAM.$proc$DualPortRAM.v:36$4'.
  created $dff cell `$procdff$270' with positive edge clock.
Creating register for signal `\DualPortRAM.\mem_MPORT_2_addr_pipe_0' using process `\DualPortRAM.$proc$DualPortRAM.v:36$4'.
  created $dff cell `$procdff$271' with positive edge clock.
Creating register for signal `\DualPortRAM.$memwr$\mem$DualPortRAM.v:38$1_ADDR' using process `\DualPortRAM.$proc$DualPortRAM.v:36$4'.
  created $dff cell `$procdff$272' with positive edge clock.
Creating register for signal `\DualPortRAM.$memwr$\mem$DualPortRAM.v:38$1_DATA' using process `\DualPortRAM.$proc$DualPortRAM.v:36$4'.
  created $dff cell `$procdff$273' with positive edge clock.
Creating register for signal `\DualPortRAM.$memwr$\mem$DualPortRAM.v:38$1_EN' using process `\DualPortRAM.$proc$DualPortRAM.v:36$4'.
  created $dff cell `$procdff$274' with positive edge clock.

2.4.9. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Removing empty process `TRELLIS_FF.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$239'.
Found and cleaned up 2 empty switches in `\TRELLIS_FF.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:350$235'.
Removing empty process `TRELLIS_FF.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:350$235'.
Removing empty process `DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$232'.
Found and cleaned up 1 empty switch in `\DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:285$211'.
Removing empty process `DPR16X4C.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:285$211'.
Removing empty process `TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:0$178'.
Found and cleaned up 1 empty switch in `\TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:221$156'.
Removing empty process `TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:221$156'.
Removing empty process `TRELLIS_DPR16X4.$proc$/usr/local/bin/../share/yosys/ecp5/cells_sim.v:213$155'.
Found and cleaned up 1 empty switch in `\DualPortRAM.$proc$DualPortRAM.v:36$4'.
Removing empty process `DualPortRAM.$proc$DualPortRAM.v:36$4'.
Cleaned up 5 empty switches.

2.5. Executing FLATTEN pass (flatten design).

2.6. Executing TRIBUF pass.

2.7. Executing DEMINOUT pass (demote inout ports to input or output).

2.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.
<suppressed ~1 debug messages>

2.9. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..
Removed 0 unused cells and 12 unused wires.
<suppressed ~2 debug messages>

2.10. Executing CHECK pass (checking for obvious problems).
checking module DualPortRAM..
found and reported 0 problems.

2.11. Executing OPT pass (performing simple optimizations).

2.11.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.11.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.11.3. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \DualPortRAM..
  Creating internal representation of mux trees.
  Evaluating internal representation of mux trees.
  Analyzing evaluation results.
Removed 0 multiplexer ports.
<suppressed ~3 debug messages>

2.11.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
  Optimizing cells in module \DualPortRAM.
    Consolidated identical input bits for $mux cell $procmux$257:
      Old ports: A=64'0000000000000000000000000000000000000000000000000000000000000000, B=64'1111111111111111111111111111111111111111111111111111111111111111, Y=$0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7
      New ports: A=1'0, B=1'1, Y=$0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0]
      New connections: $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [63:1] = { $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] $0$memwr$\mem$DualPortRAM.v:38$1_EN[63:0]$7 [0] }
  Optimizing cells in module \DualPortRAM.
Performed a total of 1 changes.

2.11.5. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.11.6. Executing OPT_DFF pass (perform DFF optimizations).

2.11.7. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.11.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.11.9. Rerunning OPT passes. (Maybe there is more to do..)

2.11.10. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \DualPortRAM..
  Creating internal representation of mux trees.
  Evaluating internal representation of mux trees.
  Analyzing evaluation results.
Removed 0 multiplexer ports.
<suppressed ~3 debug messages>

2.11.11. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
  Optimizing cells in module \DualPortRAM.
Performed a total of 0 changes.

2.11.12. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.11.13. Executing OPT_DFF pass (perform DFF optimizations).

2.11.14. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.11.15. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.11.16. Finished OPT passes. (There is nothing left to do.)

2.12. Executing FSM pass (extract and optimize FSM).

2.12.1. Executing FSM_DETECT pass (finding FSMs in design).
Not marking DualPortRAM.$memwr$\mem$DualPortRAM.v:38$1_EN as FSM state register:
    Users of register don't seem to benefit from recoding.

2.12.2. Executing FSM_EXTRACT pass (extracting FSM from design).

2.12.3. Executing FSM_OPT pass (simple optimizations of FSMs).

2.12.4. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.12.5. Executing FSM_OPT pass (simple optimizations of FSMs).

2.12.6. Executing FSM_RECODE pass (re-assigning FSM state encoding).

2.12.7. Executing FSM_INFO pass (dumping all available information on FSM cells).

2.12.8. Executing FSM_MAP pass (mapping FSMs to basic logic).

2.13. Executing OPT pass (performing simple optimizations).

2.13.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.13.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.13.3. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \DualPortRAM..
  Creating internal representation of mux trees.
  Evaluating internal representation of mux trees.
  Analyzing evaluation results.
Removed 0 multiplexer ports.
<suppressed ~3 debug messages>

2.13.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
  Optimizing cells in module \DualPortRAM.
Performed a total of 0 changes.

2.13.5. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.13.6. Executing OPT_DFF pass (perform DFF optimizations).

2.13.7. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.13.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.13.9. Finished OPT passes. (There is nothing left to do.)

2.14. Executing WREDUCE pass (reducing word size of cells).
Removed cell DualPortRAM.$procmux$259 ($mux).
Removed cell DualPortRAM.$procmux$261 ($mux).
Removed top 63 bits (of 64) from FF cell DualPortRAM.$procdff$274 ($dff).

2.15. Executing PEEPOPT pass (run peephole optimizers).

2.16. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..
Removed 0 unused cells and 2 unused wires.
<suppressed ~1 debug messages>

2.17. Executing SHARE pass (SAT-based resource sharing).

2.18. Executing TECHMAP pass (map to technology primitives).

2.18.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/cmp2lut.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/cmp2lut.v' to AST representation.
Generating RTLIL representation for module `\_90_lut_cmp_'.
Successfully finished Verilog frontend.

2.18.2. Continuing TECHMAP pass.
No more expansions possible.
<suppressed ~6 debug messages>

2.19. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.20. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.21. Executing TECHMAP pass (map to technology primitives).

2.21.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/mul2dsp.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/mul2dsp.v' to AST representation.
Generating RTLIL representation for module `\_80_mul'.
Generating RTLIL representation for module `\_90_soft_mul'.
Successfully finished Verilog frontend.

2.21.2. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/dsp_map.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/dsp_map.v' to AST representation.
Generating RTLIL representation for module `\$__MUL18X18'.
Successfully finished Verilog frontend.

2.21.3. Continuing TECHMAP pass.
No more expansions possible.
<suppressed ~5 debug messages>

2.22. Executing ALUMACC pass (create $alu and $macc cells).
Extracting $alu and $macc cells in module DualPortRAM:
  created 0 $alu and 0 $macc cells.

2.23. Executing OPT pass (performing simple optimizations).

2.23.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.23.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
<suppressed ~3 debug messages>
Removed a total of 1 cells.

2.23.3. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \DualPortRAM..
  Creating internal representation of mux trees.
  Evaluating internal representation of mux trees.
  Analyzing evaluation results.
Removed 0 multiplexer ports.
<suppressed ~1 debug messages>

2.23.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
  Optimizing cells in module \DualPortRAM.
Performed a total of 0 changes.

2.23.5. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.23.6. Executing OPT_DFF pass (perform DFF optimizations).

2.23.7. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..
Removed 0 unused cells and 1 unused wires.
<suppressed ~1 debug messages>

2.23.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.23.9. Rerunning OPT passes. (Maybe there is more to do..)

2.23.10. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \DualPortRAM..
  Creating internal representation of mux trees.
  Evaluating internal representation of mux trees.
  Analyzing evaluation results.
Removed 0 multiplexer ports.
<suppressed ~1 debug messages>

2.23.11. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
  Optimizing cells in module \DualPortRAM.
Performed a total of 0 changes.

2.23.12. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.23.13. Executing OPT_DFF pass (perform DFF optimizations).

2.23.14. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.23.15. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.23.16. Finished OPT passes. (There is nothing left to do.)

2.24. Executing MEMORY pass.

2.24.1. Executing OPT_MEM pass (optimize memories).
Performed a total of 0 transformations.

2.24.2. Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).
Checking cell `$memwr$\mem$DualPortRAM.v:0$9' in module `\DualPortRAM': merged $dff to cell.
Checking cell `$memrd$\mem$DualPortRAM.v:27$2' in module `\DualPortRAM': merged address $dff to cell.
Checking cell `$memrd$\mem$DualPortRAM.v:29$3' in module `\DualPortRAM': merged address $dff to cell.

2.24.3. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..
Removed 4 unused cells and 6 unused wires.
<suppressed ~9 debug messages>

2.24.4. Executing MEMORY_SHARE pass (consolidating $memrd/$memwr cells).

2.24.5. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.24.6. Executing MEMORY_COLLECT pass (generating $mem cells).

2.25. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.26. Executing MEMORY_BRAM pass (mapping $mem cells to block memories).
Processing DualPortRAM.mem:
  Properties: ports=3 bits=1048576 rports=2 wports=1 dbits=64 abits=14 words=16384
  Checking rule #1 for bram type $__ECP5_PDPW16KD (variant 1):
    Bram geometry: abits=9 dbits=36 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_PDPW16KD: awaste=0 dwaste=8 bwaste=4096 waste=4096 efficiency=88
    Rule #1 for bram type $__ECP5_PDPW16KD (variant 1) accepted.
    Mapping to bram type $__ECP5_PDPW16KD (variant 1):
      Shuffle bit order to accommodate enable buckets of size 9..
      Results of bit order shuffling: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 -1 -1 -1 -1 -1 -1 -1 -1
      Write port #0 is in clock domain \clock.
        Mapped to bram port A1.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Failed to map read port #1.
      Growing more read ports by duplicating bram cells.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Mapped to bram port B1.2.
      Updated properties: dups=2 waste=8192 efficiency=44
      Storing for later selection.
  Checking rule #2 for bram type $__ECP5_PDPW16KD (variant 1):
    Bram geometry: abits=9 dbits=36 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_PDPW16KD: awaste=0 dwaste=8 bwaste=4096 waste=4096 efficiency=88
    Rule for bram type $__ECP5_PDPW16KD (variant 1) rejected: requirement 'attribute syn_ramstyle="block_ram" ...' not met.
  Checking rule #3 for bram type $__ECP5_PDPW16KD (variant 1):
    Bram geometry: abits=9 dbits=36 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_PDPW16KD: awaste=0 dwaste=8 bwaste=4096 waste=4096 efficiency=88
    Rule #3 for bram type $__ECP5_PDPW16KD (variant 1) rejected: requirement 'max wports 0' not met.
  Checking rule #4 for bram type $__ECP5_DP16KD (variant 1):
    Bram geometry: abits=10 dbits=18 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=8 bwaste=8192 waste=8192 efficiency=88
    Rule #4 for bram type $__ECP5_DP16KD (variant 1) accepted.
    Mapping to bram type $__ECP5_DP16KD (variant 1):
      Shuffle bit order to accommodate enable buckets of size 9..
      Results of bit order shuffling: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 -1 -1 -1 -1 -1 -1 -1 -1
      Write port #0 is in clock domain \clock.
        Mapped to bram port A1.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Failed to map read port #1.
      Growing more read ports by duplicating bram cells.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Mapped to bram port B1.2.
      Updated properties: dups=2 waste=16384 efficiency=44
      Storing for later selection.
  Checking rule #4 for bram type $__ECP5_DP16KD (variant 2):
    Bram geometry: abits=11 dbits=9 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=8 bwaste=16384 waste=16384 efficiency=88
    Rule #4 for bram type $__ECP5_DP16KD (variant 2) accepted.
    Mapping to bram type $__ECP5_DP16KD (variant 2):
      Shuffle bit order to accommodate enable buckets of size 9..
      Results of bit order shuffling: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 -1 -1 -1 -1 -1 -1 -1 -1
      Write port #0 is in clock domain \clock.
        Mapped to bram port A1.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Failed to map read port #1.
      Growing more read ports by duplicating bram cells.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Mapped to bram port B1.2.
      Updated properties: dups=2 waste=32768 efficiency=44
      Storing for later selection.
  Checking rule #4 for bram type $__ECP5_DP16KD (variant 3):
    Bram geometry: abits=12 dbits=4 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule #4 for bram type $__ECP5_DP16KD (variant 3) accepted.
    Mapping to bram type $__ECP5_DP16KD (variant 3):
      Shuffle bit order to accommodate enable buckets of size 4..
      Results of bit order shuffling: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
      Write port #0 is in clock domain \clock.
        Mapped to bram port A1.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Failed to map read port #1.
      Growing more read ports by duplicating bram cells.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Mapped to bram port B1.2.
      Updated properties: dups=2 waste=0 efficiency=50
      Storing for later selection.
  Checking rule #4 for bram type $__ECP5_DP16KD (variant 4):
    Bram geometry: abits=13 dbits=2 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule #4 for bram type $__ECP5_DP16KD (variant 4) accepted.
    Mapping to bram type $__ECP5_DP16KD (variant 4):
      Shuffle bit order to accommodate enable buckets of size 2..
      Results of bit order shuffling: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
      Write port #0 is in clock domain \clock.
        Mapped to bram port A1.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Failed to map read port #1.
      Growing more read ports by duplicating bram cells.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Mapped to bram port B1.2.
      Updated properties: dups=2 waste=0 efficiency=50
      Storing for later selection.
  Checking rule #4 for bram type $__ECP5_DP16KD (variant 5):
    Bram geometry: abits=14 dbits=1 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule #4 for bram type $__ECP5_DP16KD (variant 5) accepted.
    Mapping to bram type $__ECP5_DP16KD (variant 5):
      Write port #0 is in clock domain \clock.
        Mapped to bram port A1.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Failed to map read port #1.
      Growing more read ports by duplicating bram cells.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Mapped to bram port B1.2.
      Updated properties: dups=2 waste=0 efficiency=50
      Storing for later selection.
  Checking rule #5 for bram type $__ECP5_DP16KD (variant 1):
    Bram geometry: abits=10 dbits=18 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=8 bwaste=8192 waste=8192 efficiency=88
    Rule for bram type $__ECP5_DP16KD (variant 1) rejected: requirement 'attribute syn_ramstyle="block_ram" ...' not met.
  Checking rule #5 for bram type $__ECP5_DP16KD (variant 2):
    Bram geometry: abits=11 dbits=9 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=8 bwaste=16384 waste=16384 efficiency=88
    Rule for bram type $__ECP5_DP16KD (variant 2) rejected: requirement 'attribute syn_ramstyle="block_ram" ...' not met.
  Checking rule #5 for bram type $__ECP5_DP16KD (variant 3):
    Bram geometry: abits=12 dbits=4 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule for bram type $__ECP5_DP16KD (variant 3) rejected: requirement 'attribute syn_ramstyle="block_ram" ...' not met.
  Checking rule #5 for bram type $__ECP5_DP16KD (variant 4):
    Bram geometry: abits=13 dbits=2 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule for bram type $__ECP5_DP16KD (variant 4) rejected: requirement 'attribute syn_ramstyle="block_ram" ...' not met.
  Checking rule #5 for bram type $__ECP5_DP16KD (variant 5):
    Bram geometry: abits=14 dbits=1 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule for bram type $__ECP5_DP16KD (variant 5) rejected: requirement 'attribute syn_ramstyle="block_ram" ...' not met.
  Checking rule #6 for bram type $__ECP5_DP16KD (variant 1):
    Bram geometry: abits=10 dbits=18 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=8 bwaste=8192 waste=8192 efficiency=88
    Rule #6 for bram type $__ECP5_DP16KD (variant 1) rejected: requirement 'max wports 0' not met.
  Checking rule #6 for bram type $__ECP5_DP16KD (variant 2):
    Bram geometry: abits=11 dbits=9 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=8 bwaste=16384 waste=16384 efficiency=88
    Rule #6 for bram type $__ECP5_DP16KD (variant 2) rejected: requirement 'max wports 0' not met.
  Checking rule #6 for bram type $__ECP5_DP16KD (variant 3):
    Bram geometry: abits=12 dbits=4 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule #6 for bram type $__ECP5_DP16KD (variant 3) rejected: requirement 'max wports 0' not met.
  Checking rule #6 for bram type $__ECP5_DP16KD (variant 4):
    Bram geometry: abits=13 dbits=2 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule #6 for bram type $__ECP5_DP16KD (variant 4) rejected: requirement 'max wports 0' not met.
  Checking rule #6 for bram type $__ECP5_DP16KD (variant 5):
    Bram geometry: abits=14 dbits=1 wports=0 rports=0
    Estimated number of duplicates for more read ports: dups=1
    Metrics for $__ECP5_DP16KD: awaste=0 dwaste=0 bwaste=0 waste=0 efficiency=100
    Rule #6 for bram type $__ECP5_DP16KD (variant 5) rejected: requirement 'max wports 0' not met.
  Selecting best of 6 rules:
    Efficiency for rule 4.5: efficiency=50, cells=128, acells=1
    Efficiency for rule 4.4: efficiency=50, cells=128, acells=2
    Efficiency for rule 4.3: efficiency=50, cells=128, acells=4
    Efficiency for rule 4.2: efficiency=44, cells=128, acells=8
    Efficiency for rule 4.1: efficiency=44, cells=128, acells=16
    Efficiency for rule 1.1: efficiency=44, cells=128, acells=32
    Selected rule 4.5 with efficiency 50.
    Mapping to bram type $__ECP5_DP16KD (variant 5):
      Write port #0 is in clock domain \clock.
        Mapped to bram port A1.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Failed to map read port #1.
      Growing more read ports by duplicating bram cells.
      Read port #0 is in clock domain \clock.
        Mapped to bram port B1.1.
      Read port #1 is in clock domain \clock.
        Mapped to bram port B1.2.
      Creating $__ECP5_DP16KD cell at grid position <0 0 0>: mem.0.0.0
      Creating $__ECP5_DP16KD cell at grid position <0 0 1>: mem.0.0.1
      Creating $__ECP5_DP16KD cell at grid position <1 0 0>: mem.1.0.0
      Creating $__ECP5_DP16KD cell at grid position <1 0 1>: mem.1.0.1
      Creating $__ECP5_DP16KD cell at grid position <2 0 0>: mem.2.0.0
      Creating $__ECP5_DP16KD cell at grid position <2 0 1>: mem.2.0.1
      Creating $__ECP5_DP16KD cell at grid position <3 0 0>: mem.3.0.0
      Creating $__ECP5_DP16KD cell at grid position <3 0 1>: mem.3.0.1
      Creating $__ECP5_DP16KD cell at grid position <4 0 0>: mem.4.0.0
      Creating $__ECP5_DP16KD cell at grid position <4 0 1>: mem.4.0.1
      Creating $__ECP5_DP16KD cell at grid position <5 0 0>: mem.5.0.0
      Creating $__ECP5_DP16KD cell at grid position <5 0 1>: mem.5.0.1
      Creating $__ECP5_DP16KD cell at grid position <6 0 0>: mem.6.0.0
      Creating $__ECP5_DP16KD cell at grid position <6 0 1>: mem.6.0.1
      Creating $__ECP5_DP16KD cell at grid position <7 0 0>: mem.7.0.0
      Creating $__ECP5_DP16KD cell at grid position <7 0 1>: mem.7.0.1
      Creating $__ECP5_DP16KD cell at grid position <8 0 0>: mem.8.0.0
      Creating $__ECP5_DP16KD cell at grid position <8 0 1>: mem.8.0.1
      Creating $__ECP5_DP16KD cell at grid position <9 0 0>: mem.9.0.0
      Creating $__ECP5_DP16KD cell at grid position <9 0 1>: mem.9.0.1
      Creating $__ECP5_DP16KD cell at grid position <10 0 0>: mem.10.0.0
      Creating $__ECP5_DP16KD cell at grid position <10 0 1>: mem.10.0.1
      Creating $__ECP5_DP16KD cell at grid position <11 0 0>: mem.11.0.0
      Creating $__ECP5_DP16KD cell at grid position <11 0 1>: mem.11.0.1
      Creating $__ECP5_DP16KD cell at grid position <12 0 0>: mem.12.0.0
      Creating $__ECP5_DP16KD cell at grid position <12 0 1>: mem.12.0.1
      Creating $__ECP5_DP16KD cell at grid position <13 0 0>: mem.13.0.0
      Creating $__ECP5_DP16KD cell at grid position <13 0 1>: mem.13.0.1
      Creating $__ECP5_DP16KD cell at grid position <14 0 0>: mem.14.0.0
      Creating $__ECP5_DP16KD cell at grid position <14 0 1>: mem.14.0.1
      Creating $__ECP5_DP16KD cell at grid position <15 0 0>: mem.15.0.0
      Creating $__ECP5_DP16KD cell at grid position <15 0 1>: mem.15.0.1
      Creating $__ECP5_DP16KD cell at grid position <16 0 0>: mem.16.0.0
      Creating $__ECP5_DP16KD cell at grid position <16 0 1>: mem.16.0.1
      Creating $__ECP5_DP16KD cell at grid position <17 0 0>: mem.17.0.0
      Creating $__ECP5_DP16KD cell at grid position <17 0 1>: mem.17.0.1
      Creating $__ECP5_DP16KD cell at grid position <18 0 0>: mem.18.0.0
      Creating $__ECP5_DP16KD cell at grid position <18 0 1>: mem.18.0.1
      Creating $__ECP5_DP16KD cell at grid position <19 0 0>: mem.19.0.0
      Creating $__ECP5_DP16KD cell at grid position <19 0 1>: mem.19.0.1
      Creating $__ECP5_DP16KD cell at grid position <20 0 0>: mem.20.0.0
      Creating $__ECP5_DP16KD cell at grid position <20 0 1>: mem.20.0.1
      Creating $__ECP5_DP16KD cell at grid position <21 0 0>: mem.21.0.0
      Creating $__ECP5_DP16KD cell at grid position <21 0 1>: mem.21.0.1
      Creating $__ECP5_DP16KD cell at grid position <22 0 0>: mem.22.0.0
      Creating $__ECP5_DP16KD cell at grid position <22 0 1>: mem.22.0.1
      Creating $__ECP5_DP16KD cell at grid position <23 0 0>: mem.23.0.0
      Creating $__ECP5_DP16KD cell at grid position <23 0 1>: mem.23.0.1
      Creating $__ECP5_DP16KD cell at grid position <24 0 0>: mem.24.0.0
      Creating $__ECP5_DP16KD cell at grid position <24 0 1>: mem.24.0.1
      Creating $__ECP5_DP16KD cell at grid position <25 0 0>: mem.25.0.0
      Creating $__ECP5_DP16KD cell at grid position <25 0 1>: mem.25.0.1
      Creating $__ECP5_DP16KD cell at grid position <26 0 0>: mem.26.0.0
      Creating $__ECP5_DP16KD cell at grid position <26 0 1>: mem.26.0.1
      Creating $__ECP5_DP16KD cell at grid position <27 0 0>: mem.27.0.0
      Creating $__ECP5_DP16KD cell at grid position <27 0 1>: mem.27.0.1
      Creating $__ECP5_DP16KD cell at grid position <28 0 0>: mem.28.0.0
      Creating $__ECP5_DP16KD cell at grid position <28 0 1>: mem.28.0.1
      Creating $__ECP5_DP16KD cell at grid position <29 0 0>: mem.29.0.0
      Creating $__ECP5_DP16KD cell at grid position <29 0 1>: mem.29.0.1
      Creating $__ECP5_DP16KD cell at grid position <30 0 0>: mem.30.0.0
      Creating $__ECP5_DP16KD cell at grid position <30 0 1>: mem.30.0.1
      Creating $__ECP5_DP16KD cell at grid position <31 0 0>: mem.31.0.0
      Creating $__ECP5_DP16KD cell at grid position <31 0 1>: mem.31.0.1
      Creating $__ECP5_DP16KD cell at grid position <32 0 0>: mem.32.0.0
      Creating $__ECP5_DP16KD cell at grid position <32 0 1>: mem.32.0.1
      Creating $__ECP5_DP16KD cell at grid position <33 0 0>: mem.33.0.0
      Creating $__ECP5_DP16KD cell at grid position <33 0 1>: mem.33.0.1
      Creating $__ECP5_DP16KD cell at grid position <34 0 0>: mem.34.0.0
      Creating $__ECP5_DP16KD cell at grid position <34 0 1>: mem.34.0.1
      Creating $__ECP5_DP16KD cell at grid position <35 0 0>: mem.35.0.0
      Creating $__ECP5_DP16KD cell at grid position <35 0 1>: mem.35.0.1
      Creating $__ECP5_DP16KD cell at grid position <36 0 0>: mem.36.0.0
      Creating $__ECP5_DP16KD cell at grid position <36 0 1>: mem.36.0.1
      Creating $__ECP5_DP16KD cell at grid position <37 0 0>: mem.37.0.0
      Creating $__ECP5_DP16KD cell at grid position <37 0 1>: mem.37.0.1
      Creating $__ECP5_DP16KD cell at grid position <38 0 0>: mem.38.0.0
      Creating $__ECP5_DP16KD cell at grid position <38 0 1>: mem.38.0.1
      Creating $__ECP5_DP16KD cell at grid position <39 0 0>: mem.39.0.0
      Creating $__ECP5_DP16KD cell at grid position <39 0 1>: mem.39.0.1
      Creating $__ECP5_DP16KD cell at grid position <40 0 0>: mem.40.0.0
      Creating $__ECP5_DP16KD cell at grid position <40 0 1>: mem.40.0.1
      Creating $__ECP5_DP16KD cell at grid position <41 0 0>: mem.41.0.0
      Creating $__ECP5_DP16KD cell at grid position <41 0 1>: mem.41.0.1
      Creating $__ECP5_DP16KD cell at grid position <42 0 0>: mem.42.0.0
      Creating $__ECP5_DP16KD cell at grid position <42 0 1>: mem.42.0.1
      Creating $__ECP5_DP16KD cell at grid position <43 0 0>: mem.43.0.0
      Creating $__ECP5_DP16KD cell at grid position <43 0 1>: mem.43.0.1
      Creating $__ECP5_DP16KD cell at grid position <44 0 0>: mem.44.0.0
      Creating $__ECP5_DP16KD cell at grid position <44 0 1>: mem.44.0.1
      Creating $__ECP5_DP16KD cell at grid position <45 0 0>: mem.45.0.0
      Creating $__ECP5_DP16KD cell at grid position <45 0 1>: mem.45.0.1
      Creating $__ECP5_DP16KD cell at grid position <46 0 0>: mem.46.0.0
      Creating $__ECP5_DP16KD cell at grid position <46 0 1>: mem.46.0.1
      Creating $__ECP5_DP16KD cell at grid position <47 0 0>: mem.47.0.0
      Creating $__ECP5_DP16KD cell at grid position <47 0 1>: mem.47.0.1
      Creating $__ECP5_DP16KD cell at grid position <48 0 0>: mem.48.0.0
      Creating $__ECP5_DP16KD cell at grid position <48 0 1>: mem.48.0.1
      Creating $__ECP5_DP16KD cell at grid position <49 0 0>: mem.49.0.0
      Creating $__ECP5_DP16KD cell at grid position <49 0 1>: mem.49.0.1
      Creating $__ECP5_DP16KD cell at grid position <50 0 0>: mem.50.0.0
      Creating $__ECP5_DP16KD cell at grid position <50 0 1>: mem.50.0.1
      Creating $__ECP5_DP16KD cell at grid position <51 0 0>: mem.51.0.0
      Creating $__ECP5_DP16KD cell at grid position <51 0 1>: mem.51.0.1
      Creating $__ECP5_DP16KD cell at grid position <52 0 0>: mem.52.0.0
      Creating $__ECP5_DP16KD cell at grid position <52 0 1>: mem.52.0.1
      Creating $__ECP5_DP16KD cell at grid position <53 0 0>: mem.53.0.0
      Creating $__ECP5_DP16KD cell at grid position <53 0 1>: mem.53.0.1
      Creating $__ECP5_DP16KD cell at grid position <54 0 0>: mem.54.0.0
      Creating $__ECP5_DP16KD cell at grid position <54 0 1>: mem.54.0.1
      Creating $__ECP5_DP16KD cell at grid position <55 0 0>: mem.55.0.0
      Creating $__ECP5_DP16KD cell at grid position <55 0 1>: mem.55.0.1
      Creating $__ECP5_DP16KD cell at grid position <56 0 0>: mem.56.0.0
      Creating $__ECP5_DP16KD cell at grid position <56 0 1>: mem.56.0.1
      Creating $__ECP5_DP16KD cell at grid position <57 0 0>: mem.57.0.0
      Creating $__ECP5_DP16KD cell at grid position <57 0 1>: mem.57.0.1
      Creating $__ECP5_DP16KD cell at grid position <58 0 0>: mem.58.0.0
      Creating $__ECP5_DP16KD cell at grid position <58 0 1>: mem.58.0.1
      Creating $__ECP5_DP16KD cell at grid position <59 0 0>: mem.59.0.0
      Creating $__ECP5_DP16KD cell at grid position <59 0 1>: mem.59.0.1
      Creating $__ECP5_DP16KD cell at grid position <60 0 0>: mem.60.0.0
      Creating $__ECP5_DP16KD cell at grid position <60 0 1>: mem.60.0.1
      Creating $__ECP5_DP16KD cell at grid position <61 0 0>: mem.61.0.0
      Creating $__ECP5_DP16KD cell at grid position <61 0 1>: mem.61.0.1
      Creating $__ECP5_DP16KD cell at grid position <62 0 0>: mem.62.0.0
      Creating $__ECP5_DP16KD cell at grid position <62 0 1>: mem.62.0.1
      Creating $__ECP5_DP16KD cell at grid position <63 0 0>: mem.63.0.0
      Creating $__ECP5_DP16KD cell at grid position <63 0 1>: mem.63.0.1

2.27. Executing TECHMAP pass (map to technology primitives).

2.27.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/brams_map.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/brams_map.v' to AST representation.
Generating RTLIL representation for module `\$__ECP5_DP16KD'.
Generating RTLIL representation for module `\$__ECP5_PDPW16KD'.
Successfully finished Verilog frontend.

2.27.2. Continuing TECHMAP pass.
Using template $paramod$cb0ea14e7b69acbcdb2cc6ee683870e98ae8a109\$__ECP5_DP16KD for cells of type $__ECP5_DP16KD.
No more expansions possible.
<suppressed ~153 debug messages>

2.28. Executing MEMORY_BRAM pass (mapping $mem cells to block memories).

2.29. Executing TECHMAP pass (map to technology primitives).

2.29.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/lutrams_map.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/lutrams_map.v' to AST representation.
Generating RTLIL representation for module `\$__TRELLIS_DPR16X4'.
Successfully finished Verilog frontend.

2.29.2. Continuing TECHMAP pass.
No more expansions possible.
<suppressed ~3 debug messages>

2.30. Executing OPT pass (performing simple optimizations).

2.30.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.
<suppressed ~129 debug messages>

2.30.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.30.3. Executing OPT_DFF pass (perform DFF optimizations).

2.30.4. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..
Removed 0 unused cells and 1281 unused wires.
<suppressed ~1 debug messages>

2.30.5. Finished fast OPT passes.

2.31. Executing MEMORY_MAP pass (converting memories to logic and flip-flops).

2.32. Executing OPT pass (performing simple optimizations).

2.32.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.32.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.32.3. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \DualPortRAM..
  Creating internal representation of mux trees.
  No muxes found in this module.
Removed 0 multiplexer ports.

2.32.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
  Optimizing cells in module \DualPortRAM.
Performed a total of 0 changes.

2.32.5. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.32.6. Executing OPT_DFF pass (perform DFF optimizations).

2.32.7. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.32.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.32.9. Finished OPT passes. (There is nothing left to do.)

2.33. Executing TECHMAP pass (map to technology primitives).

2.33.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/techmap.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/techmap.v' to AST representation.
Generating RTLIL representation for module `\_90_simplemap_bool_ops'.
Generating RTLIL representation for module `\_90_simplemap_reduce_ops'.
Generating RTLIL representation for module `\_90_simplemap_logic_ops'.
Generating RTLIL representation for module `\_90_simplemap_compare_ops'.
Generating RTLIL representation for module `\_90_simplemap_various'.
Generating RTLIL representation for module `\_90_simplemap_registers'.
Generating RTLIL representation for module `\_90_shift_ops_shr_shl_sshl_sshr'.
Generating RTLIL representation for module `\_90_shift_shiftx'.
Generating RTLIL representation for module `\_90_fa'.
Generating RTLIL representation for module `\_90_lcu'.
Generating RTLIL representation for module `\_90_alu'.
Generating RTLIL representation for module `\_90_macc'.
Generating RTLIL representation for module `\_90_alumacc'.
Generating RTLIL representation for module `\$__div_mod_u'.
Generating RTLIL representation for module `\$__div_mod_trunc'.
Generating RTLIL representation for module `\_90_div'.
Generating RTLIL representation for module `\_90_mod'.
Generating RTLIL representation for module `\$__div_mod_floor'.
Generating RTLIL representation for module `\_90_divfloor'.
Generating RTLIL representation for module `\_90_modfloor'.
Generating RTLIL representation for module `\_90_pow'.
Generating RTLIL representation for module `\_90_pmux'.
Generating RTLIL representation for module `\_90_lut'.
Successfully finished Verilog frontend.

2.33.2. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/arith_map.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/arith_map.v' to AST representation.
Generating RTLIL representation for module `\_80_ecp5_alu'.
Successfully finished Verilog frontend.

2.33.3. Continuing TECHMAP pass.
No more expansions possible.
<suppressed ~67 debug messages>

2.34. Executing OPT pass (performing simple optimizations).

2.34.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.34.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\DualPortRAM'.
Removed a total of 0 cells.

2.34.3. Executing OPT_DFF pass (perform DFF optimizations).

2.34.4. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.34.5. Finished fast OPT passes.

2.35. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.36. Executing DFFLEGALIZE pass (convert FFs to types supported by the target).

2.37. Executing TECHMAP pass (map to technology primitives).

2.37.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/cells_map.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/cells_map.v' to AST representation.
Generating RTLIL representation for module `\$_DFF_N_'.
Generating RTLIL representation for module `\$_DFF_P_'.
Generating RTLIL representation for module `\$_DFFE_NN_'.
Generating RTLIL representation for module `\$_DFFE_PN_'.
Generating RTLIL representation for module `\$_DFFE_NP_'.
Generating RTLIL representation for module `\$_DFFE_PP_'.
Generating RTLIL representation for module `\$_DFF_NP0_'.
Generating RTLIL representation for module `\$_DFF_NP1_'.
Generating RTLIL representation for module `\$_DFF_PP0_'.
Generating RTLIL representation for module `\$_DFF_PP1_'.
Generating RTLIL representation for module `\$_SDFF_NP0_'.
Generating RTLIL representation for module `\$_SDFF_NP1_'.
Generating RTLIL representation for module `\$_SDFF_PP0_'.
Generating RTLIL representation for module `\$_SDFF_PP1_'.
Generating RTLIL representation for module `\$_DFFE_NP0P_'.
Generating RTLIL representation for module `\$_DFFE_NP1P_'.
Generating RTLIL representation for module `\$_DFFE_PP0P_'.
Generating RTLIL representation for module `\$_DFFE_PP1P_'.
Generating RTLIL representation for module `\$_DFFE_NP0N_'.
Generating RTLIL representation for module `\$_DFFE_NP1N_'.
Generating RTLIL representation for module `\$_DFFE_PP0N_'.
Generating RTLIL representation for module `\$_DFFE_PP1N_'.
Generating RTLIL representation for module `\$_SDFFE_NP0P_'.
Generating RTLIL representation for module `\$_SDFFE_NP1P_'.
Generating RTLIL representation for module `\$_SDFFE_PP0P_'.
Generating RTLIL representation for module `\$_SDFFE_PP1P_'.
Generating RTLIL representation for module `\$_SDFFE_NP0N_'.
Generating RTLIL representation for module `\$_SDFFE_NP1N_'.
Generating RTLIL representation for module `\$_SDFFE_PP0N_'.
Generating RTLIL representation for module `\$_SDFFE_PP1N_'.
Generating RTLIL representation for module `\FD1P3AX'.
Generating RTLIL representation for module `\FD1P3AY'.
Generating RTLIL representation for module `\FD1P3BX'.
Generating RTLIL representation for module `\FD1P3DX'.
Generating RTLIL representation for module `\FD1P3IX'.
Generating RTLIL representation for module `\FD1P3JX'.
Generating RTLIL representation for module `\FD1S3AX'.
Generating RTLIL representation for module `\FD1S3AY'.
Generating RTLIL representation for module `\FD1S3BX'.
Generating RTLIL representation for module `\FD1S3DX'.
Generating RTLIL representation for module `\FD1S3IX'.
Generating RTLIL representation for module `\FD1S3JX'.
Generating RTLIL representation for module `\IFS1P3BX'.
Generating RTLIL representation for module `\IFS1P3DX'.
Generating RTLIL representation for module `\IFS1P3IX'.
Generating RTLIL representation for module `\IFS1P3JX'.
Generating RTLIL representation for module `\OFS1P3BX'.
Generating RTLIL representation for module `\OFS1P3DX'.
Generating RTLIL representation for module `\OFS1P3IX'.
Generating RTLIL representation for module `\OFS1P3JX'.
Generating RTLIL representation for module `\IB'.
Generating RTLIL representation for module `\IBPU'.
Generating RTLIL representation for module `\IBPD'.
Generating RTLIL representation for module `\OB'.
Generating RTLIL representation for module `\OBZ'.
Generating RTLIL representation for module `\OBZPU'.
Generating RTLIL representation for module `\OBZPD'.
Generating RTLIL representation for module `\OBCO'.
Generating RTLIL representation for module `\BB'.
Generating RTLIL representation for module `\BBPU'.
Generating RTLIL representation for module `\BBPD'.
Generating RTLIL representation for module `\ILVDS'.
Generating RTLIL representation for module `\OLVDS'.
Successfully finished Verilog frontend.

2.37.2. Continuing TECHMAP pass.
No more expansions possible.
<suppressed ~65 debug messages>

2.38. Executing OPT_EXPR pass (perform const folding).
Optimizing module DualPortRAM.

2.39. Executing SIMPLEMAP pass (map simple cells to gate primitives).

2.40. Executing ECP5_GSR pass (implement FF init values).
Handling GSR in DualPortRAM.

2.41. Executing ATTRMVCP pass (move or copy attributes).

2.42. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \DualPortRAM..

2.43. Executing TECHMAP pass (map to technology primitives).

2.43.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/latches_map.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/latches_map.v' to AST representation.
Generating RTLIL representation for module `\$_DLATCH_N_'.
Generating RTLIL representation for module `\$_DLATCH_P_'.
Successfully finished Verilog frontend.

2.43.2. Continuing TECHMAP pass.
No more expansions possible.
<suppressed ~4 debug messages>

2.44. Executing ABC pass (technology mapping using ABC).

2.44.1. Extracting gate netlist of module `\DualPortRAM' to `<abc-temp-dir>/input.blif'..
Extracted 0 gates and 0 wires to a netlist network with 0 inputs and 0 outputs.
Don't call ABC as there is nothing to map.
Removing temp directory.

2.45. Executing TECHMAP pass (map to technology primitives).

2.45.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ecp5/cells_map.v
Parsing Verilog input from `/usr/local/bin/../share/yosys/ecp5/cells_map.v' to AST representation.
Generating RTLIL representation for module `\$_DFF_N_'.
Generating RTLIL representation for module `\$_DFF_P_'.
Generating RTLIL representation for module `\$_DFFE_NN_'.
Generating RTLIL representation for module `\$_DFFE_PN_'.
Generating RTLIL representation for module `\$_DFFE_NP_'.
Generating RTLIL representation for module `\$_DFFE_PP_'.
Generating RTLIL representation for module `\$_DFF_NP0_'.
Generating RTLIL representation for module `\$_DFF_NP1_'.
Generating RTLIL representation for module `\$_DFF_PP0_'.
Generating RTLIL representation for module `\$_DFF_PP1_'.
Generating RTLIL representation for module `\$_SDFF_NP0_'.
Generating RTLIL representation for module `\$_SDFF_NP1_'.
Generating RTLIL representation for module `\$_SDFF_PP0_'.
Generating RTLIL representation for module `\$_SDFF_PP1_'.
Generating RTLIL representation for module `\$_DFFE_NP0P_'.
Generating RTLIL representation for module `\$_DFFE_NP1P_'.
Generating RTLIL representation for module `\$_DFFE_PP0P_'.
Generating RTLIL representation for module `\$_DFFE_PP1P_'.
Generating RTLIL representation for module `\$_DFFE_NP0N_'.
Generating RTLIL representation for module `\$_DFFE_NP1N_'.
Generating RTLIL representation for module `\$_DFFE_PP0N_'.
Generating RTLIL representation for module `\$_DFFE_PP1N_'.
Generating RTLIL representation for module `\$_SDFFE_NP0P_'.
Generating RTLIL representation for module `\$_SDFFE_NP1P_'.
Generating RTLIL representation for module `\$_SDFFE_PP0P_'.
Generating RTLIL representation for module `\$_SDFFE_PP1P_'.
Generating RTLIL representation for module `\$_SDFFE_NP0N_'.
Generating RTLIL representation for module `\$_SDFFE_NP1N_'.
Generating RTLIL representation for module `\$_SDFFE_PP0N_'.
Generating RTLIL representation for module `\$_SDFFE_PP1N_'.
Generating RTLIL representation for module `\FD1P3AX'.
Generating RTLIL representation for module `\FD1P3AY'.
Generating RTLIL representation for module `\FD1P3BX'.
Generating RTLIL representation for module `\FD1P3DX'.
Generating RTLIL representation for module `\FD1P3IX'.
Generating RTLIL representation for module `\FD1P3JX'.
Generating RTLIL representation for module `\FD1S3AX'.
Generating RTLIL representation for module `\FD1S3AY'.
Generating RTLIL representation for module `\FD1S3BX'.
Generating RTLIL representation for module `\FD1S3DX'.
Generating RTLIL representation for module `\FD1S3IX'.
Generating RTLIL representation for module `\FD1S3JX'.
Generating RTLIL representation for module `\IFS1P3BX'.
Generating RTLIL representation for module `\IFS1P3DX'.
Generating RTLIL representation for module `\IFS1P3IX'.
Generating RTLIL representation for module `\IFS1P3JX'.
Generating RTLIL representation for module `\OFS1P3BX'.
Generating RTLIL representation for module `\OFS1P3DX'.
Generating RTLIL representation for module `\OFS1P3IX'.
Generating RTLIL representation for module `\OFS1P3JX'.
Generating RTLIL representation for module `\IB'.
Generating RTLIL representation for module `\IBPU'.
Generating RTLIL representation for module `\IBPD'.
Generating RTLIL representation for module `\OB'.
Generating RTLIL representation for module `\OBZ'.
Generating RTLIL representation for module `\OBZPU'.
Generating RTLIL representation for module `\OBZPD'.
Generating RTLIL representation for module `\OBCO'.
Generating RTLIL representation for module `\BB'.
Generating RTLIL representation for module `\BBPU'.
Generating RTLIL representation for module `\BBPD'.
Generating RTLIL representation for module `\ILVDS'.
Generating RTLIL representation for module `\OLVDS'.
Generating RTLIL representation for module `\$lut'.
Successfully finished Verilog frontend.

2.45.2. Continuing TECHMAP pass.
No more expansions possible.
<suppressed ~66 debug messages>

2.46. Executing OPT_LUT_INS pass (discard unused LUT inputs).
Optimizing LUTs in DualPortRAM.

2.47. Executing AUTONAME pass.

2.48. Executing HIERARCHY pass (managing design hierarchy).

2.48.1. Analyzing design hierarchy..
Top module:  \DualPortRAM

2.48.2. Analyzing design hierarchy..
Top module:  \DualPortRAM
Removed 0 unused modules.

2.49. Printing statistics.

=== DualPortRAM ===

   Number of wires:                 14
   Number of wire bits:            433
   Number of public wires:          14
   Number of public wire bits:     433
   Number of memories:               0
   Number of memory bits:            0
   Number of processes:              0
   Number of cells:                128
     DP16KD                        128

2.50. Executing CHECK pass (checking for obvious problems).
checking module DualPortRAM..
found and reported 0 problems.

2.51. Executing JSON backend.

End of script. Logfile hash: c6aa19b95c, CPU: user 1.74s system 0.13s, MEM: 265.09 MB peak
Yosys 0.9+3675 (git sha1 UNKNOWN, clang 7.0.1-8+deb10u2 -fPIC -Os)
Time spent: 43% 15x read_verilog (0 sec), 17% 8x techmap (0 sec), ...

Contributor Checklist

  • Did you add Scaladoc to every public function/method?
  • Did you update the FIRRTL spec to include every new feature/behavior?
  • Did you add at least one test demonstrating the PR?
  • Did you delete any extraneous printlns/debugging code?
  • Did you specify the type of improvement?
  • Did you state the API impact?
  • Did you specify the code generation impact?
  • Did you request a desired merge strategy?
  • Did you add text to be included in the Release Notes for this change?

Type of Improvement

  • new feature/API

API Impact

No impact on previous methods or API, adds new annotation.

Backend Code Generation Impact

This annotation adds readmem[hb] statements to generated Verilog.

Desired Merge Strategy

  • Squash: The PR will be squashed and merged

Release Notes

(addition) Added MemoryFileInlineAnnotation to allow loading hex and bin memory files inline in Verilog emitter(#2107)

Reviewer Checklist (only modified by reviewer)

  • Did you add the appropriate labels?
  • Did you mark the proper milestone (1.2.x, 1.3.0, 1.4.0) ?
  • Did you review?
  • Did you check whether all relevant Contributor checkboxes have been checked?
  • Did you mark as Please Merge?

@CLAassistant
Copy link

CLAassistant commented Mar 8, 2021

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

@ekiwi ekiwi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great @carlosedp !
Extending the MemoryInitValue and MemoryInitAnnotation is definitely the way to go.

All I am asking you to do is move the code that generates the actual Verilog into the Verilog emitter (see my comments below). This is in order to keep the other files more generic so that they could be reuse by a (hypothetical) VHDL or yosys RTLIR emitter.

src/main/scala/firrtl/EmissionOption.scala Outdated Show resolved Hide resolved
@carlosedp
Copy link
Contributor Author

@ekiwi Thanks for the great feedback, makes total sense having code related to Verilog in one place.
I just pushed changes based on this.

@ekiwi
Copy link
Contributor

ekiwi commented Mar 9, 2021

I just pushed changes based on this.

Looks good (the reason CI is failing is that you need to run sbt scalafmtAll to reformat your changes).

For testing, I would suggest that you look at the following file and try to add some tests for your new Annotation to it: https://github.com/chipsalliance/firrtl/blob/master/src/test/scala/firrtlTests/MemoryInitSpec.scala

@carlosedp
Copy link
Contributor Author

Thanks Kevin, I've fixed the formatting and also added some tests to the new annotation.

Copy link
Member

@seldridge seldridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a great improvement.

I have a minor request that the error is promoted to a construction-time error.

Comment on lines 853 to 855
if (filename.trim().isEmpty()) {
throw EmitterException(s"empty filename not allowed in MemoryFileInlineAnnotation")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This very late runtime check (running during Verilog emission) should be promoted to a construction-time requirement on the annotation. That way, you'll get an error as soon as you fail the requirement specified here (like after Chisel elaboration) as opposed to having to wait for the full FIRRTL compile.

(Tangentially, other code here is doing late checks. No reason to follow that pattern here if the error can be produced earlier.)

Comment on lines 181 to 183
assertThrows[EmitterException] {
compile(Seq(MemoryFileInlineAnnotation(mRef, filename = "")))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception type will change here with the change to a require that runs during object creation. (No need to then do compile after that fix.)

@ekiwi ekiwi added this to the 1.4.x milestone Mar 9, 2021
@ekiwi
Copy link
Contributor

ekiwi commented Mar 9, 2021

Once @seldridge's suggestion have been addressed, I would be happy to get this in.

@carlosedp
Copy link
Contributor Author

Addressed @seldridge comments on latest push. The validation is done on MemoryFileInlineAnnotation class instead of the VerilogEmitter.
Also fixed a typo on one of the tests.

This PR adds a new annotation allowing inline loading for memory files
in Verilog code.
@carlosedp
Copy link
Contributor Author

Just pushed as suggested! Thanks for pointing it out :)

Copy link
Contributor

@ekiwi ekiwi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This looks great. 🚢

@ekiwi ekiwi added the Please Merge Accepted PRs that are ready to be merged. Useful when waiting on CI. label Mar 9, 2021
Copy link
Contributor

@jackkoenig jackkoenig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, thanks @carlosedp for your high quality contribution!

@mergify mergify bot merged commit efdefde into chipsalliance:master Mar 9, 2021
mergify bot pushed a commit that referenced this pull request Mar 9, 2021
This PR adds a new annotation allowing inline loading for memory files
in Verilog code.

(cherry picked from commit efdefde)
@mergify mergify bot added the Backported This PR has been backported to marked stable branch label Mar 9, 2021
@carlosedp
Copy link
Contributor Author

Thanks for all the patience and guidance on this @ekiwi @seldridge @jackkoenig!
Looking forward to contribute more to the projects!

mergify bot added a commit that referenced this pull request Mar 9, 2021
This PR adds a new annotation allowing inline loading for memory files
in Verilog code.

(cherry picked from commit efdefde)

Co-authored-by: Carlos Eduardo <carlosedp@gmail.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Backported This PR has been backported to marked stable branch Please Merge Accepted PRs that are ready to be merged. Useful when waiting on CI.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants