aboutsummaryrefslogtreecommitdiffstats
path: root/backends/firrtl
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2016-11-18 02:41:29 +0100
committerClifford Wolf <clifford@clifford.at>2016-11-18 02:41:29 +0100
commite01382739db10b4ee01d02ba9991aace8dd666a5 (patch)
tree41392f08ce3b2385c0f15e9283f8f164034d40aa /backends/firrtl
parentc051115e03208faceca1b53da94bd430da2158e8 (diff)
downloadyosys-e01382739db10b4ee01d02ba9991aace8dd666a5.tar.gz
yosys-e01382739db10b4ee01d02ba9991aace8dd666a5.tar.bz2
yosys-e01382739db10b4ee01d02ba9991aace8dd666a5.zip
More progress in FIRRTL back-end
Diffstat (limited to 'backends/firrtl')
-rw-r--r--backends/firrtl/firrtl.cc96
-rw-r--r--backends/firrtl/test.sh3
-rw-r--r--backends/firrtl/test.v26
3 files changed, 121 insertions, 4 deletions
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index ef45eb043..3b61eb9f8 100644
--- a/backends/firrtl/firrtl.cc
+++ b/backends/firrtl/firrtl.cc
@@ -190,6 +190,102 @@ struct FirrtlWorker
continue;
}
+ if (cell->type.in("$mux"))
+ {
+ string y_id = make_id(cell->name);
+ int width = cell->parameters.at("\\WIDTH").as_int();
+ string a_expr = make_expr(cell->getPort("\\A"));
+ string b_expr = make_expr(cell->getPort("\\B"));
+ string s_expr = make_expr(cell->getPort("\\S"));
+ wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), width));
+
+ string expr = stringf("mux(%s, %s, %s)", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
+
+ cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ register_reverse_wire_map(y_id, cell->getPort("\\Y"));
+
+ continue;
+ }
+
+ if (cell->type.in("$mem"))
+ {
+ string mem_id = make_id(cell->name);
+ int abits = cell->parameters.at("\\ABITS").as_int();
+ int width = cell->parameters.at("\\WIDTH").as_int();
+ int size = cell->parameters.at("\\SIZE").as_int();
+ int rd_ports = cell->parameters.at("\\RD_PORTS").as_int();
+ int wr_ports = cell->parameters.at("\\WR_PORTS").as_int();
+
+ Const initdata = cell->parameters.at("\\INIT");
+ for (State bit : initdata.bits)
+ if (bit != State::Sx)
+ log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(cell));
+
+ Const rd_clk_enable = cell->parameters.at("\\RD_CLK_ENABLE");
+ Const wr_clk_enable = cell->parameters.at("\\WR_CLK_ENABLE");
+ Const wr_clk_polarity = cell->parameters.at("\\WR_CLK_POLARITY");
+
+ int offset = cell->parameters.at("\\OFFSET").as_int();
+ if (offset != 0)
+ log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(cell));
+
+ cell_exprs.push_back(stringf(" mem %s:\n", mem_id.c_str()));
+ cell_exprs.push_back(stringf(" data-type => UInt<%d>\n", width));
+ cell_exprs.push_back(stringf(" depth => %d\n", size));
+
+ for (int i = 0; i < rd_ports; i++)
+ cell_exprs.push_back(stringf(" reader => r%d\n", i));
+
+ for (int i = 0; i < wr_ports; i++)
+ cell_exprs.push_back(stringf(" writer => w%d\n", i));
+
+ cell_exprs.push_back(stringf(" read-latency => 0\n"));
+ cell_exprs.push_back(stringf(" write-latency => 1\n"));
+ cell_exprs.push_back(stringf(" read-under-write => undefined\n"));
+
+ for (int i = 0; i < rd_ports; i++)
+ {
+ if (rd_clk_enable[i] != State::S0)
+ log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ SigSpec data_sig = cell->getPort("\\RD_DATA").extract(i*width, width);
+ string addr_expr = make_expr(cell->getPort("\\RD_ADDR").extract(i*abits, abits));
+
+ cell_exprs.push_back(stringf(" %s.r%d.addr <= %s\n", mem_id.c_str(), i, addr_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.r%d.en <= UInt<1>(1)\n", mem_id.c_str(), i));
+ cell_exprs.push_back(stringf(" %s.r%d.clk <= asClock(UInt<1>(0))\n", mem_id.c_str(), i));
+
+ register_reverse_wire_map(stringf("%s.r%d.data", mem_id.c_str(), i), data_sig);
+ }
+
+ for (int i = 0; i < wr_ports; i++)
+ {
+ if (wr_clk_enable[i] != State::S1)
+ log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ if (wr_clk_polarity[i] != State::S1)
+ log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ string addr_expr = make_expr(cell->getPort("\\WR_ADDR").extract(i*abits, abits));
+ string data_expr = make_expr(cell->getPort("\\WR_DATA").extract(i*width, width));
+ string clk_expr = make_expr(cell->getPort("\\WR_CLK").extract(i));
+
+ SigSpec wen_sig = cell->getPort("\\WR_EN").extract(i*width, width);
+ string wen_expr = make_expr(wen_sig[0]);
+
+ for (int i = 1; i < GetSize(wen_sig); i++)
+ if (wen_sig[0] != wen_sig[i])
+ log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ cell_exprs.push_back(stringf(" %s.w%d.addr <= %s\n", mem_id.c_str(), i, addr_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.w%d.data <= %s\n", mem_id.c_str(), i, data_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.w%d.en <= %s\n", mem_id.c_str(), i, wen_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.w%d.clk <= asClock(%s)\n", mem_id.c_str(), i, clk_expr.c_str()));
+ }
+
+ continue;
+ }
+
if (cell->type.in("$dff"))
{
bool clkpol = cell->parameters.at("\\CLK_POLARITY").as_bool();
diff --git a/backends/firrtl/test.sh b/backends/firrtl/test.sh
index fd4929bf1..0a7151afa 100644
--- a/backends/firrtl/test.sh
+++ b/backends/firrtl/test.sh
@@ -1,7 +1,7 @@
#!/bin/bash
set -ex
-../../yosys -p 'prep; write_firrtl test.fir' test.v
+../../yosys -p 'prep -nordff; write_firrtl test.fir' test.v
firrtl -i test.fir -o test_out.v
@@ -13,6 +13,7 @@ firrtl -i test.fir -o test_out.v
rename test gate
prep
+ memory_map
miter -equiv -flatten gold gate miter
hierarchy -top miter
diff --git a/backends/firrtl/test.v b/backends/firrtl/test.v
index 3e294e3d5..1c7088ab8 100644
--- a/backends/firrtl/test.v
+++ b/backends/firrtl/test.v
@@ -1,4 +1,24 @@
-module test(input clk, signed input [7:0] a, b, x, output [15:0] s, d, y, z, u, q);
- assign s = a+{b[6:2], 2'b1}, d = a-b, y = x, z[7:0] = s+d, z[15:8] = s-d;
- always @(posedge clk) q <= s ^ d ^ x;
+module test(
+ input clk, wen,
+ input [4:0] waddr, raddr,
+ input [31:0] wdata,
+ output reg [31:0] rdata,
+ signed input [7:0] a, b, x,
+ output [15:0] s, d, y, z, u, q
+);
+ reg [31:0] memory [0:31];
+
+ always @(posedge clk) begin
+ rdata <= memory[raddr];
+ if (wen) memory[waddr] <= wdata;
+ end
+
+ assign s = a+{b[6:2], 2'b1};
+ assign d = a-b;
+ assign y = x;
+ assign z[7:0] = s+d;
+ assign z[15:8] = s-d;
+
+ always @(posedge clk)
+ q <= s ^ d ^ x;
endmodule