mirror of https://github.com/YosysHQ/yosys.git
ice40: Add ice40_braminit pass to allow initialization of BRAM from file
This adds a INIT_FILE attribute to the SB_RAM40_4K blocks that will initialize content from a hex file. Same behavior is imlemented in the simulation model and in a new pass for actual synthesis Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
parent
7a40294e93
commit
e71055cfe8
|
@ -1,5 +1,6 @@
|
|||
|
||||
OBJS += techlibs/ice40/synth_ice40.o
|
||||
OBJS += techlibs/ice40/ice40_braminit.o
|
||||
OBJS += techlibs/ice40/ice40_ffssr.o
|
||||
OBJS += techlibs/ice40/ice40_ffinit.o
|
||||
OBJS += techlibs/ice40/ice40_opt.o
|
||||
|
|
|
@ -326,6 +326,8 @@ module SB_RAM40_4K (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
`ifndef BLACKBOX
|
||||
wire [15:0] WMASK_I;
|
||||
wire [15:0] RMASK_I;
|
||||
|
@ -408,43 +410,46 @@ module SB_RAM40_4K (
|
|||
reg [15:0] memory [0:255];
|
||||
|
||||
initial begin
|
||||
for (i=0; i<16; i=i+1) begin
|
||||
if (INIT_FILE != "")
|
||||
$readmemh(INIT_FILE, memory);
|
||||
else
|
||||
for (i=0; i<16; i=i+1) begin
|
||||
`ifdef YOSYS
|
||||
memory[ 0*16 + i] <= INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] <= INIT_1[16*i +: 16];
|
||||
memory[ 2*16 + i] <= INIT_2[16*i +: 16];
|
||||
memory[ 3*16 + i] <= INIT_3[16*i +: 16];
|
||||
memory[ 4*16 + i] <= INIT_4[16*i +: 16];
|
||||
memory[ 5*16 + i] <= INIT_5[16*i +: 16];
|
||||
memory[ 6*16 + i] <= INIT_6[16*i +: 16];
|
||||
memory[ 7*16 + i] <= INIT_7[16*i +: 16];
|
||||
memory[ 8*16 + i] <= INIT_8[16*i +: 16];
|
||||
memory[ 9*16 + i] <= INIT_9[16*i +: 16];
|
||||
memory[10*16 + i] <= INIT_A[16*i +: 16];
|
||||
memory[11*16 + i] <= INIT_B[16*i +: 16];
|
||||
memory[12*16 + i] <= INIT_C[16*i +: 16];
|
||||
memory[13*16 + i] <= INIT_D[16*i +: 16];
|
||||
memory[14*16 + i] <= INIT_E[16*i +: 16];
|
||||
memory[15*16 + i] <= INIT_F[16*i +: 16];
|
||||
memory[ 0*16 + i] <= INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] <= INIT_1[16*i +: 16];
|
||||
memory[ 2*16 + i] <= INIT_2[16*i +: 16];
|
||||
memory[ 3*16 + i] <= INIT_3[16*i +: 16];
|
||||
memory[ 4*16 + i] <= INIT_4[16*i +: 16];
|
||||
memory[ 5*16 + i] <= INIT_5[16*i +: 16];
|
||||
memory[ 6*16 + i] <= INIT_6[16*i +: 16];
|
||||
memory[ 7*16 + i] <= INIT_7[16*i +: 16];
|
||||
memory[ 8*16 + i] <= INIT_8[16*i +: 16];
|
||||
memory[ 9*16 + i] <= INIT_9[16*i +: 16];
|
||||
memory[10*16 + i] <= INIT_A[16*i +: 16];
|
||||
memory[11*16 + i] <= INIT_B[16*i +: 16];
|
||||
memory[12*16 + i] <= INIT_C[16*i +: 16];
|
||||
memory[13*16 + i] <= INIT_D[16*i +: 16];
|
||||
memory[14*16 + i] <= INIT_E[16*i +: 16];
|
||||
memory[15*16 + i] <= INIT_F[16*i +: 16];
|
||||
`else
|
||||
memory[ 0*16 + i] = INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] = INIT_1[16*i +: 16];
|
||||
memory[ 2*16 + i] = INIT_2[16*i +: 16];
|
||||
memory[ 3*16 + i] = INIT_3[16*i +: 16];
|
||||
memory[ 4*16 + i] = INIT_4[16*i +: 16];
|
||||
memory[ 5*16 + i] = INIT_5[16*i +: 16];
|
||||
memory[ 6*16 + i] = INIT_6[16*i +: 16];
|
||||
memory[ 7*16 + i] = INIT_7[16*i +: 16];
|
||||
memory[ 8*16 + i] = INIT_8[16*i +: 16];
|
||||
memory[ 9*16 + i] = INIT_9[16*i +: 16];
|
||||
memory[10*16 + i] = INIT_A[16*i +: 16];
|
||||
memory[11*16 + i] = INIT_B[16*i +: 16];
|
||||
memory[12*16 + i] = INIT_C[16*i +: 16];
|
||||
memory[13*16 + i] = INIT_D[16*i +: 16];
|
||||
memory[14*16 + i] = INIT_E[16*i +: 16];
|
||||
memory[15*16 + i] = INIT_F[16*i +: 16];
|
||||
memory[ 0*16 + i] = INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] = INIT_1[16*i +: 16];
|
||||
memory[ 2*16 + i] = INIT_2[16*i +: 16];
|
||||
memory[ 3*16 + i] = INIT_3[16*i +: 16];
|
||||
memory[ 4*16 + i] = INIT_4[16*i +: 16];
|
||||
memory[ 5*16 + i] = INIT_5[16*i +: 16];
|
||||
memory[ 6*16 + i] = INIT_6[16*i +: 16];
|
||||
memory[ 7*16 + i] = INIT_7[16*i +: 16];
|
||||
memory[ 8*16 + i] = INIT_8[16*i +: 16];
|
||||
memory[ 9*16 + i] = INIT_9[16*i +: 16];
|
||||
memory[10*16 + i] = INIT_A[16*i +: 16];
|
||||
memory[11*16 + i] = INIT_B[16*i +: 16];
|
||||
memory[12*16 + i] = INIT_C[16*i +: 16];
|
||||
memory[13*16 + i] = INIT_D[16*i +: 16];
|
||||
memory[14*16 + i] = INIT_E[16*i +: 16];
|
||||
memory[15*16 + i] = INIT_F[16*i +: 16];
|
||||
`endif
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge WCLK) begin
|
||||
|
@ -504,6 +509,8 @@ module SB_RAM40_4KNR (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
SB_RAM40_4K #(
|
||||
.WRITE_MODE(WRITE_MODE),
|
||||
.READ_MODE (READ_MODE ),
|
||||
|
@ -522,7 +529,8 @@ module SB_RAM40_4KNR (
|
|||
.INIT_C (INIT_C ),
|
||||
.INIT_D (INIT_D ),
|
||||
.INIT_E (INIT_E ),
|
||||
.INIT_F (INIT_F )
|
||||
.INIT_F (INIT_F ),
|
||||
.INIT_FILE (INIT_FILE )
|
||||
) RAM (
|
||||
.RDATA(RDATA),
|
||||
.RCLK (~RCLKN),
|
||||
|
@ -566,6 +574,8 @@ module SB_RAM40_4KNW (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
SB_RAM40_4K #(
|
||||
.WRITE_MODE(WRITE_MODE),
|
||||
.READ_MODE (READ_MODE ),
|
||||
|
@ -584,7 +594,8 @@ module SB_RAM40_4KNW (
|
|||
.INIT_C (INIT_C ),
|
||||
.INIT_D (INIT_D ),
|
||||
.INIT_E (INIT_E ),
|
||||
.INIT_F (INIT_F )
|
||||
.INIT_F (INIT_F ),
|
||||
.INIT_FILE (INIT_FILE )
|
||||
) RAM (
|
||||
.RDATA(RDATA),
|
||||
.RCLK (RCLK ),
|
||||
|
@ -628,6 +639,8 @@ module SB_RAM40_4KNRNW (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
SB_RAM40_4K #(
|
||||
.WRITE_MODE(WRITE_MODE),
|
||||
.READ_MODE (READ_MODE ),
|
||||
|
@ -646,7 +659,8 @@ module SB_RAM40_4KNRNW (
|
|||
.INIT_C (INIT_C ),
|
||||
.INIT_D (INIT_D ),
|
||||
.INIT_E (INIT_E ),
|
||||
.INIT_F (INIT_F )
|
||||
.INIT_F (INIT_F ),
|
||||
.INIT_FILE (INIT_FILE )
|
||||
) RAM (
|
||||
.RDATA(RDATA),
|
||||
.RCLK (~RCLKN),
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <bitset>
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
static void run_ice40_braminit(Module *module)
|
||||
{
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
uint16_t mem[256];
|
||||
|
||||
/* Only consider cells we're interested in */
|
||||
if (cell->type != "\\SB_RAM40_4K" &&
|
||||
cell->type != "\\SB_RAM40_4KNR" &&
|
||||
cell->type != "\\SB_RAM40_4KNW" &&
|
||||
cell->type != "\\SB_RAM40_4KNRNW")
|
||||
continue;
|
||||
if (!cell->hasParam("\\INIT_FILE"))
|
||||
continue;
|
||||
std::string init_file = cell->getParam("\\INIT_FILE").decode_string();
|
||||
cell->unsetParam("\\INIT_FILE");
|
||||
if (init_file == "")
|
||||
continue;
|
||||
|
||||
/* Open file */
|
||||
log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str());
|
||||
|
||||
std::ifstream f;
|
||||
f.open(init_file.c_str());
|
||||
if (f.fail()) {
|
||||
log("Can not open file `%s`.\n", init_file.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Defaults to 0 */
|
||||
memset(mem, 0x00, sizeof(mem));
|
||||
|
||||
/* Process each line */
|
||||
bool in_comment = false;
|
||||
int cursor = 0;
|
||||
|
||||
while (!f.eof())
|
||||
{
|
||||
std::string line, token;
|
||||
std::getline(f, line);
|
||||
|
||||
for (int i = 0; i < GetSize(line); i++)
|
||||
{
|
||||
if (in_comment && line.substr(i, 2) == "*/") {
|
||||
line[i] = ' ';
|
||||
line[i+1] = ' ';
|
||||
in_comment = false;
|
||||
continue;
|
||||
}
|
||||
if (!in_comment && line.substr(i, 2) == "/*")
|
||||
in_comment = true;
|
||||
if (in_comment)
|
||||
line[i] = ' ';
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
bool set_cursor = false;
|
||||
long value;
|
||||
|
||||
token = next_token(line, " \t\r\n");
|
||||
if (token.empty() || token.substr(0, 2) == "//")
|
||||
break;
|
||||
|
||||
if (token[0] == '@') {
|
||||
token = token.substr(1);
|
||||
set_cursor = true;
|
||||
}
|
||||
|
||||
const char *nptr = token.c_str();
|
||||
char *endptr;
|
||||
value = strtol(nptr, &endptr, 16);
|
||||
if (!*nptr || *endptr) {
|
||||
log("Can not parse %s `%s` for %s.\n",
|
||||
set_cursor ? "address" : "value",
|
||||
nptr, token.c_str()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (set_cursor)
|
||||
cursor = value;
|
||||
else if (cursor >= 0 && cursor < 256)
|
||||
mem[cursor++] = value;
|
||||
else
|
||||
log("Attempt to initialize non existent address %d\n", cursor);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set attributes */
|
||||
const char *hex = "0123456789ABCDEF";
|
||||
for (int i=0; i<16; i++) {
|
||||
std::string val = "";
|
||||
for (int j=15; j>=0; j--)
|
||||
val += std::bitset<16>(mem[i*16+j]).to_string();
|
||||
cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Ice40BRAMInitPass : public Pass {
|
||||
Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" ice40_braminit\n");
|
||||
log("\n");
|
||||
log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n");
|
||||
log("parameter and converts it inti the required INIT_x attributes\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing ICE40_BRAMINIT pass.\n");
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
// if (args[argidx] == "-???") {
|
||||
// continue;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
run_ice40_braminit(module);
|
||||
}
|
||||
} Ice40BRAMInitPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
Loading…
Reference in New Issue