f4pga / f4pga-arch-defs

FOSS architecture definitions of FPGA hardware useful for doing PnR device generation.
https://f4pga.org
ISC License
269 stars 112 forks source link

Make v2x support dpram32 generation #776

Open mithro opened 5 years ago

mithro commented 5 years ago

Need to generate the pb_type.xml and model.xml from the Verilog using v2x.

Input Verilog

Things wrong with this verilog;

/*
 * Dual Port (Async read, sync write) - 32 * 1-bit (LUT) RAM.
 *
 */
(* whitebox *)
module DPRAM32 (
  // Sync write port
  CLK, WE, WA, DI,
  // Async read port
  A, O
);
  // Memory data storage
  // --------------------------
  parameter [31:0] INIT_00 = 32'h0;
  reg [31:0] mem;
  initial mem <= INIT_00;

  // Async read port
  // --------------------------
  // Read Address (unclocked)
  input wire [4:0] A;
  // Data Output (unclocked)
  output wire O;

  assign O = mem[A];

  // Sync write port
  // --------------------------
  // Clock
  input wire CLK;
  // Write enable (clocked)
  input wire WE;
  // Write address (clocked)
  input wire [4:0] WA;
  // Data input (clocked)
  input wire DI;

  parameter IS_WCLK_INVERTED = 1'b0;
  wire clk = CLK ^ IS_WCLK_INVERTED;

  always @(posedge clk)
    if (WE) begin
      mem[WA] <= DI;
    end
endmodule

dpram32.model.xml

<models>
 <model name="DPRAM32">
  <input_ports>
   <port is_clock="1"   name="CLK"  />
   <port clock="CLK"    name="WE"  combinational_sink_ports="O" />
   <port clock="CLK"    name="DI"  combinational_sink_ports="O" />
   <port clock="CLK"    name="WA"  combinational_sink_ports="O" />

   <port                name="A"   combinational_sink_ports="O" />
  </input_ports>
  <output_ports>
   <port                name="O" />
  </output_ports>
 </model>
</models>

dpram32.pb_type.xml

<pb_type name="DPRAM32" num_pb="2">
  <blif_model>.subckt DPRAM32</blif_model>
  <clock  name="CLK" num_pins="1" />

  <!-- A1 - Read port -->
  <input  name="A"  num_pins="5" />
  <output name="O"  num_pins="1" />

  <delay_matrix type="max" in_port="A" out_port="O">
    0.068e-9
    0.068e-9
    0.068e-9
    0.068e-9
    0.068e-9
  </delay_matrix>

  <!-- B1 - Write Port -->
  <input  name="WA" num_pins="5" />
  <input  name="DI" num_pins="1" />
  <input  name="WE" num_pins="1" />

  <T_setup      value="10e-12" port="WA"    clock="CLK"  />
  <T_clock_to_Q   max="10e-12" port="WA"    clock="CLK"  />
  <delay_constant max="10e-12" in_port="WA" out_port="O" />

  <T_setup      value="10e-12" port="WE"    clock="CLK"  />
  <T_clock_to_Q   max="10e-12" port="WE"    clock="CLK"  />
  <delay_constant max="10e-12" in_port="WE" out_port="O" />

  <T_setup      value="10e-12" port="DI"    clock="CLK"  />
  <T_clock_to_Q   max="10e-12" port="DI"    clock="CLK"  />
  <delay_constant max="10e-12" in_port="DI" out_port="O" />
  <metadata>
    <meta name="fasm_params">
      INIT[31:0] = INIT_00
      INIT[63:32] = INIT_01
    </meta>
    <meta name="fasm_features">
      RAM
      SMALL
    </meta>
    <meta name="type">bel</meta>
    <meta name="subtype">memory</meta>
  </metadata>
</pb_type>
mithro commented 5 years ago

Currently the following model.xml is produced;

<models xmlns:xi="http://www.w3.org/2001/XInclude">
  <model name="DPRAM32">
    <input_ports>
      <port combinational_sink_ports="O" name="A"/>
      <port combinational_sink_ports="O" name="CLK"/>
      <port combinational_sink_ports="O" name="DI"/>
      <port combinational_sink_ports="O" name="WA"/>
      <port combinational_sink_ports="O" name="WE"/>
    </input_ports>
    <output_ports>
      <port name="O"/>
    </output_ports>
  </model>
</models>
mithro commented 5 years ago

Current issues on model.xml;

mithro commented 5 years ago

This seems pretty similar to https://github.com/SymbiFlow/symbiflow-arch-defs/issues/630

mithro commented 5 years ago

Yosys outputs the following;

yosys> prep -top DPRAM32 

2. Executing PREP pass.

2.1. Executing HIERARCHY pass (managing design hierarchy).

2.1.1. Analyzing design hierarchy..
Top module:  \DPRAM32

2.1.2. Analyzing design hierarchy..
Top module:  \DPRAM32
Removed 0 unused modules.

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

2.2.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.

