aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/verilog/const2ast.cc3
-rw-r--r--passes/techmap/deminout.cc2
-rw-r--r--passes/techmap/iopadmap.cc16
-rw-r--r--techlibs/common/gen_fine_ffs.py239
-rw-r--r--techlibs/common/simcells.v50
-rw-r--r--tests/techmap/iopadmap.ys10
6 files changed, 298 insertions, 22 deletions
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc
index 49281f7e7..230dfadbf 100644
--- a/frontends/verilog/const2ast.cc
+++ b/frontends/verilog/const2ast.cc
@@ -139,6 +139,9 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
data.resize(len_in_bits, msb);
}
+ if (len_in_bits == 0)
+ log_file_error(current_filename, get_line_num(), "Illegal integer constant size of zero (IEEE 1800-2012, 5.7).\n");
+
if (len > len_in_bits)
log_warning("Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n",
len_in_bits, len, current_filename.c_str(), get_line_num());
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
index 35d43b106..a7dce9c81 100644
--- a/passes/techmap/deminout.cc
+++ b/passes/techmap/deminout.cc
@@ -113,7 +113,7 @@ struct DeminoutPass : public Pass {
{
if (bits_numports[bit] > 1 || bits_inout.count(bit))
new_input = true, new_output = true;
- if (bit == State::S0 || bit == State::S1)
+ if (!bit.wire)
new_output = true;
if (bits_written.count(bit)) {
new_output = true;
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 4504633ee..a18d02652 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -229,11 +229,13 @@ struct IopadmapPass : public Pass {
for (auto module : design->selected_modules())
{
dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits;
+ pool<SigSig> remove_conns;
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
{
dict<SigBit, Cell *> tbuf_bits;
pool<SigBit> driven_bits;
+ dict<SigBit, SigSig> z_conns;
// Gather tristate buffers and always-on drivers.
for (auto cell : module->cells())
@@ -252,8 +254,10 @@ struct IopadmapPass : public Pass {
for (int i = 0; i < GetSize(conn.first); i++) {
SigBit dstbit = conn.first[i];
SigBit srcbit = conn.second[i];
- if (!srcbit.wire && srcbit.data == State::Sz)
+ if (!srcbit.wire && srcbit.data == State::Sz) {
+ z_conns[dstbit] = conn;
continue;
+ }
driven_bits.insert(dstbit);
}
@@ -302,6 +306,8 @@ struct IopadmapPass : public Pass {
// enable.
en_sig = SigBit(State::S0);
data_sig = SigBit(State::Sx);
+ if (z_conns.count(wire_bit))
+ remove_conns.insert(z_conns[wire_bit]);
}
if (wire->port_input)
@@ -454,6 +460,14 @@ struct IopadmapPass : public Pass {
}
}
+ if (!remove_conns.empty()) {
+ std::vector<SigSig> new_conns;
+ for (auto &conn : module->connections())
+ if (!remove_conns.count(conn))
+ new_conns.push_back(conn);
+ module->new_connections(new_conns);
+ }
+
for (auto &it : rewrite_bits) {
RTLIL::Wire *wire = it.first;
RTLIL::Wire *new_wire = module->addWire(
diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py
new file mode 100644
index 000000000..3a9aa6c59
--- /dev/null
+++ b/techlibs/common/gen_fine_ffs.py
@@ -0,0 +1,239 @@
+TEMPLATES = [
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_SR_{S:N|P}{R:N|P}_ (S, R, Q)
+//-
+//- A set-reset latch with {S:negative|positive} polarity SET and {R:negative|positive} polarity RESET.
+//-
+//- Truth table: S R | Q
+//- -----+---
+//- {S:0|1} {R:0|1} | x
+//- {S:0|1} {R:1|0} | 1
+//- {S:1|0} {R:0|1} | 0
+//- {S:1|0} {R:1|0} | y
+//-
+module \$_SR_{S:N|P}{R:N|P}_ (S, R, Q);
+input S, R;
+output reg Q;
+always @({S:neg|pos}edge S, {R:neg|pos}edge R) begin
+ if (R == {R:0|1})
+ Q <= 0;
+ else if (S == {S:0|1})
+ Q <= 1;
+end
+endmodule
+""",
+"""
+`ifdef SIMCELLS_FF
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_FF_ (D, Q)
+//-
+//- A D-type flip-flop that is clocked from the implicit global clock. (This cell
+//- type is usually only used in netlists for formal verification.)
+//-
+module \$_FF_ (D, Q);
+input D;
+output reg Q;
+always @($global_clock) begin
+ Q <= D;
+end
+endmodule
+`endif
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_DFF_{C:N|P}_ (D, C, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop.
+//-
+//- Truth table: D C | Q
+//- -----+---
+//- d {C:\\|/} | d
+//- - - | q
+//-
+module \$_DFF_{C:N|P}_ (D, C, Q);
+input D, C;
+output reg Q;
+always @({C:neg|pos}edge C) begin
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_DFFE_{C:N|P}{E:N|P}_ (D, C, E, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop with {E:negative|positive} polarity enable.
+//-
+//- Truth table: D C E | Q
+//- -------+---
+//- d {C:\\|/} {E:0|1} | d
+//- - - - | q
+//-
+module \$_DFFE_{C:N|P}{E:N|P}_ (D, C, E, Q);
+input D, C, E;
+output reg Q;
+always @({C:neg|pos}edge C) begin
+ if ({E:!E|E}) Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_DFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop with {R:negative|positive} polarity {V:reset|set}.
+//-
+//- Truth table: D C R | Q
+//- -------+---
+//- - - {R:0|1} | {V:0|1}
+//- d {C:\\|/} - | d
+//- - - - | q
+//-
+module \$_DFF_{C:N|P}{R:N|P}{V:0|1}_ (D, C, R, Q);
+input D, C, R;
+output reg Q;
+always @({C:neg|pos}edge C or {R:neg|pos}edge R) begin
+ if (R == {R:0|1})
+ Q <= {V:0|1};
+ else
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive}
+//- polarity reset.
+//-
+//- Truth table: C S R D | Q
+//- ---------+---
+//- - - {R:0|1} - | 0
+//- - {S:0|1} - - | 1
+//- {C:\\|/} - - d | d
+//- - - - - | q
+//-
+module \$_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q);
+input C, S, R, D;
+output reg Q;
+always @({C:neg|pos}edge C, {S:neg|pos}edge S, {R:neg|pos}edge R) begin
+ if (R == {R:0|1})
+ Q <= 0;
+ else if (S == {S:0|1})
+ Q <= 1;
+ else
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_DLATCH_{E:N|P}_ (E, D, Q)
+//-
+//- A {E:negative|positive} enable D-type latch.
+//-
+//- Truth table: E D | Q
+//- -----+---
+//- {E:0|1} d | d
+//- - - | q
+//-
+module \$_DLATCH_{E:N|P}_ (E, D, Q);
+input E, D;
+output reg Q;
+always @* begin
+ if (E == {E:0|1})
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_DLATCHSR_{E:N|P}{S:N|P}{R:N|P}_ (E, S, R, D, Q)
+//-
+//- A {E:negative|positive} enable D-type latch with {S:negative|positive} polarity set and {R:negative|positive}
+//- polarity reset.
+//-
+//- Truth table: E S R D | Q
+//- ---------+---
+//- - - {R:0|1} - | 0
+//- - {S:0|1} - - | 1
+//- {E:0|1} - - d | d
+//- - - - - | q
+//-
+module \$_DLATCHSR_{E:N|P}{S:N|P}{R:N|P}_ (E, S, R, D, Q);
+input E, S, R, D;
+output reg Q;
+always @* begin
+ if (R == {R:0|1})
+ Q <= 0;
+ else if (S == {S:0|1})
+ Q <= 1;
+ else if (E == {E:0|1})
+ Q <= D;
+end
+endmodule
+""",
+]
+
+lines = []
+with open('simcells.v') as f:
+ for l in f:
+ lines.append(l)
+ if 'START AUTOGENERATED CELL TYPES' in l:
+ break
+
+with open('simcells.v', 'w') as f:
+ for l in lines:
+ f.write(l)
+ for template in TEMPLATES:
+ chunks = []
+ vars = {}
+ pos = 0
+ while pos < len(template):
+ if template[pos] != '{':
+ np = template.find('{', pos)
+ if np == -1:
+ np = len(template)
+ chunks.append(template[pos:np])
+ pos = np
+ else:
+ np = template.index('}', pos)
+ sub = template[pos + 1:np]
+ pos = np + 1
+ var, _, vals = sub.partition(':')
+ if not vals:
+ raise ValueError(sub)
+ vals = vals.split('|')
+ if var not in vars:
+ vars[var] = len(vals)
+ else:
+ if vars[var] != len(vals):
+ raise ValueError(vars[var], vals)
+ chunks.append((var, vals))
+ combs = [{}]
+ for var in vars:
+ combs = [
+ {
+ var: i,
+ **comb,
+ }
+ for comb in combs
+ for i in range(vars[var])
+ ]
+ for comb in combs:
+ f.write(
+ ''.join(
+ c if isinstance(c, str) else c[1][comb[c[0]]]
+ for c in chunks
+ )
+ )
diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v
index 64720e598..2bac78d38 100644
--- a/techlibs/common/simcells.v
+++ b/techlibs/common/simcells.v
@@ -456,11 +456,16 @@ output Y;
assign Y = E ? A : 1'bz;
endmodule
+// NOTE: the following cell types are autogenerated. DO NOT EDIT them manually,
+// instead edit the templates in gen_ff_types.py and rerun it.
+
+// START AUTOGENERATED CELL TYPES
+
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $_SR_NN_ (S, R, Q)
//-
-//- A set-reset latch with negative polarity SET and RESET.
+//- A set-reset latch with negative polarity SET and negative polarity RESET.
//-
//- Truth table: S R | Q
//- -----+---
@@ -532,7 +537,7 @@ endmodule
//-
//- $_SR_PP_ (S, R, Q)
//-
-//- A set-reset latch with positive polarity SET and RESET.
+//- A set-reset latch with positive polarity SET and positive polarity RESET.
//-
//- Truth table: S R | Q
//- -----+---
@@ -871,7 +876,8 @@ endmodule
//-
//- $_DFFSR_NNN_ (C, S, R, D, Q)
//-
-//- A negative edge D-type flip-flop with negative polarity set and reset.
+//- A negative edge D-type flip-flop with negative polarity set and negative
+//- polarity reset.
//-
//- Truth table: C S R D | Q
//- ---------+---
@@ -951,7 +957,8 @@ endmodule
//-
//- $_DFFSR_NPP_ (C, S, R, D, Q)
//-
-//- A negative edge D-type flip-flop with positive polarity set and reset.
+//- A negative edge D-type flip-flop with positive polarity set and positive
+//- polarity reset.
//-
//- Truth table: C S R D | Q
//- ---------+---
@@ -977,7 +984,8 @@ endmodule
//-
//- $_DFFSR_PNN_ (C, S, R, D, Q)
//-
-//- A positive edge D-type flip-flop with negative polarity set and reset.
+//- A positive edge D-type flip-flop with negative polarity set and negative
+//- polarity reset.
//-
//- Truth table: C S R D | Q
//- ---------+---
@@ -1057,7 +1065,8 @@ endmodule
//-
//- $_DFFSR_PPP_ (C, S, R, D, Q)
//-
-//- A positive edge D-type flip-flop with positive polarity set and reset.
+//- A positive edge D-type flip-flop with positive polarity set and positive
+//- polarity reset.
//-
//- Truth table: C S R D | Q
//- ---------+---
@@ -1123,7 +1132,8 @@ endmodule
//-
//- $_DLATCHSR_NNN_ (E, S, R, D, Q)
//-
-//- A negative enable D-type latch with negative polarity set and reset.
+//- A negative enable D-type latch with negative polarity set and negative
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1149,8 +1159,8 @@ endmodule
//-
//- $_DLATCHSR_NNP_ (E, S, R, D, Q)
//-
-//- A negative enable D-type latch with negative polarity set and positive polarity
-//- reset.
+//- A negative enable D-type latch with negative polarity set and positive
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1176,8 +1186,8 @@ endmodule
//-
//- $_DLATCHSR_NPN_ (E, S, R, D, Q)
//-
-//- A negative enable D-type latch with positive polarity set and negative polarity
-//- reset.
+//- A negative enable D-type latch with positive polarity set and negative
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1203,7 +1213,8 @@ endmodule
//-
//- $_DLATCHSR_NPP_ (E, S, R, D, Q)
//-
-//- A negative enable D-type latch with positive polarity set and reset.
+//- A negative enable D-type latch with positive polarity set and positive
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1229,7 +1240,8 @@ endmodule
//-
//- $_DLATCHSR_PNN_ (E, S, R, D, Q)
//-
-//- A positive enable D-type latch with negative polarity set and reset.
+//- A positive enable D-type latch with negative polarity set and negative
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1255,8 +1267,8 @@ endmodule
//-
//- $_DLATCHSR_PNP_ (E, S, R, D, Q)
//-
-//- A positive enable D-type latch with negative polarity set and positive polarity
-//- reset.
+//- A positive enable D-type latch with negative polarity set and positive
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1282,8 +1294,8 @@ endmodule
//-
//- $_DLATCHSR_PPN_ (E, S, R, D, Q)
//-
-//- A positive enable D-type latch with positive polarity set and negative polarity
-//- reset.
+//- A positive enable D-type latch with positive polarity set and negative
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1309,7 +1321,8 @@ endmodule
//-
//- $_DLATCHSR_PPP_ (E, S, R, D, Q)
//-
-//- A positive enable D-type latch with positive polarity set and reset.
+//- A positive enable D-type latch with positive polarity set and positive
+//- polarity reset.
//-
//- Truth table: E S R D | Q
//- ---------+---
@@ -1330,4 +1343,3 @@ always @* begin
Q <= D;
end
endmodule
-
diff --git a/tests/techmap/iopadmap.ys b/tests/techmap/iopadmap.ys
index 25ea94dfc..df029b3a0 100644
--- a/tests/techmap/iopadmap.ys
+++ b/tests/techmap/iopadmap.ys
@@ -55,13 +55,19 @@ obuf b (.i(i), .o(tmp));
assign o = tmp;
endmodule
+module k(inout o, o2);
+assign o = 1'bz;
+endmodule
+
EOT
opt_clean
tribuf
simplemap
-iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io a b c d e f g h i j
+iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io a b c d e f g h i j k
opt_clean
+hierarchy -check
+check
select -assert-count 1 a/t:ibuf
select -assert-count 1 a/t:obuf
@@ -140,6 +146,8 @@ select -assert-count 0 i/t:obuf
select -assert-count 1 j/t:ibuf
select -assert-count 1 j/t:obuf
+select -assert-count 2 k/t:iobuf
+
# Check that \init attributes get moved from output buffer
# to buffer input