2.2.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
Marked 1 switch rules as full_case in process $proc$dpram32.sim.v:41$3 in module DPRAM32.
Removed a total of 0 dead cases.

2.2.3. Executing PROC_INIT pass (extract init attributes).
Found init rule in `\DPRAM32.$proc$dpram32.sim.v:16$4'.
  Set init value: \mem = 0

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

2.2.5. Executing PROC_MUX pass (convert decision trees to multiplexers).
Creating decoders for process `\DPRAM32.$proc$dpram32.sim.v:16$4'.
     1/1: $1\mem[31:0]
Creating decoders for process `\DPRAM32.$proc$dpram32.sim.v:41$3'.
     1/32: $0\mem[31:0] [31]
     2/32: $0\mem[31:0] [30]
     3/32: $0\mem[31:0] [29]
     4/32: $0\mem[31:0] [28]
     5/32: $0\mem[31:0] [27]
     6/32: $0\mem[31:0] [26]
     7/32: $0\mem[31:0] [25]
     8/32: $0\mem[31:0] [24]
     9/32: $0\mem[31:0] [23]
    10/32: $0\mem[31:0] [22]
    11/32: $0\mem[31:0] [21]
    12/32: $0\mem[31:0] [20]
    13/32: $0\mem[31:0] [19]
    14/32: $0\mem[31:0] [18]
    15/32: $0\mem[31:0] [17]
    16/32: $0\mem[31:0] [16]
    17/32: $0\mem[31:0] [15]
    18/32: $0\mem[31:0] [14]
    19/32: $0\mem[31:0] [13]
    20/32: $0\mem[31:0] [12]
    21/32: $0\mem[31:0] [11]
    22/32: $0\mem[31:0] [10]
    23/32: $0\mem[31:0] [9]
    24/32: $0\mem[31:0] [8]
    25/32: $0\mem[31:0] [7]
    26/32: $0\mem[31:0] [6]
    27/32: $0\mem[31:0] [5]
    28/32: $0\mem[31:0] [4]
    29/32: $0\mem[31:0] [3]
    30/32: $0\mem[31:0] [2]
    31/32: $0\mem[31:0] [1]
    32/32: $0\mem[31:0] [0]

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

2.2.7. Executing PROC_DFF pass (convert process syncs to FFs).
Creating register for signal `\DPRAM32.\mem' using process `\DPRAM32.$proc$dpram32.sim.v:41$3'.
  created $dff cell `$procdff$629' with positive edge clock.

2.2.8. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Removing empty process `DPRAM32.$proc$dpram32.sim.v:16$4'.
Found and cleaned up 2 empty switches in `\DPRAM32.$proc$dpram32.sim.v:41$3'.
Removing empty process `DPRAM32.$proc$dpram32.sim.v:41$3'.
Cleaned up 2 empty switches.
mithro commented 5 years ago

I updated the Verilog to be as follows;

`default_nettype none

/*
 * Dual Port (Async read, sync write) - 32 * 1-bit (LUT) RAM.
 */
//(* whitebox *)
module DPRAM32 (
  // Sync write port
  CLK, WE, WA, DI,
  // Async read port
  A, O
);
  // Memory data storage
  // --------------------------
  localparam DATA_WIDTH = 1;  // 1-bit
  localparam ADDR_WIDTH = 5;  // 2**5 == 32 positions
  localparam DATA_WORDS = 2 ** ADDR_WIDTH;
  reg [DATA_WIDTH-1:0] mem [0:DATA_WORDS-1];

  // Memory init from parameter...
  localparam MEM_SIZE = DATA_WIDTH * DATA_WORDS;
  parameter [MEM_SIZE-1:0] INIT_00 = 1'bx;
  genvar i;
  generate
    for(i = 0; i < DATA_WORDS; i++) begin
      initial mem[i] = INIT_00[i*DATA_WIDTH +: DATA_WIDTH];
    end
  endgenerate

  // Async read port
  // --------------------------
  // Read Address (unclocked)
  input wire [ADDR_WIDTH-1:0] A;
  // Data Output (unclocked)
  output wire O;

  // Read port
  assign O = mem[A];

  // Sync write port
  // --------------------------
  // Clock
  input wire CLK;
  // Write enable (clocked)
  input wire WE;
  // Write address (clocked)
  input wire [ADDR_WIDTH-1:0] WA;
  // Data input (clocked)
  input wire DI;

  always @(posedge CLK) begin
    if (WE) begin
      mem[WA] <= DI;
    end
  end

endmodule

And now I get;

<models xmlns:xi="http://www.w3.org/2001/XInclude">
  <model name="DPRAM32">
    <input_ports>
      <port combinational_sink_ports="O" name="A"/>
      <port is_clock="1" name="CLK"/>
      <port name="DI"/>
      <port name="WA"/>
      <port name="WE"/>
    </input_ports>
    <output_ports>
      <port name="O"/>
    </output_ports>
  </model>
</models>