diff --git a/.travis.yml b/.travis.yml
index 4102f05fe..09f380831 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -40,35 +40,6 @@ matrix:
       env:
         - MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
 
-    # Latest gcc-6 on Travis Linux
-    - os: linux
-      addons:
-        apt:
-          sources:
-            - ubuntu-toolchain-r-test
-          packages:
-            - g++-6
-            - gperf
-            - build-essential
-            - bison
-            - flex
-            - libreadline-dev
-            - gawk
-            - tcl-dev
-            - libffi-dev
-            - git
-            - graphviz
-            - xdot
-            - pkg-config
-            - python
-            - python3
-            - libboost-system-dev
-            - libboost-python-dev
-            - libboost-filesystem-dev
-            - zlib1g-dev
-      env:
-        - MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6"
-
     # Latest gcc supported on Travis Linux
     - os: linux
       addons:
@@ -76,7 +47,7 @@ matrix:
           sources:
             - ubuntu-toolchain-r-test
           packages:
-            - g++-7
+            - g++-9
             - gperf
             - build-essential
             - bison
@@ -96,7 +67,7 @@ matrix:
             - libboost-filesystem-dev
             - zlib1g-dev
       env:
-        - MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
+        - MATRIX_EVAL="CONFIG=gcc && CC=gcc-9 && CXX=g++-9"
 
     # Clang which ships on Trusty Linux
     - os: linux
@@ -133,9 +104,9 @@ matrix:
       addons:
         apt:
           sources:
-            - llvm-toolchain-trusty-5.0
+            - llvm-toolchain-xenial-8
           packages:
-            - clang-5.0
+            - clang-8
             - gperf
             - build-essential
             - bison
@@ -155,7 +126,7 @@ matrix:
             - libboost-filesystem-dev
             - zlib1g-dev
       env:
-        - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
+        - MATRIX_EVAL="CONFIG=clang && CC=clang-8 && CXX=clang++-8"
 
 #   # Latest clang on Mac OS X
 #   - os: osx
diff --git a/.travis/setup.sh b/.travis/setup.sh
index 4af0b8ee9..02879b974 100755
--- a/.travis/setup.sh
+++ b/.travis/setup.sh
@@ -51,7 +51,7 @@ fi
 		git clone git://github.com/steveicarus/iverilog.git
 		cd iverilog
 		autoconf
-		./configure --prefix=$HOME/.local-bin
+		CC=gcc CXX=g++ ./configure --prefix=$HOME/.local-bin
 		make
 		make install
 		echo
diff --git a/Dockerfile b/Dockerfile
index 3c7188d82..549c73c97 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,33 +1,57 @@
-FROM ubuntu:18.04 as builder
-LABEL author="Abdelrahman Hosny <abdelrahman.hosny@hotmail.com>"
-ENV DEBIAN_FRONTEND=noninteractive
-RUN apt-get update && apt-get install -y build-essential \
+ARG IMAGE="python:3-slim-buster"
+
+#---
+
+FROM $IMAGE AS base
+
+RUN apt-get update -qq \
+ && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
+    ca-certificates \
     clang \
+    curl \
+    libffi-dev \
+    libreadline-dev \
+    tcl-dev \
+    graphviz \
+    xdot \
+ && apt-get autoclean && apt-get clean && apt-get -y autoremove \
+ && update-ca-certificates \
+ && rm -rf /var/lib/apt/lists
+
+#---
+
+FROM base AS build
+
+RUN apt-get update -qq \
+ && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
     bison \
     flex \
-    libreadline-dev \
     gawk \
-    tcl-dev \
-    libffi-dev \
+    gcc \
     git \
+    iverilog \
     pkg-config \
-    python3 && \
-    rm -rf /var/lib/apt/lists
-COPY . /
-RUN make && \
-    make install
+ && apt-get autoclean && apt-get clean && apt-get -y autoremove \
+ && rm -rf /var/lib/apt/lists
 
-FROM ubuntu:18.04
-ENV DEBIAN_FRONTEND=noninteractive
-RUN apt-get update && apt-get install -y libreadline-dev tcl-dev
+COPY . /yosys
 
-COPY --from=builder /yosys /build/yosys
-COPY --from=builder /yosys-abc /build/yosys-abc
-COPY --from=builder /yosys-config /build/yosys-config
-COPY --from=builder /yosys-filterlib /build/yosys-filterlib
-COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc
+ENV PREFIX /opt/yosys
+
+RUN cd /yosys \
+ && make \
+ && make install \
+ && make test
+
+#---
+
+FROM base
+
+COPY --from=build /opt/yosys /opt/yosys
+
+ENV PATH /opt/yosys/bin:$PATH
 
-ENV PATH /build:$PATH
 RUN useradd -m yosys
 USER yosys
-ENTRYPOINT ["yosys"]
+
+CMD ["yosys"]
diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc
index fbc6d045e..6d496db45 100644
--- a/kernel/cellaigs.cc
+++ b/kernel/cellaigs.cc
@@ -268,9 +268,9 @@ Aig::Aig(Cell *cell)
 	cell->parameters.sort();
 	for (auto p : cell->parameters)
 	{
-		if (p.first == "\\A_WIDTH" && mkname_a_signed) {
+		if (p.first == ID(A_WIDTH) && mkname_a_signed) {
 			name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
-		} else if (p.first == "\\B_WIDTH" && mkname_b_signed) {
+		} else if (p.first == ID(B_WIDTH) && mkname_b_signed) {
 			name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
 		} else {
 			mkname_last = name;
@@ -280,183 +280,183 @@ Aig::Aig(Cell *cell)
 		mkname_a_signed = false;
 		mkname_b_signed = false;
 		mkname_is_signed = false;
-		if (p.first == "\\A_SIGNED") {
+		if (p.first == ID(A_SIGNED)) {
 			mkname_a_signed = true;
 			mkname_is_signed = p.second.as_bool();
 		}
-		if (p.first == "\\B_SIGNED") {
+		if (p.first == ID(B_SIGNED)) {
 			mkname_b_signed = true;
 			mkname_is_signed = p.second.as_bool();
 		}
 	}
 
-	if (cell->type.in("$not", "$_NOT_", "$pos", "$_BUF_"))
+	if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($_BUF_)))
 	{
-		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
-			int A = mk.inport("\\A", i);
-			int Y = cell->type.in("$not", "$_NOT_") ? mk.not_gate(A) : A;
-			mk.outport(Y, "\\Y", i);
+		for (int i = 0; i < GetSize(cell->getPort(ID(Y))); i++) {
+			int A = mk.inport(ID(A), i);
+			int Y = cell->type.in(ID($not), ID($_NOT_)) ? mk.not_gate(A) : A;
+			mk.outport(Y, ID(Y), i);
 		}
 		goto optimize;
 	}
 
-	if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$xor", "$xnor", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
+	if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_), ID($or), ID($_OR_), ID($_NOR_), ID($xor), ID($xnor), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
 	{
-		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
-			int A = mk.inport("\\A", i);
-			int B = mk.inport("\\B", i);
-			int Y = cell->type.in("$and", "$_AND_")   ? mk.and_gate(A, B) :
-			        cell->type.in("$_NAND_")          ? mk.nand_gate(A, B) :
-			        cell->type.in("$or", "$_OR_")     ? mk.or_gate(A, B) :
-			        cell->type.in("$_NOR_")           ? mk.nor_gate(A, B) :
-			        cell->type.in("$xor", "$_XOR_")   ? mk.xor_gate(A, B) :
-			        cell->type.in("$xnor", "$_XNOR_") ? mk.xnor_gate(A, B) :
-			        cell->type.in("$_ANDNOT_")        ? mk.andnot_gate(A, B) :
-			        cell->type.in("$_ORNOT_")         ? mk.ornot_gate(A, B) : -1;
-			mk.outport(Y, "\\Y", i);
+		for (int i = 0; i < GetSize(cell->getPort(ID(Y))); i++) {
+			int A = mk.inport(ID(A), i);
+			int B = mk.inport(ID(B), i);
+			int Y = cell->type.in(ID($and), ID($_AND_))   ? mk.and_gate(A, B) :
+			        cell->type.in(ID($_NAND_))          ? mk.nand_gate(A, B) :
+			        cell->type.in(ID($or), ID($_OR_))     ? mk.or_gate(A, B) :
+			        cell->type.in(ID($_NOR_))           ? mk.nor_gate(A, B) :
+			        cell->type.in(ID($xor), ID($_XOR_))   ? mk.xor_gate(A, B) :
+			        cell->type.in(ID($xnor), ID($_XNOR_)) ? mk.xnor_gate(A, B) :
+			        cell->type.in(ID($_ANDNOT_))        ? mk.andnot_gate(A, B) :
+			        cell->type.in(ID($_ORNOT_))         ? mk.ornot_gate(A, B) : -1;
+			mk.outport(Y, ID(Y), i);
 		}
 		goto optimize;
 	}
 
-	if (cell->type.in("$mux", "$_MUX_"))
+	if (cell->type.in(ID($mux), ID($_MUX_)))
 	{
-		int S = mk.inport("\\S");
-		for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
-			int A = mk.inport("\\A", i);
-			int B = mk.inport("\\B", i);
+		int S = mk.inport(ID(S));
+		for (int i = 0; i < GetSize(cell->getPort(ID(Y))); i++) {
+			int A = mk.inport(ID(A), i);
+			int B = mk.inport(ID(B), i);
 			int Y = mk.mux_gate(A, B, S);
-			if (cell->type == "$_NMUX_")
+			if (cell->type == ID($_NMUX_))
 				Y = mk.not_gate(Y);
-			mk.outport(Y, "\\Y", i);
+			mk.outport(Y, ID(Y), i);
 		}
 		goto optimize;
 	}
 
-	if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool"))
+	if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)))
 	{
-		int Y = mk.inport("\\A", 0);
-		for (int i = 1; i < GetSize(cell->getPort("\\A")); i++) {
-			int A = mk.inport("\\A", i);
-			if (cell->type == "$reduce_and")  Y = mk.and_gate(A, Y);
-			if (cell->type == "$reduce_or")   Y = mk.or_gate(A, Y);
-			if (cell->type == "$reduce_bool") Y = mk.or_gate(A, Y);
-			if (cell->type == "$reduce_xor")  Y = mk.xor_gate(A, Y);
-			if (cell->type == "$reduce_xnor") Y = mk.xor_gate(A, Y);
+		int Y = mk.inport(ID(A), 0);
+		for (int i = 1; i < GetSize(cell->getPort(ID(A))); i++) {
+			int A = mk.inport(ID(A), i);
+			if (cell->type == ID($reduce_and))  Y = mk.and_gate(A, Y);
+			if (cell->type == ID($reduce_or))   Y = mk.or_gate(A, Y);
+			if (cell->type == ID($reduce_bool)) Y = mk.or_gate(A, Y);
+			if (cell->type == ID($reduce_xor))  Y = mk.xor_gate(A, Y);
+			if (cell->type == ID($reduce_xnor)) Y = mk.xor_gate(A, Y);
 		}
-		if (cell->type == "$reduce_xnor")
+		if (cell->type == ID($reduce_xnor))
 			Y = mk.not_gate(Y);
-		mk.outport(Y, "\\Y", 0);
-		for (int i = 1; i < GetSize(cell->getPort("\\Y")); i++)
-			mk.outport(mk.bool_node(false), "\\Y", i);
+		mk.outport(Y, ID(Y), 0);
+		for (int i = 1; i < GetSize(cell->getPort(ID(Y))); i++)
+			mk.outport(mk.bool_node(false), ID(Y), i);
 		goto optimize;
 	}
 
-	if (cell->type.in("$logic_not", "$logic_and", "$logic_or"))
+	if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or)))
 	{
-		int A = mk.inport("\\A", 0), Y = -1;
-		for (int i = 1; i < GetSize(cell->getPort("\\A")); i++)
-			A = mk.or_gate(mk.inport("\\A", i), A);
-		if (cell->type.in("$logic_and", "$logic_or")) {
-			int B = mk.inport("\\B", 0);
-			for (int i = 1; i < GetSize(cell->getPort("\\B")); i++)
-				B = mk.or_gate(mk.inport("\\B", i), B);
-			if (cell->type == "$logic_and") Y = mk.and_gate(A, B);
-			if (cell->type == "$logic_or")  Y = mk.or_gate(A, B);
+		int A = mk.inport(ID(A), 0), Y = -1;
+		for (int i = 1; i < GetSize(cell->getPort(ID(A))); i++)
+			A = mk.or_gate(mk.inport(ID(A), i), A);
+		if (cell->type.in(ID($logic_and), ID($logic_or))) {
+			int B = mk.inport(ID(B), 0);
+			for (int i = 1; i < GetSize(cell->getPort(ID(B))); i++)
+				B = mk.or_gate(mk.inport(ID(B), i), B);
+			if (cell->type == ID($logic_and)) Y = mk.and_gate(A, B);
+			if (cell->type == ID($logic_or))  Y = mk.or_gate(A, B);
 		} else {
-			if (cell->type == "$logic_not") Y = mk.not_gate(A);
+			if (cell->type == ID($logic_not)) Y = mk.not_gate(A);
 		}
-		mk.outport_bool(Y, "\\Y");
+		mk.outport_bool(Y, ID(Y));
 		goto optimize;
 	}
 
-	if (cell->type.in("$add", "$sub"))
+	if (cell->type.in(ID($add), ID($sub)))
 	{
-		int width = GetSize(cell->getPort("\\Y"));
-		vector<int> A = mk.inport_vec("\\A", width);
-		vector<int> B = mk.inport_vec("\\B", width);
+		int width = GetSize(cell->getPort(ID(Y)));
+		vector<int> A = mk.inport_vec(ID(A), width);
+		vector<int> B = mk.inport_vec(ID(B), width);
 		int carry = mk.bool_node(false);
-		if (cell->type == "$sub") {
+		if (cell->type == ID($sub)) {
 			for (auto &n : B)
 				n = mk.not_gate(n);
 			carry = mk.not_gate(carry);
 		}
 		vector<int> Y = mk.adder(A, B, carry);
-		mk.outport_vec(Y, "\\Y");
+		mk.outport_vec(Y, ID(Y));
 		goto optimize;
 	}
 
-	if (cell->type == "$alu")
+	if (cell->type == ID($alu))
 	{
-		int width = GetSize(cell->getPort("\\Y"));
-		vector<int> A = mk.inport_vec("\\A", width);
-		vector<int> B = mk.inport_vec("\\B", width);
-		int carry = mk.inport("\\CI");
-		int binv = mk.inport("\\BI");
+		int width = GetSize(cell->getPort(ID(Y)));
+		vector<int> A = mk.inport_vec(ID(A), width);
+		vector<int> B = mk.inport_vec(ID(B), width);
+		int carry = mk.inport(ID(CI));
+		int binv = mk.inport(ID(BI));
 		for (auto &n : B)
 			n = mk.xor_gate(n, binv);
 		vector<int> X(width), CO(width);
 		vector<int> Y = mk.adder(A, B, carry, &X, &CO);
 		for (int i = 0; i < width; i++)
 			X[i] = mk.xor_gate(A[i], B[i]);
-		mk.outport_vec(Y, "\\Y");
-		mk.outport_vec(X, "\\X");
-		mk.outport_vec(CO, "\\CO");
+		mk.outport_vec(Y, ID(Y));
+		mk.outport_vec(X, ID(X));
+		mk.outport_vec(CO, ID(CO));
 		goto optimize;
 	}
 
-	if (cell->type.in("$eq", "$ne"))
+	if (cell->type.in(ID($eq), ID($ne)))
 	{
-		int width = max(GetSize(cell->getPort("\\A")), GetSize(cell->getPort("\\B")));
-		vector<int> A = mk.inport_vec("\\A", width);
-		vector<int> B = mk.inport_vec("\\B", width);
+		int width = max(GetSize(cell->getPort(ID(A))), GetSize(cell->getPort(ID(B))));
+		vector<int> A = mk.inport_vec(ID(A), width);
+		vector<int> B = mk.inport_vec(ID(B), width);
 		int Y = mk.bool_node(false);
 		for (int i = 0; i < width; i++)
 			Y = mk.or_gate(Y, mk.xor_gate(A[i], B[i]));
-		if (cell->type == "$eq")
+		if (cell->type == ID($eq))
 			Y = mk.not_gate(Y);
-		mk.outport_bool(Y, "\\Y");
+		mk.outport_bool(Y, ID(Y));
 		goto optimize;
 	}
 
-	if (cell->type == "$_AOI3_")
+	if (cell->type == ID($_AOI3_))
 	{
-		int A = mk.inport("\\A");
-		int B = mk.inport("\\B");
-		int C = mk.inport("\\C");
+		int A = mk.inport(ID(A));
+		int B = mk.inport(ID(B));
+		int C = mk.inport(ID(C));
 		int Y = mk.nor_gate(mk.and_gate(A, B), C);
-		mk.outport(Y, "\\Y");
+		mk.outport(Y, ID(Y));
 		goto optimize;
 	}
 
-	if (cell->type == "$_OAI3_")
+	if (cell->type == ID($_OAI3_))
 	{
-		int A = mk.inport("\\A");
-		int B = mk.inport("\\B");
-		int C = mk.inport("\\C");
+		int A = mk.inport(ID(A));
+		int B = mk.inport(ID(B));
+		int C = mk.inport(ID(C));
 		int Y = mk.nand_gate(mk.or_gate(A, B), C);
-		mk.outport(Y, "\\Y");
+		mk.outport(Y, ID(Y));
 		goto optimize;
 	}
 
-	if (cell->type == "$_AOI4_")
+	if (cell->type == ID($_AOI4_))
 	{
-		int A = mk.inport("\\A");
-		int B = mk.inport("\\B");
-		int C = mk.inport("\\C");
-		int D = mk.inport("\\D");
+		int A = mk.inport(ID(A));
+		int B = mk.inport(ID(B));
+		int C = mk.inport(ID(C));
+		int D = mk.inport(ID(D));
 		int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
-		mk.outport(Y, "\\Y");
+		mk.outport(Y, ID(Y));
 		goto optimize;
 	}
 
-	if (cell->type == "$_OAI4_")
+	if (cell->type == ID($_OAI4_))
 	{
-		int A = mk.inport("\\A");
-		int B = mk.inport("\\B");
-		int C = mk.inport("\\C");
-		int D = mk.inport("\\D");
+		int A = mk.inport(ID(A));
+		int B = mk.inport(ID(B));
+		int C = mk.inport(ID(C));
+		int D = mk.inport(ID(D));
 		int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D));
-		mk.outport(Y, "\\Y");
+		mk.outport(Y, ID(Y));
 		goto optimize;
 	}
 
diff --git a/kernel/celledges.cc b/kernel/celledges.cc
index 556e8b826..7a324a06e 100644
--- a/kernel/celledges.cc
+++ b/kernel/celledges.cc
@@ -24,9 +24,9 @@ PRIVATE_NAMESPACE_BEGIN
 
 void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	IdString A = "\\A", Y = "\\Y";
+	IdString A = ID(A), Y = ID(Y);
 
-	bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
+	bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 	int a_width = GetSize(cell->getPort(A));
 	int y_width = GetSize(cell->getPort(Y));
 
@@ -41,14 +41,14 @@ void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 
 void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	IdString A = "\\A", B = "\\B", Y = "\\Y";
+	IdString A = ID(A), B = ID(B), Y = ID(Y);
 
-	bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
+	bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 	int a_width = GetSize(cell->getPort(A));
 	int b_width = GetSize(cell->getPort(B));
 	int y_width = GetSize(cell->getPort(Y));
 
-	if (cell->type == "$and" && !is_signed) {
+	if (cell->type == ID($and) && !is_signed) {
 		if (a_width > b_width)
 			a_width = b_width;
 		else
@@ -71,9 +71,9 @@ void bitwise_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 
 void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	IdString A = "\\A", Y = "\\Y";
+	IdString A = ID(A), Y = ID(Y);
 
-	bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
+	bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 	int a_width = GetSize(cell->getPort(A));
 	int y_width = GetSize(cell->getPort(Y));
 
@@ -87,14 +87,14 @@ void arith_neg_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 
 void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	IdString A = "\\A", B = "\\B", Y = "\\Y";
+	IdString A = ID(A), B = ID(B), Y = ID(Y);
 
-	bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
+	bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 	int a_width = GetSize(cell->getPort(A));
 	int b_width = GetSize(cell->getPort(B));
 	int y_width = GetSize(cell->getPort(Y));
 
-	if (!is_signed && cell->type != "$sub") {
+	if (!is_signed && cell->type != ID($sub)) {
 		int ab_width = std::max(a_width, b_width);
 		y_width = std::min(y_width, ab_width+1);
 	}
@@ -114,7 +114,7 @@ void arith_binary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 
 void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	IdString A = "\\A", Y = "\\Y";
+	IdString A = ID(A), Y = ID(Y);
 
 	int a_width = GetSize(cell->getPort(A));
 
@@ -124,7 +124,7 @@ void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 
 void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	IdString A = "\\A", B = "\\B", Y = "\\Y";
+	IdString A = ID(A), B = ID(B), Y = ID(Y);
 
 	int a_width = GetSize(cell->getPort(A));
 	int b_width = GetSize(cell->getPort(B));
@@ -138,7 +138,7 @@ void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 
 void mux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y";
+	IdString A = ID(A), B = ID(B), S = ID(S), Y = ID(Y);
 
 	int a_width = GetSize(cell->getPort(A));
 	int b_width = GetSize(cell->getPort(B));
@@ -160,43 +160,43 @@ PRIVATE_NAMESPACE_END
 
 bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
 {
-	if (cell->type.in("$not", "$pos")) {
+	if (cell->type.in(ID($not), ID($pos))) {
 		bitwise_unary_op(this, cell);
 		return true;
 	}
 
-	if (cell->type.in("$and", "$or", "$xor", "$xnor")) {
+	if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) {
 		bitwise_binary_op(this, cell);
 		return true;
 	}
 
-	if (cell->type == "$neg") {
+	if (cell->type == ID($neg)) {
 		arith_neg_op(this, cell);
 		return true;
 	}
 
-	if (cell->type.in("$add", "$sub")) {
+	if (cell->type.in(ID($add), ID($sub))) {
 		arith_binary_op(this, cell);
 		return true;
 	}
 
-	if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", "$logic_not")) {
+	if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($logic_not))) {
 		reduce_op(this, cell);
 		return true;
 	}
 
 	// FIXME:
-	// if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) {
+	// if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
 	// 	shift_op(this, cell);
 	// 	return true;
 	// }
 
-	if (cell->type.in("$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt")) {
+	if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) {
 		compare_op(this, cell);
 		return true;
 	}
 
-	if (cell->type.in("$mux", "$pmux")) {
+	if (cell->type.in(ID($mux), ID($pmux))) {
 		mux_op(this, cell);
 		return true;
 	}
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index 1256fbcba..ade305e83 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -84,46 +84,46 @@ struct CellTypes
 	{
 		setup_internals_eval();
 
-		IdString A = "\\A", B = "\\B", EN = "\\EN", Y = "\\Y";
-		IdString SRC = "\\SRC", DST = "\\DST", DAT = "\\DAT";
-		IdString EN_SRC = "\\EN_SRC", EN_DST = "\\EN_DST";
+		IdString A = ID(A), B = ID(B), EN = ID(EN), Y = ID(Y);
+		IdString SRC = ID(SRC), DST = ID(DST), DAT = ID(DAT);
+		IdString EN_SRC = ID(EN_SRC), EN_DST = ID(EN_DST);
 
-		setup_type("$tribuf", {A, EN}, {Y}, true);
+		setup_type(ID($tribuf), {A, EN}, {Y}, true);
 
-		setup_type("$assert", {A, EN}, pool<RTLIL::IdString>(), true);
-		setup_type("$assume", {A, EN}, pool<RTLIL::IdString>(), true);
-		setup_type("$live", {A, EN}, pool<RTLIL::IdString>(), true);
-		setup_type("$fair", {A, EN}, pool<RTLIL::IdString>(), true);
-		setup_type("$cover", {A, EN}, pool<RTLIL::IdString>(), true);
-		setup_type("$initstate", pool<RTLIL::IdString>(), {Y}, true);
-		setup_type("$anyconst", pool<RTLIL::IdString>(), {Y}, true);
-		setup_type("$anyseq", pool<RTLIL::IdString>(), {Y}, true);
-		setup_type("$allconst", pool<RTLIL::IdString>(), {Y}, true);
-		setup_type("$allseq", pool<RTLIL::IdString>(), {Y}, true);
-		setup_type("$equiv", {A, B}, {Y}, true);
-		setup_type("$specify2", {EN, SRC, DST}, pool<RTLIL::IdString>(), true);
-		setup_type("$specify3", {EN, SRC, DST, DAT}, pool<RTLIL::IdString>(), true);
-		setup_type("$specrule", {EN_SRC, EN_DST, SRC, DST}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($assert), {A, EN}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($assume), {A, EN}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($live), {A, EN}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($fair), {A, EN}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($cover), {A, EN}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($initstate), pool<RTLIL::IdString>(), {Y}, true);
+		setup_type(ID($anyconst), pool<RTLIL::IdString>(), {Y}, true);
+		setup_type(ID($anyseq), pool<RTLIL::IdString>(), {Y}, true);
+		setup_type(ID($allconst), pool<RTLIL::IdString>(), {Y}, true);
+		setup_type(ID($allseq), pool<RTLIL::IdString>(), {Y}, true);
+		setup_type(ID($equiv), {A, B}, {Y}, true);
+		setup_type(ID($specify2), {EN, SRC, DST}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($specify3), {EN, SRC, DST, DAT}, pool<RTLIL::IdString>(), true);
+		setup_type(ID($specrule), {EN_SRC, EN_DST, SRC, DST}, pool<RTLIL::IdString>(), true);
 	}
 
 	void setup_internals_eval()
 	{
 		std::vector<RTLIL::IdString> unary_ops = {
-			"$not", "$pos", "$neg",
-			"$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
-			"$logic_not", "$slice", "$lut", "$sop"
+			ID($not), ID($pos), ID($neg),
+			ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
+			ID($logic_not), ID($slice), ID($lut), ID($sop)
 		};
 
 		std::vector<RTLIL::IdString> binary_ops = {
-			"$and", "$or", "$xor", "$xnor",
-			"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
-			"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
-			"$add", "$sub", "$mul", "$div", "$mod", "$pow",
-			"$logic_and", "$logic_or", "$concat", "$macc"
+			ID($and), ID($or), ID($xor), ID($xnor),
+			ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
+			ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
+			ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow),
+			ID($logic_and), ID($logic_or), ID($concat), ID($macc)
 		};
-		IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y";
-		IdString P = "\\P", G = "\\G", C = "\\C", X = "\\X";
-		IdString BI = "\\BI", CI = "\\CI", CO = "\\CO", EN = "\\EN";
+		IdString A = ID(A), B = ID(B), S = ID(S), Y = ID(Y);
+		IdString P = ID(P), G = ID(G), C = ID(C), X = ID(X);
+		IdString BI = ID(BI), CI = ID(CI), CO = ID(CO), EN = ID(EN);
 
 		for (auto type : unary_ops)
 			setup_type(type, {A}, {Y}, true);
@@ -131,27 +131,27 @@ struct CellTypes
 		for (auto type : binary_ops)
 			setup_type(type, {A, B}, {Y}, true);
 
-		for (auto type : std::vector<RTLIL::IdString>({"$mux", "$pmux"}))
+		for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux)}))
 			setup_type(type, {A, B, S}, {Y}, true);
 
-		setup_type("$lcu", {P, G, CI}, {CO}, true);
-		setup_type("$alu", {A, B, CI, BI}, {X, Y, CO}, true);
-		setup_type("$fa", {A, B, C}, {X, Y}, true);
+		setup_type(ID($lcu), {P, G, CI}, {CO}, true);
+		setup_type(ID($alu), {A, B, CI, BI}, {X, Y, CO}, true);
+		setup_type(ID($fa), {A, B, C}, {X, Y}, true);
 	}
 
 	void setup_internals_ff()
 	{
-		IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
-		IdString Q = "\\Q", D = "\\D";
+		IdString SET = ID(SET), CLR = ID(CLR), CLK = ID(CLK), ARST = ID(ARST), EN = ID(EN);
+		IdString Q = ID(Q), D = ID(D);
 
-		setup_type("$sr", {SET, CLR}, {Q});
-		setup_type("$ff", {D}, {Q});
-		setup_type("$dff", {CLK, D}, {Q});
-		setup_type("$dffe", {CLK, EN, D}, {Q});
-		setup_type("$dffsr", {CLK, SET, CLR, D}, {Q});
-		setup_type("$adff", {CLK, ARST, D}, {Q});
-		setup_type("$dlatch", {EN, D}, {Q});
-		setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q});
+		setup_type(ID($sr), {SET, CLR}, {Q});
+		setup_type(ID($ff), {D}, {Q});
+		setup_type(ID($dff), {CLK, D}, {Q});
+		setup_type(ID($dffe), {CLK, EN, D}, {Q});
+		setup_type(ID($dffsr), {CLK, SET, CLR, D}, {Q});
+		setup_type(ID($adff), {CLK, ARST, D}, {Q});
+		setup_type(ID($dlatch), {EN, D}, {Q});
+		setup_type(ID($dlatchsr), {EN, SET, CLR, D}, {Q});
 
 	}
 
@@ -159,63 +159,63 @@ struct CellTypes
 	{
 		setup_internals_ff();
 
-		IdString CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
-		IdString ADDR = "\\ADDR", DATA = "\\DATA", RD_EN = "\\RD_EN";
-		IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN";
-		IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA";
-		IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT";
+		IdString CLK = ID(CLK), ARST = ID(ARST), EN = ID(EN);
+		IdString ADDR = ID(ADDR), DATA = ID(DATA), RD_EN = ID(RD_EN);
+		IdString RD_CLK = ID(RD_CLK), RD_ADDR = ID(RD_ADDR), WR_CLK = ID(WR_CLK), WR_EN = ID(WR_EN);
+		IdString WR_ADDR = ID(WR_ADDR), WR_DATA = ID(WR_DATA), RD_DATA = ID(RD_DATA);
+		IdString CTRL_IN = ID(CTRL_IN), CTRL_OUT = ID(CTRL_OUT);
 
-		setup_type("$memrd", {CLK, EN, ADDR}, {DATA});
-		setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
-		setup_type("$meminit", {ADDR, DATA}, pool<RTLIL::IdString>());
-		setup_type("$mem", {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
+		setup_type(ID($memrd), {CLK, EN, ADDR}, {DATA});
+		setup_type(ID($memwr), {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
+		setup_type(ID($meminit), {ADDR, DATA}, pool<RTLIL::IdString>());
+		setup_type(ID($mem), {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
 
-		setup_type("$fsm", {CLK, ARST, CTRL_IN}, {CTRL_OUT});
+		setup_type(ID($fsm), {CLK, ARST, CTRL_IN}, {CTRL_OUT});
 	}
 
 	void setup_stdcells()
 	{
 		setup_stdcells_eval();
 
-		IdString A = "\\A", E = "\\E", Y = "\\Y";
+		IdString A = ID(A), E = ID(E), Y = ID(Y);
 
-		setup_type("$_TBUF_", {A, E}, {Y}, true);
+		setup_type(ID($_TBUF_), {A, E}, {Y}, true);
 	}
 
 	void setup_stdcells_eval()
 	{
-		IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D";
-		IdString E = "\\E", F = "\\F", G = "\\G", H = "\\H";
-		IdString I = "\\I", J = "\\J", K = "\\K", L = "\\L";
-		IdString M = "\\M", N = "\\N", O = "\\O", P = "\\P";
-		IdString S = "\\S", T = "\\T", U = "\\U", V = "\\V";
-		IdString Y = "\\Y";
+		IdString A = ID(A), B = ID(B), C = ID(C), D = ID(D);
+		IdString E = ID(E), F = ID(F), G = ID(G), H = ID(H);
+		IdString I = ID(I), J = ID(J), K = ID(K), L = ID(L);
+		IdString M = ID(M), N = ID(N), O = ID(O), P = ID(P);
+		IdString S = ID(S), T = ID(T), U = ID(U), V = ID(V);
+		IdString Y = ID(Y);
 
-		setup_type("$_BUF_", {A}, {Y}, true);
-		setup_type("$_NOT_", {A}, {Y}, true);
-		setup_type("$_AND_", {A, B}, {Y}, true);
-		setup_type("$_NAND_", {A, B}, {Y}, true);
-		setup_type("$_OR_",  {A, B}, {Y}, true);
-		setup_type("$_NOR_",  {A, B}, {Y}, true);
-		setup_type("$_XOR_", {A, B}, {Y}, true);
-		setup_type("$_XNOR_", {A, B}, {Y}, true);
-		setup_type("$_ANDNOT_", {A, B}, {Y}, true);
-		setup_type("$_ORNOT_", {A, B}, {Y}, true);
-		setup_type("$_MUX_", {A, B, S}, {Y}, true);
-		setup_type("$_NMUX_", {A, B, S}, {Y}, true);
-		setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true);
-		setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
-		setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
-		setup_type("$_AOI3_", {A, B, C}, {Y}, true);
-		setup_type("$_OAI3_", {A, B, C}, {Y}, true);
-		setup_type("$_AOI4_", {A, B, C, D}, {Y}, true);
-		setup_type("$_OAI4_", {A, B, C, D}, {Y}, true);
+		setup_type(ID($_BUF_), {A}, {Y}, true);
+		setup_type(ID($_NOT_), {A}, {Y}, true);
+		setup_type(ID($_AND_), {A, B}, {Y}, true);
+		setup_type(ID($_NAND_), {A, B}, {Y}, true);
+		setup_type(ID($_OR_),  {A, B}, {Y}, true);
+		setup_type(ID($_NOR_),  {A, B}, {Y}, true);
+		setup_type(ID($_XOR_), {A, B}, {Y}, true);
+		setup_type(ID($_XNOR_), {A, B}, {Y}, true);
+		setup_type(ID($_ANDNOT_), {A, B}, {Y}, true);
+		setup_type(ID($_ORNOT_), {A, B}, {Y}, true);
+		setup_type(ID($_MUX_), {A, B, S}, {Y}, true);
+		setup_type(ID($_NMUX_), {A, B, S}, {Y}, true);
+		setup_type(ID($_MUX4_), {A, B, C, D, S, T}, {Y}, true);
+		setup_type(ID($_MUX8_), {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
+		setup_type(ID($_MUX16_), {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
+		setup_type(ID($_AOI3_), {A, B, C}, {Y}, true);
+		setup_type(ID($_OAI3_), {A, B, C}, {Y}, true);
+		setup_type(ID($_AOI4_), {A, B, C, D}, {Y}, true);
+		setup_type(ID($_OAI4_), {A, B, C, D}, {Y}, true);
 	}
 
 	void setup_stdcells_mem()
 	{
-		IdString S = "\\S", R = "\\R", C = "\\C";
-		IdString D = "\\D", Q = "\\Q", E = "\\E";
+		IdString S = ID(S), R = ID(R), C = ID(C);
+		IdString D = ID(D), Q = ID(Q), E = ID(E);
 
 		std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'};
 
@@ -223,7 +223,7 @@ struct CellTypes
 		for (auto c2 : list_np)
 			setup_type(stringf("$_SR_%c%c_", c1, c2), {S, R}, {Q});
 
-		setup_type("$_FF_", {D}, {Q});
+		setup_type(ID($_FF_), {D}, {Q});
 
 		for (auto c1 : list_np)
 			setup_type(stringf("$_DFF_%c_", c1), {C, D}, {Q});
@@ -289,13 +289,13 @@ struct CellTypes
 
 	static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr)
 	{
-		if (type == "$sshr" && !signed1)
-			type = "$shr";
-		if (type == "$sshl" && !signed1)
-			type = "$shl";
+		if (type == ID($sshr) && !signed1)
+			type = ID($shr);
+		if (type == ID($sshl) && !signed1)
+			type = ID($shl);
 
-		if (type != "$sshr" && type != "$sshl" && type != "$shr" && type != "$shl" && type != "$shift" && type != "$shiftx" &&
-				type != "$pos" && type != "$neg" && type != "$not") {
+		if (type != ID($sshr) && type != ID($sshl) && type != ID($shr) && type != ID($shl) && type != ID($shift) && type != ID($shiftx) &&
+				type != ID($pos) && type != ID($neg) && type != ID($not)) {
 			if (!signed1 || !signed2)
 				signed1 = false, signed2 = false;
 		}
@@ -338,25 +338,25 @@ struct CellTypes
 		HANDLE_CELL_TYPE(neg)
 #undef HANDLE_CELL_TYPE
 
-		if (type == "$_BUF_")
+		if (type == ID($_BUF_))
 			return arg1;
-		if (type == "$_NOT_")
+		if (type == ID($_NOT_))
 			return eval_not(arg1);
-		if (type == "$_AND_")
+		if (type == ID($_AND_))
 			return const_and(arg1, arg2, false, false, 1);
-		if (type == "$_NAND_")
+		if (type == ID($_NAND_))
 			return eval_not(const_and(arg1, arg2, false, false, 1));
-		if (type == "$_OR_")
+		if (type == ID($_OR_))
 			return const_or(arg1, arg2, false, false, 1);
-		if (type == "$_NOR_")
+		if (type == ID($_NOR_))
 			return eval_not(const_or(arg1, arg2, false, false, 1));
-		if (type == "$_XOR_")
+		if (type == ID($_XOR_))
 			return const_xor(arg1, arg2, false, false, 1);
-		if (type == "$_XNOR_")
+		if (type == ID($_XNOR_))
 			return const_xnor(arg1, arg2, false, false, 1);
-		if (type == "$_ANDNOT_")
+		if (type == ID($_ANDNOT_))
 			return const_and(arg1, eval_not(arg2), false, false, 1);
-		if (type == "$_ORNOT_")
+		if (type == ID($_ORNOT_))
 			return const_or(arg1, eval_not(arg2), false, false, 1);
 
 		if (errp != nullptr) {
@@ -369,25 +369,25 @@ struct CellTypes
 
 	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr)
 	{
-		if (cell->type == "$slice") {
+		if (cell->type == ID($slice)) {
 			RTLIL::Const ret;
-			int width = cell->parameters.at("\\Y_WIDTH").as_int();
-			int offset = cell->parameters.at("\\OFFSET").as_int();
+			int width = cell->parameters.at(ID(Y_WIDTH)).as_int();
+			int offset = cell->parameters.at(ID(OFFSET)).as_int();
 			ret.bits.insert(ret.bits.end(), arg1.bits.begin()+offset, arg1.bits.begin()+offset+width);
 			return ret;
 		}
 
-		if (cell->type == "$concat") {
+		if (cell->type == ID($concat)) {
 			RTLIL::Const ret = arg1;
 			ret.bits.insert(ret.bits.end(), arg2.bits.begin(), arg2.bits.end());
 			return ret;
 		}
 
-		if (cell->type == "$lut")
+		if (cell->type == ID($lut))
 		{
-			int width = cell->parameters.at("\\WIDTH").as_int();
+			int width = cell->parameters.at(ID(WIDTH)).as_int();
 
-			std::vector<RTLIL::State> t = cell->parameters.at("\\LUT").bits;
+			std::vector<RTLIL::State> t = cell->parameters.at(ID(LUT)).bits;
 			while (GetSize(t) < (1 << width))
 				t.push_back(State::S0);
 			t.resize(1 << width);
@@ -409,11 +409,11 @@ struct CellTypes
 			return t;
 		}
 
-		if (cell->type == "$sop")
+		if (cell->type == ID($sop))
 		{
-			int width = cell->parameters.at("\\WIDTH").as_int();
-			int depth = cell->parameters.at("\\DEPTH").as_int();
-			std::vector<RTLIL::State> t = cell->parameters.at("\\TABLE").bits;
+			int width = cell->parameters.at(ID(WIDTH)).as_int();
+			int depth = cell->parameters.at(ID(DEPTH)).as_int();
+			std::vector<RTLIL::State> t = cell->parameters.at(ID(TABLE)).bits;
 
 			while (GetSize(t) < width*depth*2)
 				t.push_back(State::S0);
@@ -447,15 +447,15 @@ struct CellTypes
 			return default_ret;
 		}
 
-		bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
-		bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
-		int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
+		bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool();
+		bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool();
+		int result_len = cell->parameters.count(ID(Y_WIDTH)) > 0 ? cell->parameters[ID(Y_WIDTH)].as_int() : -1;
 		return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp);
 	}
 
 	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
 	{
-		if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
+		if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
 			RTLIL::Const ret = arg1;
 			for (size_t i = 0; i < arg3.bits.size(); i++)
 				if (arg3.bits[i] == RTLIL::State::S1) {
@@ -465,9 +465,9 @@ struct CellTypes
 			return ret;
 		}
 
-		if (cell->type == "$_AOI3_")
+		if (cell->type == ID($_AOI3_))
 			return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
-		if (cell->type == "$_OAI3_")
+		if (cell->type == ID($_OAI3_))
 			return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
 
 		log_assert(arg3.bits.size() == 0);
@@ -476,9 +476,9 @@ struct CellTypes
 
 	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4, bool *errp = nullptr)
 	{
-		if (cell->type == "$_AOI4_")
+		if (cell->type == ID($_AOI4_))
 			return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
-		if (cell->type == "$_OAI4_")
+		if (cell->type == ID($_OAI4_))
 			return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_or(arg3, arg4, false, false, 1), false, false, 1));
 
 		log_assert(arg4.bits.size() == 0);
diff --git a/kernel/consteval.h b/kernel/consteval.h
index 521ce96d4..09b4c434b 100644
--- a/kernel/consteval.h
+++ b/kernel/consteval.h
@@ -89,12 +89,12 @@ struct ConstEval
 
 	bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef)
 	{
-		if (cell->type == "$lcu")
+		if (cell->type == ID($lcu))
 		{
-			RTLIL::SigSpec sig_p = cell->getPort("\\P");
-			RTLIL::SigSpec sig_g = cell->getPort("\\G");
-			RTLIL::SigSpec sig_ci = cell->getPort("\\CI");
-			RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort("\\CO")));
+			RTLIL::SigSpec sig_p = cell->getPort(ID(P));
+			RTLIL::SigSpec sig_g = cell->getPort(ID(G));
+			RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
+			RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort(ID(CO))));
 
 			if (sig_co.is_fully_const())
 				return true;
@@ -128,24 +128,24 @@ struct ConstEval
 
 		RTLIL::SigSpec sig_a, sig_b, sig_s, sig_y;
 
-		log_assert(cell->hasPort("\\Y"));
-		sig_y = values_map(assign_map(cell->getPort("\\Y")));
+		log_assert(cell->hasPort(ID(Y)));
+		sig_y = values_map(assign_map(cell->getPort(ID(Y))));
 		if (sig_y.is_fully_const())
 			return true;
 
-		if (cell->hasPort("\\S")) {
-			sig_s = cell->getPort("\\S");
+		if (cell->hasPort(ID(S))) {
+			sig_s = cell->getPort(ID(S));
 			if (!eval(sig_s, undef, cell))
 				return false;
 		}
 
-		if (cell->hasPort("\\A"))
-			sig_a = cell->getPort("\\A");
+		if (cell->hasPort(ID(A)))
+			sig_a = cell->getPort(ID(A));
 
-		if (cell->hasPort("\\B"))
-			sig_b = cell->getPort("\\B");
+		if (cell->hasPort(ID(B)))
+			sig_b = cell->getPort(ID(B));
 
-		if (cell->type.in("$mux", "$pmux", "$_MUX_", "$_NMUX_"))
+		if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_NMUX_)))
 		{
 			std::vector<RTLIL::SigSpec> y_candidates;
 			int count_maybe_set_s_bits = 0;
@@ -175,7 +175,7 @@ struct ConstEval
 			for (auto &yc : y_candidates) {
 				if (!eval(yc, undef, cell))
 					return false;
-				if (cell->type == "$_NMUX_")
+				if (cell->type == ID($_NMUX_))
 					y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc)));
 				else
 					y_values.push_back(yc.as_const());
@@ -198,10 +198,10 @@ struct ConstEval
 			else
 				set(sig_y, y_values.front());
 		}
-		else if (cell->type == "$fa")
+		else if (cell->type == ID($fa))
 		{
-			RTLIL::SigSpec sig_c = cell->getPort("\\C");
-			RTLIL::SigSpec sig_x = cell->getPort("\\X");
+			RTLIL::SigSpec sig_c = cell->getPort(ID(C));
+			RTLIL::SigSpec sig_x = cell->getPort(ID(X));
 			int width = GetSize(sig_c);
 
 			if (!eval(sig_a, undef, cell))
@@ -227,13 +227,13 @@ struct ConstEval
 			set(sig_y, val_y);
 			set(sig_x, val_x);
 		}
-		else if (cell->type == "$alu")
+		else if (cell->type == ID($alu))
 		{
-			bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
-			bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
+			bool signed_a = cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool();
+			bool signed_b = cell->parameters.count(ID(B_SIGNED)) > 0 && cell->parameters[ID(B_SIGNED)].as_bool();
 
-			RTLIL::SigSpec sig_ci = cell->getPort("\\CI");
-			RTLIL::SigSpec sig_bi = cell->getPort("\\BI");
+			RTLIL::SigSpec sig_ci = cell->getPort(ID(CI));
+			RTLIL::SigSpec sig_bi = cell->getPort(ID(BI));
 
 			if (!eval(sig_a, undef, cell))
 				return false;
@@ -247,8 +247,8 @@ struct ConstEval
 			if (!eval(sig_bi, undef, cell))
 				return false;
 
-			RTLIL::SigSpec sig_x = cell->getPort("\\X");
-			RTLIL::SigSpec sig_co = cell->getPort("\\CO");
+			RTLIL::SigSpec sig_x = cell->getPort(ID(X));
+			RTLIL::SigSpec sig_co = cell->getPort(ID(CO));
 
 			bool any_input_undef = !(sig_a.is_fully_def() && sig_b.is_fully_def() && sig_ci.is_fully_def() && sig_bi.is_fully_def());
 			sig_a.extend_u0(GetSize(sig_y), signed_a);
@@ -283,7 +283,7 @@ struct ConstEval
 				}
 			}
 		}
-		else if (cell->type == "$macc")
+		else if (cell->type == ID($macc))
 		{
 			Macc macc;
 			macc.from_cell(cell);
@@ -298,21 +298,21 @@ struct ConstEval
 					return false;
 			}
 
-			RTLIL::Const result(0, GetSize(cell->getPort("\\Y")));
+			RTLIL::Const result(0, GetSize(cell->getPort(ID(Y))));
 			if (!macc.eval(result))
 				log_abort();
 
-			set(cell->getPort("\\Y"), result);
+			set(cell->getPort(ID(Y)), result);
 		}
 		else
 		{
 			RTLIL::SigSpec sig_c, sig_d;
 
-			if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) {
-				if (cell->hasPort("\\C"))
-					sig_c = cell->getPort("\\C");
-				if (cell->hasPort("\\D"))
-					sig_d = cell->getPort("\\D");
+			if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) {
+				if (cell->hasPort(ID(C)))
+					sig_c = cell->getPort(ID(C));
+				if (cell->hasPort(ID(D)))
+					sig_d = cell->getPort(ID(D));
 			}
 
 			if (sig_a.size() > 0 && !eval(sig_a, undef, cell))
diff --git a/kernel/cost.h b/kernel/cost.h
index 10fa50fb3..ea2a4c1f0 100644
--- a/kernel/cost.h
+++ b/kernel/cost.h
@@ -28,44 +28,44 @@ struct CellCosts
 {
 	static const dict<RTLIL::IdString, int>& default_gate_cost() {
 		static const dict<RTLIL::IdString, int> db = {
-			{ "$_BUF_",    1 },
-			{ "$_NOT_",    2 },
-			{ "$_AND_",    4 },
-			{ "$_NAND_",   4 },
-			{ "$_OR_",     4 },
-			{ "$_NOR_",    4 },
-			{ "$_ANDNOT_", 4 },
-			{ "$_ORNOT_",  4 },
-			{ "$_XOR_",    5 },
-			{ "$_XNOR_",   5 },
-			{ "$_AOI3_",   6 },
-			{ "$_OAI3_",   6 },
-			{ "$_AOI4_",   7 },
-			{ "$_OAI4_",   7 },
-			{ "$_MUX_",    4 },
-			{ "$_NMUX_",   4 }
+			{ ID($_BUF_),    1 },
+			{ ID($_NOT_),    2 },
+			{ ID($_AND_),    4 },
+			{ ID($_NAND_),   4 },
+			{ ID($_OR_),     4 },
+			{ ID($_NOR_),    4 },
+			{ ID($_ANDNOT_), 4 },
+			{ ID($_ORNOT_),  4 },
+			{ ID($_XOR_),    5 },
+			{ ID($_XNOR_),   5 },
+			{ ID($_AOI3_),   6 },
+			{ ID($_OAI3_),   6 },
+			{ ID($_AOI4_),   7 },
+			{ ID($_OAI4_),   7 },
+			{ ID($_MUX_),    4 },
+			{ ID($_NMUX_),   4 }
 		};
 		return db;
 	}
 
 	static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
 		static const dict<RTLIL::IdString, int> db = {
-			{ "$_BUF_",     1 },
-			{ "$_NOT_",     2 },
-			{ "$_AND_",     6 },
-			{ "$_NAND_",    4 },
-			{ "$_OR_",      6 },
-			{ "$_NOR_",     4 },
-			{ "$_ANDNOT_",  6 },
-			{ "$_ORNOT_",   6 },
-			{ "$_XOR_",    12 },
-			{ "$_XNOR_",   12 },
-			{ "$_AOI3_",    6 },
-			{ "$_OAI3_",    6 },
-			{ "$_AOI4_",    8 },
-			{ "$_OAI4_",    8 },
-			{ "$_MUX_",    12 },
-			{ "$_NMUX_",   10 }
+			{ ID($_BUF_),     1 },
+			{ ID($_NOT_),     2 },
+			{ ID($_AND_),     6 },
+			{ ID($_NAND_),    4 },
+			{ ID($_OR_),      6 },
+			{ ID($_NOR_),     4 },
+			{ ID($_ANDNOT_),  6 },
+			{ ID($_ORNOT_),   6 },
+			{ ID($_XOR_),    12 },
+			{ ID($_XNOR_),   12 },
+			{ ID($_AOI3_),    6 },
+			{ ID($_OAI3_),    6 },
+			{ ID($_AOI4_),    8 },
+			{ ID($_OAI4_),    8 },
+			{ ID($_MUX_),    12 },
+			{ ID($_NMUX_),   10 }
 		};
 		return db;
 	}
@@ -92,8 +92,8 @@ struct CellCosts
 		{
 			RTLIL::Module *mod = design->module(cell->type);
 
-			if (mod->attributes.count("\\cost"))
-				return mod->attributes.at("\\cost").as_int();
+			if (mod->attributes.count(ID(cost)))
+				return mod->attributes.at(ID(cost)).as_int();
 
 			if (mod_cost_cache.count(mod->name))
 				return mod_cost_cache.at(mod->name);
diff --git a/kernel/macc.h b/kernel/macc.h
index c7595ebc1..e07e7e01a 100644
--- a/kernel/macc.h
+++ b/kernel/macc.h
@@ -99,16 +99,16 @@ struct Macc
 
 	void from_cell(RTLIL::Cell *cell)
 	{
-		RTLIL::SigSpec port_a = cell->getPort("\\A");
+		RTLIL::SigSpec port_a = cell->getPort(ID(A));
 
 		ports.clear();
-		bit_ports = cell->getPort("\\B");
+		bit_ports = cell->getPort(ID(B));
 
-		std::vector<RTLIL::State> config_bits = cell->getParam("\\CONFIG").bits;
+		std::vector<RTLIL::State> config_bits = cell->getParam(ID(CONFIG)).bits;
 		int config_cursor = 0;
 
 #ifndef NDEBUG
-		int config_width = cell->getParam("\\CONFIG_WIDTH").as_int();
+		int config_width = cell->getParam(ID(CONFIG_WIDTH)).as_int();
 		log_assert(GetSize(config_bits) >= config_width);
 #endif
 
@@ -191,12 +191,12 @@ struct Macc
 			port_a.append(port.in_b);
 		}
 
-		cell->setPort("\\A", port_a);
-		cell->setPort("\\B", bit_ports);
-		cell->setParam("\\CONFIG", config_bits);
-		cell->setParam("\\CONFIG_WIDTH", GetSize(config_bits));
-		cell->setParam("\\A_WIDTH", GetSize(port_a));
-		cell->setParam("\\B_WIDTH", GetSize(bit_ports));
+		cell->setPort(ID(A), port_a);
+		cell->setPort(ID(B), bit_ports);
+		cell->setParam(ID(CONFIG), config_bits);
+		cell->setParam(ID(CONFIG_WIDTH), GetSize(config_bits));
+		cell->setParam(ID(A_WIDTH), GetSize(port_a));
+		cell->setParam(ID(B_WIDTH), GetSize(bit_ports));
 	}
 
 	bool eval(RTLIL::Const &result) const
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index fade0bc36..d01bd0c62 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -29,12 +29,23 @@
 YOSYS_NAMESPACE_BEGIN
 
 RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard;
-std::vector<int> RTLIL::IdString::global_refcount_storage_;
 std::vector<char*> RTLIL::IdString::global_id_storage_;
 dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_;
+#ifndef YOSYS_NO_IDS_REFCNT
+std::vector<int> RTLIL::IdString::global_refcount_storage_;
 std::vector<int> RTLIL::IdString::global_free_idx_list_;
+#endif
+#ifdef YOSYS_USE_STICKY_IDS
 int RTLIL::IdString::last_created_idx_[8];
 int RTLIL::IdString::last_created_idx_ptr_;
+#endif
+
+IdString RTLIL::ID::A;
+IdString RTLIL::ID::B;
+IdString RTLIL::ID::Y;
+IdString RTLIL::ID::keep;
+IdString RTLIL::ID::whitebox;
+IdString RTLIL::ID::blackbox;
 
 RTLIL::Const::Const()
 {
@@ -264,16 +275,16 @@ pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const
 void RTLIL::AttrObject::set_src_attribute(const std::string &src)
 {
 	if (src.empty())
-		attributes.erase("\\src");
+		attributes.erase(ID(src));
 	else
-		attributes["\\src"] = src;
+		attributes[ID(src)] = src;
 }
 
 std::string RTLIL::AttrObject::get_src_attribute() const
 {
 	std::string src;
-	if (attributes.count("\\src"))
-		src = attributes.at("\\src").decode_string();
+	if (attributes.count(ID(src)))
+		src = attributes.at(ID(src)).decode_string();
 	return src;
 }
 
@@ -417,7 +428,7 @@ RTLIL::Module *RTLIL::Design::top_module()
 	int module_count = 0;
 
 	for (auto mod : selected_modules()) {
-		if (mod->get_bool_attribute("\\top"))
+		if (mod->get_bool_attribute(ID(top)))
 			return mod;
 		module_count++;
 		module = mod;
@@ -706,7 +717,7 @@ void RTLIL::Module::makeblackbox()
 	processes.clear();
 
 	remove(delwires);
-	set_bool_attribute("\\blackbox");
+	set_bool_attribute(ID(blackbox));
 }
 
 void RTLIL::Module::reprocess_module(RTLIL::Design *, dict<RTLIL::IdString, RTLIL::Module *>)
@@ -754,7 +765,7 @@ namespace {
 					cell->name.c_str(), cell->type.c_str(), __FILE__, linenr, buf.str().c_str());
 		}
 
-		int param(const char *name)
+		int param(RTLIL::IdString name)
 		{
 			if (cell->parameters.count(name) == 0)
 				error(__LINE__);
@@ -762,7 +773,7 @@ namespace {
 			return cell->parameters.at(name).as_int();
 		}
 
-		int param_bool(const char *name)
+		int param_bool(RTLIL::IdString name)
 		{
 			int v = param(name);
 			if (cell->parameters.at(name).bits.size() > 32)
@@ -772,14 +783,14 @@ namespace {
 			return v;
 		}
 
-		void param_bits(const char *name, int width)
+		void param_bits(RTLIL::IdString name, int width)
 		{
 			param(name);
 			if (int(cell->parameters.at(name).bits.size()) != width)
 				error(__LINE__);
 		}
 
-		void port(const char *name, int width)
+		void port(RTLIL::IdString name, int width)
 		{
 			if (!cell->hasPort(name))
 				error(__LINE__);
@@ -797,9 +808,9 @@ namespace {
 				if (expected_ports.count(conn.first) == 0)
 					error(__LINE__);
 
-			if (expected_params.count("\\A_SIGNED") != 0 && expected_params.count("\\B_SIGNED") && check_matched_sign) {
-				bool a_is_signed = param("\\A_SIGNED") != 0;
-				bool b_is_signed = param("\\B_SIGNED") != 0;
+			if (expected_params.count(ID(A_SIGNED)) != 0 && expected_params.count(ID(B_SIGNED)) && check_matched_sign) {
+				bool a_is_signed = param(ID(A_SIGNED)) != 0;
+				bool b_is_signed = param(ID(B_SIGNED)) != 0;
 				if (a_is_signed != b_is_signed)
 					error(__LINE__);
 			}
@@ -832,478 +843,478 @@ namespace {
 					cell->type.begins_with("$verific$") || cell->type.begins_with("$array:") || cell->type.begins_with("$extern:"))
 				return;
 
-			if (cell->type.in("$not", "$pos", "$neg")) {
-				param_bool("\\A_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type.in(ID($not), ID($pos), ID($neg))) {
+				param_bool(ID(A_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$and", "$or", "$xor", "$xnor")) {
-				param_bool("\\A_SIGNED");
-				param_bool("\\B_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor))) {
+				param_bool(ID(A_SIGNED));
+				param_bool(ID(B_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool")) {
-				param_bool("\\A_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool))) {
+				param_bool(ID(A_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) {
-				param_bool("\\A_SIGNED");
-				param_bool("\\B_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
+				param_bool(ID(A_SIGNED));
+				param_bool(ID(B_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected(false);
 				return;
 			}
 
-			if (cell->type.in("$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt")) {
-				param_bool("\\A_SIGNED");
-				param_bool("\\B_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt))) {
+				param_bool(ID(A_SIGNED));
+				param_bool(ID(B_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$pow")) {
-				param_bool("\\A_SIGNED");
-				param_bool("\\B_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
-				check_expected(cell->type != "$pow");
+			if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) {
+				param_bool(ID(A_SIGNED));
+				param_bool(ID(B_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
+				check_expected(cell->type != ID($pow));
 				return;
 			}
 
-			if (cell->type == "$fa") {
-				port("\\A", param("\\WIDTH"));
-				port("\\B", param("\\WIDTH"));
-				port("\\C", param("\\WIDTH"));
-				port("\\X", param("\\WIDTH"));
-				port("\\Y", param("\\WIDTH"));
+			if (cell->type == ID($fa)) {
+				port(ID(A), param(ID(WIDTH)));
+				port(ID(B), param(ID(WIDTH)));
+				port(ID(C), param(ID(WIDTH)));
+				port(ID(X), param(ID(WIDTH)));
+				port(ID(Y), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$lcu") {
-				port("\\P", param("\\WIDTH"));
-				port("\\G", param("\\WIDTH"));
-				port("\\CI", 1);
-				port("\\CO", param("\\WIDTH"));
+			if (cell->type == ID($lcu)) {
+				port(ID(P), param(ID(WIDTH)));
+				port(ID(G), param(ID(WIDTH)));
+				port(ID(CI), 1);
+				port(ID(CO), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$alu") {
-				param_bool("\\A_SIGNED");
-				param_bool("\\B_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\CI", 1);
-				port("\\BI", 1);
-				port("\\X", param("\\Y_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
-				port("\\CO", param("\\Y_WIDTH"));
+			if (cell->type == ID($alu)) {
+				param_bool(ID(A_SIGNED));
+				param_bool(ID(B_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(CI), 1);
+				port(ID(BI), 1);
+				port(ID(X), param(ID(Y_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
+				port(ID(CO), param(ID(Y_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$macc") {
-				param("\\CONFIG");
-				param("\\CONFIG_WIDTH");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type == ID($macc)) {
+				param(ID(CONFIG));
+				param(ID(CONFIG_WIDTH));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected();
 				Macc().from_cell(cell);
 				return;
 			}
 
-			if (cell->type == "$logic_not") {
-				param_bool("\\A_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type == ID($logic_not)) {
+				param_bool(ID(A_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$logic_and", "$logic_or")) {
-				param_bool("\\A_SIGNED");
-				param_bool("\\B_SIGNED");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
+			if (cell->type.in(ID($logic_and), ID($logic_or))) {
+				param_bool(ID(A_SIGNED));
+				param_bool(ID(B_SIGNED));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
 				check_expected(false);
 				return;
 			}
 
-			if (cell->type == "$slice") {
-				param("\\OFFSET");
-				port("\\A", param("\\A_WIDTH"));
-				port("\\Y", param("\\Y_WIDTH"));
-				if (param("\\OFFSET") + param("\\Y_WIDTH") > param("\\A_WIDTH"))
+			if (cell->type == ID($slice)) {
+				param(ID(OFFSET));
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(Y), param(ID(Y_WIDTH)));
+				if (param(ID(OFFSET)) + param(ID(Y_WIDTH)) > param(ID(A_WIDTH)))
 					error(__LINE__);
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$concat") {
-				port("\\A", param("\\A_WIDTH"));
-				port("\\B", param("\\B_WIDTH"));
-				port("\\Y", param("\\A_WIDTH") + param("\\B_WIDTH"));
+			if (cell->type == ID($concat)) {
+				port(ID(A), param(ID(A_WIDTH)));
+				port(ID(B), param(ID(B_WIDTH)));
+				port(ID(Y), param(ID(A_WIDTH)) + param(ID(B_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$mux") {
-				port("\\A", param("\\WIDTH"));
-				port("\\B", param("\\WIDTH"));
-				port("\\S", 1);
-				port("\\Y", param("\\WIDTH"));
+			if (cell->type == ID($mux)) {
+				port(ID(A), param(ID(WIDTH)));
+				port(ID(B), param(ID(WIDTH)));
+				port(ID(S), 1);
+				port(ID(Y), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$pmux") {
-				port("\\A", param("\\WIDTH"));
-				port("\\B", param("\\WIDTH") * param("\\S_WIDTH"));
-				port("\\S", param("\\S_WIDTH"));
-				port("\\Y", param("\\WIDTH"));
+			if (cell->type == ID($pmux)) {
+				port(ID(A), param(ID(WIDTH)));
+				port(ID(B), param(ID(WIDTH)) * param(ID(S_WIDTH)));
+				port(ID(S), param(ID(S_WIDTH)));
+				port(ID(Y), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$lut") {
-				param("\\LUT");
-				port("\\A", param("\\WIDTH"));
-				port("\\Y", 1);
+			if (cell->type == ID($lut)) {
+				param(ID(LUT));
+				port(ID(A), param(ID(WIDTH)));
+				port(ID(Y), 1);
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$sop") {
-				param("\\DEPTH");
-				param("\\TABLE");
-				port("\\A", param("\\WIDTH"));
-				port("\\Y", 1);
+			if (cell->type == ID($sop)) {
+				param(ID(DEPTH));
+				param(ID(TABLE));
+				port(ID(A), param(ID(WIDTH)));
+				port(ID(Y), 1);
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$sr") {
-				param_bool("\\SET_POLARITY");
-				param_bool("\\CLR_POLARITY");
-				port("\\SET", param("\\WIDTH"));
-				port("\\CLR", param("\\WIDTH"));
-				port("\\Q",   param("\\WIDTH"));
+			if (cell->type == ID($sr)) {
+				param_bool(ID(SET_POLARITY));
+				param_bool(ID(CLR_POLARITY));
+				port(ID(SET), param(ID(WIDTH)));
+				port(ID(CLR), param(ID(WIDTH)));
+				port(ID(Q),   param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$ff") {
-				port("\\D", param("\\WIDTH"));
-				port("\\Q", param("\\WIDTH"));
+			if (cell->type == ID($ff)) {
+				port(ID(D), param(ID(WIDTH)));
+				port(ID(Q), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$dff") {
-				param_bool("\\CLK_POLARITY");
-				port("\\CLK", 1);
-				port("\\D", param("\\WIDTH"));
-				port("\\Q", param("\\WIDTH"));
+			if (cell->type == ID($dff)) {
+				param_bool(ID(CLK_POLARITY));
+				port(ID(CLK), 1);
+				port(ID(D), param(ID(WIDTH)));
+				port(ID(Q), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$dffe") {
-				param_bool("\\CLK_POLARITY");
-				param_bool("\\EN_POLARITY");
-				port("\\CLK", 1);
-				port("\\EN", 1);
-				port("\\D", param("\\WIDTH"));
-				port("\\Q", param("\\WIDTH"));
+			if (cell->type == ID($dffe)) {
+				param_bool(ID(CLK_POLARITY));
+				param_bool(ID(EN_POLARITY));
+				port(ID(CLK), 1);
+				port(ID(EN), 1);
+				port(ID(D), param(ID(WIDTH)));
+				port(ID(Q), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$dffsr") {
-				param_bool("\\CLK_POLARITY");
-				param_bool("\\SET_POLARITY");
-				param_bool("\\CLR_POLARITY");
-				port("\\CLK", 1);
-				port("\\SET", param("\\WIDTH"));
-				port("\\CLR", param("\\WIDTH"));
-				port("\\D", param("\\WIDTH"));
-				port("\\Q", param("\\WIDTH"));
+			if (cell->type == ID($dffsr)) {
+				param_bool(ID(CLK_POLARITY));
+				param_bool(ID(SET_POLARITY));
+				param_bool(ID(CLR_POLARITY));
+				port(ID(CLK), 1);
+				port(ID(SET), param(ID(WIDTH)));
+				port(ID(CLR), param(ID(WIDTH)));
+				port(ID(D), param(ID(WIDTH)));
+				port(ID(Q), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$adff") {
-				param_bool("\\CLK_POLARITY");
-				param_bool("\\ARST_POLARITY");
-				param_bits("\\ARST_VALUE", param("\\WIDTH"));
-				port("\\CLK", 1);
-				port("\\ARST", 1);
-				port("\\D", param("\\WIDTH"));
-				port("\\Q", param("\\WIDTH"));
+			if (cell->type == ID($adff)) {
+				param_bool(ID(CLK_POLARITY));
+				param_bool(ID(ARST_POLARITY));
+				param_bits(ID(ARST_VALUE), param(ID(WIDTH)));
+				port(ID(CLK), 1);
+				port(ID(ARST), 1);
+				port(ID(D), param(ID(WIDTH)));
+				port(ID(Q), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$dlatch") {
-				param_bool("\\EN_POLARITY");
-				port("\\EN", 1);
-				port("\\D", param("\\WIDTH"));
-				port("\\Q", param("\\WIDTH"));
+			if (cell->type == ID($dlatch)) {
+				param_bool(ID(EN_POLARITY));
+				port(ID(EN), 1);
+				port(ID(D), param(ID(WIDTH)));
+				port(ID(Q), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$dlatchsr") {
-				param_bool("\\EN_POLARITY");
-				param_bool("\\SET_POLARITY");
-				param_bool("\\CLR_POLARITY");
-				port("\\EN", 1);
-				port("\\SET", param("\\WIDTH"));
-				port("\\CLR", param("\\WIDTH"));
-				port("\\D", param("\\WIDTH"));
-				port("\\Q", param("\\WIDTH"));
+			if (cell->type == ID($dlatchsr)) {
+				param_bool(ID(EN_POLARITY));
+				param_bool(ID(SET_POLARITY));
+				param_bool(ID(CLR_POLARITY));
+				port(ID(EN), 1);
+				port(ID(SET), param(ID(WIDTH)));
+				port(ID(CLR), param(ID(WIDTH)));
+				port(ID(D), param(ID(WIDTH)));
+				port(ID(Q), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$fsm") {
-				param("\\NAME");
-				param_bool("\\CLK_POLARITY");
-				param_bool("\\ARST_POLARITY");
-				param("\\STATE_BITS");
-				param("\\STATE_NUM");
-				param("\\STATE_NUM_LOG2");
-				param("\\STATE_RST");
-				param_bits("\\STATE_TABLE", param("\\STATE_BITS") * param("\\STATE_NUM"));
-				param("\\TRANS_NUM");
-				param_bits("\\TRANS_TABLE", param("\\TRANS_NUM") * (2*param("\\STATE_NUM_LOG2") + param("\\CTRL_IN_WIDTH") + param("\\CTRL_OUT_WIDTH")));
-				port("\\CLK", 1);
-				port("\\ARST", 1);
-				port("\\CTRL_IN", param("\\CTRL_IN_WIDTH"));
-				port("\\CTRL_OUT", param("\\CTRL_OUT_WIDTH"));
+			if (cell->type == ID($fsm)) {
+				param(ID(NAME));
+				param_bool(ID(CLK_POLARITY));
+				param_bool(ID(ARST_POLARITY));
+				param(ID(STATE_BITS));
+				param(ID(STATE_NUM));
+				param(ID(STATE_NUM_LOG2));
+				param(ID(STATE_RST));
+				param_bits(ID(STATE_TABLE), param(ID(STATE_BITS)) * param(ID(STATE_NUM)));
+				param(ID(TRANS_NUM));
+				param_bits(ID(TRANS_TABLE), param(ID(TRANS_NUM)) * (2*param(ID(STATE_NUM_LOG2)) + param(ID(CTRL_IN_WIDTH)) + param(ID(CTRL_OUT_WIDTH))));
+				port(ID(CLK), 1);
+				port(ID(ARST), 1);
+				port(ID(CTRL_IN), param(ID(CTRL_IN_WIDTH)));
+				port(ID(CTRL_OUT), param(ID(CTRL_OUT_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$memrd") {
-				param("\\MEMID");
-				param_bool("\\CLK_ENABLE");
-				param_bool("\\CLK_POLARITY");
-				param_bool("\\TRANSPARENT");
-				port("\\CLK", 1);
-				port("\\EN", 1);
-				port("\\ADDR", param("\\ABITS"));
-				port("\\DATA", param("\\WIDTH"));
+			if (cell->type == ID($memrd)) {
+				param(ID(MEMID));
+				param_bool(ID(CLK_ENABLE));
+				param_bool(ID(CLK_POLARITY));
+				param_bool(ID(TRANSPARENT));
+				port(ID(CLK), 1);
+				port(ID(EN), 1);
+				port(ID(ADDR), param(ID(ABITS)));
+				port(ID(DATA), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$memwr") {
-				param("\\MEMID");
-				param_bool("\\CLK_ENABLE");
-				param_bool("\\CLK_POLARITY");
-				param("\\PRIORITY");
-				port("\\CLK", 1);
-				port("\\EN", param("\\WIDTH"));
-				port("\\ADDR", param("\\ABITS"));
-				port("\\DATA", param("\\WIDTH"));
+			if (cell->type == ID($memwr)) {
+				param(ID(MEMID));
+				param_bool(ID(CLK_ENABLE));
+				param_bool(ID(CLK_POLARITY));
+				param(ID(PRIORITY));
+				port(ID(CLK), 1);
+				port(ID(EN), param(ID(WIDTH)));
+				port(ID(ADDR), param(ID(ABITS)));
+				port(ID(DATA), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$meminit") {
-				param("\\MEMID");
-				param("\\PRIORITY");
-				port("\\ADDR", param("\\ABITS"));
-				port("\\DATA", param("\\WIDTH") * param("\\WORDS"));
+			if (cell->type == ID($meminit)) {
+				param(ID(MEMID));
+				param(ID(PRIORITY));
+				port(ID(ADDR), param(ID(ABITS)));
+				port(ID(DATA), param(ID(WIDTH)) * param(ID(WORDS)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$mem") {
-				param("\\MEMID");
-				param("\\SIZE");
-				param("\\OFFSET");
-				param("\\INIT");
-				param_bits("\\RD_CLK_ENABLE", max(1, param("\\RD_PORTS")));
-				param_bits("\\RD_CLK_POLARITY", max(1, param("\\RD_PORTS")));
-				param_bits("\\RD_TRANSPARENT", max(1, param("\\RD_PORTS")));
-				param_bits("\\WR_CLK_ENABLE", max(1, param("\\WR_PORTS")));
-				param_bits("\\WR_CLK_POLARITY", max(1, param("\\WR_PORTS")));
-				port("\\RD_CLK", param("\\RD_PORTS"));
-				port("\\RD_EN", param("\\RD_PORTS"));
-				port("\\RD_ADDR", param("\\RD_PORTS") * param("\\ABITS"));
-				port("\\RD_DATA", param("\\RD_PORTS") * param("\\WIDTH"));
-				port("\\WR_CLK", param("\\WR_PORTS"));
-				port("\\WR_EN", param("\\WR_PORTS") * param("\\WIDTH"));
-				port("\\WR_ADDR", param("\\WR_PORTS") * param("\\ABITS"));
-				port("\\WR_DATA", param("\\WR_PORTS") * param("\\WIDTH"));
+			if (cell->type == ID($mem)) {
+				param(ID(MEMID));
+				param(ID(SIZE));
+				param(ID(OFFSET));
+				param(ID(INIT));
+				param_bits(ID(RD_CLK_ENABLE), max(1, param(ID(RD_PORTS))));
+				param_bits(ID(RD_CLK_POLARITY), max(1, param(ID(RD_PORTS))));
+				param_bits(ID(RD_TRANSPARENT), max(1, param(ID(RD_PORTS))));
+				param_bits(ID(WR_CLK_ENABLE), max(1, param(ID(WR_PORTS))));
+				param_bits(ID(WR_CLK_POLARITY), max(1, param(ID(WR_PORTS))));
+				port(ID(RD_CLK), param(ID(RD_PORTS)));
+				port(ID(RD_EN), param(ID(RD_PORTS)));
+				port(ID(RD_ADDR), param(ID(RD_PORTS)) * param(ID(ABITS)));
+				port(ID(RD_DATA), param(ID(RD_PORTS)) * param(ID(WIDTH)));
+				port(ID(WR_CLK), param(ID(WR_PORTS)));
+				port(ID(WR_EN), param(ID(WR_PORTS)) * param(ID(WIDTH)));
+				port(ID(WR_ADDR), param(ID(WR_PORTS)) * param(ID(ABITS)));
+				port(ID(WR_DATA), param(ID(WR_PORTS)) * param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$tribuf") {
-				port("\\A", param("\\WIDTH"));
-				port("\\Y", param("\\WIDTH"));
-				port("\\EN", 1);
+			if (cell->type == ID($tribuf)) {
+				port(ID(A), param(ID(WIDTH)));
+				port(ID(Y), param(ID(WIDTH)));
+				port(ID(EN), 1);
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$assert", "$assume", "$live", "$fair", "$cover")) {
-				port("\\A", 1);
-				port("\\EN", 1);
+			if (cell->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) {
+				port(ID(A), 1);
+				port(ID(EN), 1);
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$initstate") {
-				port("\\Y", 1);
+			if (cell->type == ID($initstate)) {
+				port(ID(Y), 1);
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$anyconst", "$anyseq", "$allconst", "$allseq")) {
-				port("\\Y", param("\\WIDTH"));
+			if (cell->type.in(ID($anyconst), ID($anyseq), ID($allconst), ID($allseq))) {
+				port(ID(Y), param(ID(WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$equiv") {
-				port("\\A", 1);
-				port("\\B", 1);
-				port("\\Y", 1);
+			if (cell->type == ID($equiv)) {
+				port(ID(A), 1);
+				port(ID(B), 1);
+				port(ID(Y), 1);
 				check_expected();
 				return;
 			}
 
-			if (cell->type.in("$specify2", "$specify3")) {
-				param_bool("\\FULL");
-				param_bool("\\SRC_DST_PEN");
-				param_bool("\\SRC_DST_POL");
-				param("\\T_RISE_MIN");
-				param("\\T_RISE_TYP");
-				param("\\T_RISE_MAX");
-				param("\\T_FALL_MIN");
-				param("\\T_FALL_TYP");
-				param("\\T_FALL_MAX");
-				port("\\EN", 1);
-				port("\\SRC", param("\\SRC_WIDTH"));
-				port("\\DST", param("\\DST_WIDTH"));
-				if (cell->type == "$specify3") {
-					param_bool("\\EDGE_EN");
-					param_bool("\\EDGE_POL");
-					param_bool("\\DAT_DST_PEN");
-					param_bool("\\DAT_DST_POL");
-					port("\\DAT", param("\\DST_WIDTH"));
+			if (cell->type.in(ID($specify2), ID($specify3))) {
+				param_bool(ID(FULL));
+				param_bool(ID(SRC_DST_PEN));
+				param_bool(ID(SRC_DST_POL));
+				param(ID(T_RISE_MIN));
+				param(ID(T_RISE_TYP));
+				param(ID(T_RISE_MAX));
+				param(ID(T_FALL_MIN));
+				param(ID(T_FALL_TYP));
+				param(ID(T_FALL_MAX));
+				port(ID(EN), 1);
+				port(ID(SRC), param(ID(SRC_WIDTH)));
+				port(ID(DST), param(ID(DST_WIDTH)));
+				if (cell->type == ID($specify3)) {
+					param_bool(ID(EDGE_EN));
+					param_bool(ID(EDGE_POL));
+					param_bool(ID(DAT_DST_PEN));
+					param_bool(ID(DAT_DST_POL));
+					port(ID(DAT), param(ID(DST_WIDTH)));
 				}
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$specrule") {
-				param("\\TYPE");
-				param_bool("\\SRC_PEN");
-				param_bool("\\SRC_POL");
-				param_bool("\\DST_PEN");
-				param_bool("\\DST_POL");
-				param("\\T_LIMIT");
-				param("\\T_LIMIT2");
-				port("\\SRC_EN", 1);
-				port("\\DST_EN", 1);
-				port("\\SRC", param("\\SRC_WIDTH"));
-				port("\\DST", param("\\DST_WIDTH"));
+			if (cell->type == ID($specrule)) {
+				param(ID(TYPE));
+				param_bool(ID(SRC_PEN));
+				param_bool(ID(SRC_POL));
+				param_bool(ID(DST_PEN));
+				param_bool(ID(DST_POL));
+				param(ID(T_LIMIT));
+				param(ID(T_LIMIT2));
+				port(ID(SRC_EN), 1);
+				port(ID(DST_EN), 1);
+				port(ID(SRC), param(ID(SRC_WIDTH)));
+				port(ID(DST), param(ID(DST_WIDTH)));
 				check_expected();
 				return;
 			}
 
-			if (cell->type == "$_BUF_")    { check_gate("AY"); return; }
-			if (cell->type == "$_NOT_")    { check_gate("AY"); return; }
-			if (cell->type == "$_AND_")    { check_gate("ABY"); return; }
-			if (cell->type == "$_NAND_")   { check_gate("ABY"); return; }
-			if (cell->type == "$_OR_")     { check_gate("ABY"); return; }
-			if (cell->type == "$_NOR_")    { check_gate("ABY"); return; }
-			if (cell->type == "$_XOR_")    { check_gate("ABY"); return; }
-			if (cell->type == "$_XNOR_")   { check_gate("ABY"); return; }
-			if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; }
-			if (cell->type == "$_ORNOT_")  { check_gate("ABY"); return; }
-			if (cell->type == "$_MUX_")    { check_gate("ABSY"); return; }
-			if (cell->type == "$_NMUX_")   { check_gate("ABSY"); return; }
-			if (cell->type == "$_AOI3_")   { check_gate("ABCY"); return; }
-			if (cell->type == "$_OAI3_")   { check_gate("ABCY"); return; }
-			if (cell->type == "$_AOI4_")   { check_gate("ABCDY"); return; }
-			if (cell->type == "$_OAI4_")   { check_gate("ABCDY"); return; }
+			if (cell->type == ID($_BUF_))    { check_gate("AY"); return; }
+			if (cell->type == ID($_NOT_))    { check_gate("AY"); return; }
+			if (cell->type == ID($_AND_))    { check_gate("ABY"); return; }
+			if (cell->type == ID($_NAND_))   { check_gate("ABY"); return; }
+			if (cell->type == ID($_OR_))     { check_gate("ABY"); return; }
+			if (cell->type == ID($_NOR_))    { check_gate("ABY"); return; }
+			if (cell->type == ID($_XOR_))    { check_gate("ABY"); return; }
+			if (cell->type == ID($_XNOR_))   { check_gate("ABY"); return; }
+			if (cell->type == ID($_ANDNOT_)) { check_gate("ABY"); return; }
+			if (cell->type == ID($_ORNOT_))  { check_gate("ABY"); return; }
+			if (cell->type == ID($_MUX_))    { check_gate("ABSY"); return; }
+			if (cell->type == ID($_NMUX_))   { check_gate("ABSY"); return; }
+			if (cell->type == ID($_AOI3_))   { check_gate("ABCY"); return; }
+			if (cell->type == ID($_OAI3_))   { check_gate("ABCY"); return; }
+			if (cell->type == ID($_AOI4_))   { check_gate("ABCDY"); return; }
+			if (cell->type == ID($_OAI4_))   { check_gate("ABCDY"); return; }
 
-			if (cell->type == "$_TBUF_")  { check_gate("AYE"); return; }
+			if (cell->type == ID($_TBUF_))  { check_gate("AYE"); return; }
 
-			if (cell->type == "$_MUX4_")  { check_gate("ABCDSTY"); return; }
-			if (cell->type == "$_MUX8_")  { check_gate("ABCDEFGHSTUY"); return; }
-			if (cell->type == "$_MUX16_") { check_gate("ABCDEFGHIJKLMNOPSTUVY"); return; }
+			if (cell->type == ID($_MUX4_))  { check_gate("ABCDSTY"); return; }
+			if (cell->type == ID($_MUX8_))  { check_gate("ABCDEFGHSTUY"); return; }
+			if (cell->type == ID($_MUX16_)) { check_gate("ABCDEFGHIJKLMNOPSTUVY"); return; }
 
-			if (cell->type == "$_SR_NN_") { check_gate("SRQ"); return; }
-			if (cell->type == "$_SR_NP_") { check_gate("SRQ"); return; }
-			if (cell->type == "$_SR_PN_") { check_gate("SRQ"); return; }
-			if (cell->type == "$_SR_PP_") { check_gate("SRQ"); return; }
+			if (cell->type == ID($_SR_NN_)) { check_gate("SRQ"); return; }
+			if (cell->type == ID($_SR_NP_)) { check_gate("SRQ"); return; }
+			if (cell->type == ID($_SR_PN_)) { check_gate("SRQ"); return; }
+			if (cell->type == ID($_SR_PP_)) { check_gate("SRQ"); return; }
 
-			if (cell->type == "$_FF_")    { check_gate("DQ");  return; }
-			if (cell->type == "$_DFF_N_") { check_gate("DQC"); return; }
-			if (cell->type == "$_DFF_P_") { check_gate("DQC"); return; }
+			if (cell->type == ID($_FF_))    { check_gate("DQ");  return; }
+			if (cell->type == ID($_DFF_N_)) { check_gate("DQC"); return; }
+			if (cell->type == ID($_DFF_P_)) { check_gate("DQC"); return; }
 
-			if (cell->type == "$_DFFE_NN_") { check_gate("DQCE"); return; }
-			if (cell->type == "$_DFFE_NP_") { check_gate("DQCE"); return; }
-			if (cell->type == "$_DFFE_PN_") { check_gate("DQCE"); return; }
-			if (cell->type == "$_DFFE_PP_") { check_gate("DQCE"); return; }
+			if (cell->type == ID($_DFFE_NN_)) { check_gate("DQCE"); return; }
+			if (cell->type == ID($_DFFE_NP_)) { check_gate("DQCE"); return; }
+			if (cell->type == ID($_DFFE_PN_)) { check_gate("DQCE"); return; }
+			if (cell->type == ID($_DFFE_PP_)) { check_gate("DQCE"); return; }
 
-			if (cell->type == "$_DFF_NN0_") { check_gate("DQCR"); return; }
-			if (cell->type == "$_DFF_NN1_") { check_gate("DQCR"); return; }
-			if (cell->type == "$_DFF_NP0_") { check_gate("DQCR"); return; }
-			if (cell->type == "$_DFF_NP1_") { check_gate("DQCR"); return; }
-			if (cell->type == "$_DFF_PN0_") { check_gate("DQCR"); return; }
-			if (cell->type == "$_DFF_PN1_") { check_gate("DQCR"); return; }
-			if (cell->type == "$_DFF_PP0_") { check_gate("DQCR"); return; }
-			if (cell->type == "$_DFF_PP1_") { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_NN0_)) { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_NN1_)) { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_NP0_)) { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_NP1_)) { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_PN0_)) { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_PN1_)) { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_PP0_)) { check_gate("DQCR"); return; }
+			if (cell->type == ID($_DFF_PP1_)) { check_gate("DQCR"); return; }
 
-			if (cell->type == "$_DFFSR_NNN_") { check_gate("CSRDQ"); return; }
-			if (cell->type == "$_DFFSR_NNP_") { check_gate("CSRDQ"); return; }
-			if (cell->type == "$_DFFSR_NPN_") { check_gate("CSRDQ"); return; }
-			if (cell->type == "$_DFFSR_NPP_") { check_gate("CSRDQ"); return; }
-			if (cell->type == "$_DFFSR_PNN_") { check_gate("CSRDQ"); return; }
-			if (cell->type == "$_DFFSR_PNP_") { check_gate("CSRDQ"); return; }
-			if (cell->type == "$_DFFSR_PPN_") { check_gate("CSRDQ"); return; }
-			if (cell->type == "$_DFFSR_PPP_") { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_NNN_)) { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_NNP_)) { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_NPN_)) { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_NPP_)) { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_PNN_)) { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_PNP_)) { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_PPN_)) { check_gate("CSRDQ"); return; }
+			if (cell->type == ID($_DFFSR_PPP_)) { check_gate("CSRDQ"); return; }
 
-			if (cell->type == "$_DLATCH_N_") { check_gate("EDQ"); return; }
-			if (cell->type == "$_DLATCH_P_") { check_gate("EDQ"); return; }
+			if (cell->type == ID($_DLATCH_N_)) { check_gate("EDQ"); return; }
+			if (cell->type == ID($_DLATCH_P_)) { check_gate("EDQ"); return; }
 
-			if (cell->type == "$_DLATCHSR_NNN_") { check_gate("ESRDQ"); return; }
-			if (cell->type == "$_DLATCHSR_NNP_") { check_gate("ESRDQ"); return; }
-			if (cell->type == "$_DLATCHSR_NPN_") { check_gate("ESRDQ"); return; }
-			if (cell->type == "$_DLATCHSR_NPP_") { check_gate("ESRDQ"); return; }
-			if (cell->type == "$_DLATCHSR_PNN_") { check_gate("ESRDQ"); return; }
-			if (cell->type == "$_DLATCHSR_PNP_") { check_gate("ESRDQ"); return; }
-			if (cell->type == "$_DLATCHSR_PPN_") { check_gate("ESRDQ"); return; }
-			if (cell->type == "$_DLATCHSR_PPP_") { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_NNN_)) { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_NNP_)) { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_NPN_)) { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_NPP_)) { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_PNN_)) { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_PNP_)) { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_PPN_)) { check_gate("ESRDQ"); return; }
+			if (cell->type == ID($_DLATCHSR_PPP_)) { check_gate("ESRDQ"); return; }
 
 			error(__LINE__);
 		}
@@ -1817,11 +1828,11 @@ RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, const RTLIL::Cell *oth
 #define DEF_METHOD(_func, _y_size, _type) \
 	RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed, const std::string &src) { \
 		RTLIL::Cell *cell = addCell(name, _type);           \
-		cell->parameters["\\A_SIGNED"] = is_signed;         \
-		cell->parameters["\\A_WIDTH"] = sig_a.size();       \
-		cell->parameters["\\Y_WIDTH"] = sig_y.size();       \
-		cell->setPort("\\A", sig_a);                        \
-		cell->setPort("\\Y", sig_y);                        \
+		cell->parameters[ID(A_SIGNED)] = is_signed;         \
+		cell->parameters[ID(A_WIDTH)] = sig_a.size();       \
+		cell->parameters[ID(Y_WIDTH)] = sig_y.size();       \
+		cell->setPort(ID(A), sig_a);                        \
+		cell->setPort(ID(Y), sig_y);                        \
 		cell->set_src_attribute(src);                       \
 		return cell;                                        \
 	} \
@@ -1830,28 +1841,28 @@ RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, const RTLIL::Cell *oth
 		add ## _func(name, sig_a, sig_y, is_signed, src);   \
 		return sig_y;                                       \
 	}
-DEF_METHOD(Not,        sig_a.size(), "$not")
-DEF_METHOD(Pos,        sig_a.size(), "$pos")
-DEF_METHOD(Neg,        sig_a.size(), "$neg")
-DEF_METHOD(ReduceAnd,  1, "$reduce_and")
-DEF_METHOD(ReduceOr,   1, "$reduce_or")
-DEF_METHOD(ReduceXor,  1, "$reduce_xor")
-DEF_METHOD(ReduceXnor, 1, "$reduce_xnor")
-DEF_METHOD(ReduceBool, 1, "$reduce_bool")
-DEF_METHOD(LogicNot,   1, "$logic_not")
+DEF_METHOD(Not,        sig_a.size(), ID($not))
+DEF_METHOD(Pos,        sig_a.size(), ID($pos))
+DEF_METHOD(Neg,        sig_a.size(), ID($neg))
+DEF_METHOD(ReduceAnd,  1, ID($reduce_and))
+DEF_METHOD(ReduceOr,   1, ID($reduce_or))
+DEF_METHOD(ReduceXor,  1, ID($reduce_xor))
+DEF_METHOD(ReduceXnor, 1, ID($reduce_xnor))
+DEF_METHOD(ReduceBool, 1, ID($reduce_bool))
+DEF_METHOD(LogicNot,   1, ID($logic_not))
 #undef DEF_METHOD
 
 #define DEF_METHOD(_func, _y_size, _type) \
 	RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed, const std::string &src) { \
 		RTLIL::Cell *cell = addCell(name, _type);           \
-		cell->parameters["\\A_SIGNED"] = is_signed;         \
-		cell->parameters["\\B_SIGNED"] = is_signed;         \
-		cell->parameters["\\A_WIDTH"] = sig_a.size();       \
-		cell->parameters["\\B_WIDTH"] = sig_b.size();       \
-		cell->parameters["\\Y_WIDTH"] = sig_y.size();       \
-		cell->setPort("\\A", sig_a);                        \
-		cell->setPort("\\B", sig_b);                        \
-		cell->setPort("\\Y", sig_y);                        \
+		cell->parameters[ID(A_SIGNED)] = is_signed;         \
+		cell->parameters[ID(B_SIGNED)] = is_signed;         \
+		cell->parameters[ID(A_WIDTH)] = sig_a.size();       \
+		cell->parameters[ID(B_WIDTH)] = sig_b.size();       \
+		cell->parameters[ID(Y_WIDTH)] = sig_y.size();       \
+		cell->setPort(ID(A), sig_a);                        \
+		cell->setPort(ID(B), sig_b);                        \
+		cell->setPort(ID(Y), sig_y);                        \
 		cell->set_src_attribute(src);                       \
 		return cell;                                        \
 	} \
@@ -1860,42 +1871,42 @@ DEF_METHOD(LogicNot,   1, "$logic_not")
 		add ## _func(name, sig_a, sig_b, sig_y, is_signed, src); \
 		return sig_y;                                            \
 	}
-DEF_METHOD(And,      max(sig_a.size(), sig_b.size()), "$and")
-DEF_METHOD(Or,       max(sig_a.size(), sig_b.size()), "$or")
-DEF_METHOD(Xor,      max(sig_a.size(), sig_b.size()), "$xor")
-DEF_METHOD(Xnor,     max(sig_a.size(), sig_b.size()), "$xnor")
-DEF_METHOD(Shl,      sig_a.size(), "$shl")
-DEF_METHOD(Shr,      sig_a.size(), "$shr")
-DEF_METHOD(Sshl,     sig_a.size(), "$sshl")
-DEF_METHOD(Sshr,     sig_a.size(), "$sshr")
-DEF_METHOD(Shift,    sig_a.size(), "$shift")
-DEF_METHOD(Shiftx,   sig_a.size(), "$shiftx")
-DEF_METHOD(Lt,       1, "$lt")
-DEF_METHOD(Le,       1, "$le")
-DEF_METHOD(Eq,       1, "$eq")
-DEF_METHOD(Ne,       1, "$ne")
-DEF_METHOD(Eqx,      1, "$eqx")
-DEF_METHOD(Nex,      1, "$nex")
-DEF_METHOD(Ge,       1, "$ge")
-DEF_METHOD(Gt,       1, "$gt")
-DEF_METHOD(Add,      max(sig_a.size(), sig_b.size()), "$add")
-DEF_METHOD(Sub,      max(sig_a.size(), sig_b.size()), "$sub")
-DEF_METHOD(Mul,      max(sig_a.size(), sig_b.size()), "$mul")
-DEF_METHOD(Div,      max(sig_a.size(), sig_b.size()), "$div")
-DEF_METHOD(Mod,      max(sig_a.size(), sig_b.size()), "$mod")
-DEF_METHOD(LogicAnd, 1, "$logic_and")
-DEF_METHOD(LogicOr,  1, "$logic_or")
+DEF_METHOD(And,      max(sig_a.size(), sig_b.size()), ID($and))
+DEF_METHOD(Or,       max(sig_a.size(), sig_b.size()), ID($or))
+DEF_METHOD(Xor,      max(sig_a.size(), sig_b.size()), ID($xor))
+DEF_METHOD(Xnor,     max(sig_a.size(), sig_b.size()), ID($xnor))
+DEF_METHOD(Shl,      sig_a.size(), ID($shl))
+DEF_METHOD(Shr,      sig_a.size(), ID($shr))
+DEF_METHOD(Sshl,     sig_a.size(), ID($sshl))
+DEF_METHOD(Sshr,     sig_a.size(), ID($sshr))
+DEF_METHOD(Shift,    sig_a.size(), ID($shift))
+DEF_METHOD(Shiftx,   sig_a.size(), ID($shiftx))
+DEF_METHOD(Lt,       1, ID($lt))
+DEF_METHOD(Le,       1, ID($le))
+DEF_METHOD(Eq,       1, ID($eq))
+DEF_METHOD(Ne,       1, ID($ne))
+DEF_METHOD(Eqx,      1, ID($eqx))
+DEF_METHOD(Nex,      1, ID($nex))
+DEF_METHOD(Ge,       1, ID($ge))
+DEF_METHOD(Gt,       1, ID($gt))
+DEF_METHOD(Add,      max(sig_a.size(), sig_b.size()), ID($add))
+DEF_METHOD(Sub,      max(sig_a.size(), sig_b.size()), ID($sub))
+DEF_METHOD(Mul,      max(sig_a.size(), sig_b.size()), ID($mul))
+DEF_METHOD(Div,      max(sig_a.size(), sig_b.size()), ID($div))
+DEF_METHOD(Mod,      max(sig_a.size(), sig_b.size()), ID($mod))
+DEF_METHOD(LogicAnd, 1, ID($logic_and))
+DEF_METHOD(LogicOr,  1, ID($logic_or))
 #undef DEF_METHOD
 
 #define DEF_METHOD(_func, _type, _pmux) \
 	RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y, const std::string &src) { \
 		RTLIL::Cell *cell = addCell(name, _type);                 \
-		cell->parameters["\\WIDTH"] = sig_a.size();               \
-		if (_pmux) cell->parameters["\\S_WIDTH"] = sig_s.size();  \
-		cell->setPort("\\A", sig_a);                              \
-		cell->setPort("\\B", sig_b);                              \
-		cell->setPort("\\S", sig_s);                              \
-		cell->setPort("\\Y", sig_y);                              \
+		cell->parameters[ID(WIDTH)] = sig_a.size();               \
+		if (_pmux) cell->parameters[ID(S_WIDTH)] = sig_s.size();  \
+		cell->setPort(ID(A), sig_a);                              \
+		cell->setPort(ID(B), sig_b);                              \
+		cell->setPort(ID(S), sig_s);                              \
+		cell->setPort(ID(Y), sig_y);                              \
 		cell->set_src_attribute(src);                             \
 		return cell;                                              \
 	} \
@@ -1904,8 +1915,8 @@ DEF_METHOD(LogicOr,  1, "$logic_or")
 		add ## _func(name, sig_a, sig_b, sig_s, sig_y, src);      \
 		return sig_y;                                             \
 	}
-DEF_METHOD(Mux,      "$mux",        0)
-DEF_METHOD(Pmux,     "$pmux",       1)
+DEF_METHOD(Mux,      ID($mux),        0)
+DEF_METHOD(Pmux,     ID($pmux),       1)
 #undef DEF_METHOD
 
 #define DEF_METHOD_2(_func, _type, _P1, _P2) \
@@ -1966,22 +1977,22 @@ DEF_METHOD(Pmux,     "$pmux",       1)
 		add ## _func(name, sig1, sig2, sig3, sig4, sig5, src); \
 		return sig5;                                           \
 	}
-DEF_METHOD_2(BufGate,    "$_BUF_",    A, Y)
-DEF_METHOD_2(NotGate,    "$_NOT_",    A, Y)
-DEF_METHOD_3(AndGate,    "$_AND_",    A, B, Y)
-DEF_METHOD_3(NandGate,   "$_NAND_",   A, B, Y)
-DEF_METHOD_3(OrGate,     "$_OR_",     A, B, Y)
-DEF_METHOD_3(NorGate,    "$_NOR_",    A, B, Y)
-DEF_METHOD_3(XorGate,    "$_XOR_",    A, B, Y)
-DEF_METHOD_3(XnorGate,   "$_XNOR_",   A, B, Y)
-DEF_METHOD_3(AndnotGate, "$_ANDNOT_", A, B, Y)
-DEF_METHOD_3(OrnotGate,  "$_ORNOT_",  A, B, Y)
-DEF_METHOD_4(MuxGate,    "$_MUX_",    A, B, S, Y)
-DEF_METHOD_4(NmuxGate,   "$_NMUX_",   A, B, S, Y)
-DEF_METHOD_4(Aoi3Gate,   "$_AOI3_",   A, B, C, Y)
-DEF_METHOD_4(Oai3Gate,   "$_OAI3_",   A, B, C, Y)
-DEF_METHOD_5(Aoi4Gate,   "$_AOI4_",   A, B, C, D, Y)
-DEF_METHOD_5(Oai4Gate,   "$_OAI4_",   A, B, C, D, Y)
+DEF_METHOD_2(BufGate,    ID($_BUF_),    A, Y)
+DEF_METHOD_2(NotGate,    ID($_NOT_),    A, Y)
+DEF_METHOD_3(AndGate,    ID($_AND_),    A, B, Y)
+DEF_METHOD_3(NandGate,   ID($_NAND_),   A, B, Y)
+DEF_METHOD_3(OrGate,     ID($_OR_),     A, B, Y)
+DEF_METHOD_3(NorGate,    ID($_NOR_),    A, B, Y)
+DEF_METHOD_3(XorGate,    ID($_XOR_),    A, B, Y)
+DEF_METHOD_3(XnorGate,   ID($_XNOR_),   A, B, Y)
+DEF_METHOD_3(AndnotGate, ID($_ANDNOT_), A, B, Y)
+DEF_METHOD_3(OrnotGate,  ID($_ORNOT_),  A, B, Y)
+DEF_METHOD_4(MuxGate,    ID($_MUX_),    A, B, S, Y)
+DEF_METHOD_4(NmuxGate,   ID($_NMUX_),   A, B, S, Y)
+DEF_METHOD_4(Aoi3Gate,   ID($_AOI3_),   A, B, C, Y)
+DEF_METHOD_4(Oai3Gate,   ID($_OAI3_),   A, B, C, Y)
+DEF_METHOD_5(Aoi4Gate,   ID($_AOI4_),   A, B, C, D, Y)
+DEF_METHOD_5(Oai4Gate,   ID($_OAI4_),   A, B, C, D, Y)
 #undef DEF_METHOD_2
 #undef DEF_METHOD_3
 #undef DEF_METHOD_4
@@ -1989,165 +2000,165 @@ DEF_METHOD_5(Oai4Gate,   "$_OAI4_",   A, B, C, D, Y)
 
 RTLIL::Cell* RTLIL::Module::addPow(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool a_signed, bool b_signed, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$pow");
-	cell->parameters["\\A_SIGNED"] = a_signed;
-	cell->parameters["\\B_SIGNED"] = b_signed;
-	cell->parameters["\\A_WIDTH"] = sig_a.size();
-	cell->parameters["\\B_WIDTH"] = sig_b.size();
-	cell->parameters["\\Y_WIDTH"] = sig_y.size();
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\B", sig_b);
-	cell->setPort("\\Y", sig_y);
+	RTLIL::Cell *cell = addCell(name, ID($pow));
+	cell->parameters[ID(A_SIGNED)] = a_signed;
+	cell->parameters[ID(B_SIGNED)] = b_signed;
+	cell->parameters[ID(A_WIDTH)] = sig_a.size();
+	cell->parameters[ID(B_WIDTH)] = sig_b.size();
+	cell->parameters[ID(Y_WIDTH)] = sig_y.size();
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(B), sig_b);
+	cell->setPort(ID(Y), sig_y);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addSlice(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const offset, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$slice");
-	cell->parameters["\\A_WIDTH"] = sig_a.size();
-	cell->parameters["\\Y_WIDTH"] = sig_y.size();
-	cell->parameters["\\OFFSET"] = offset;
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\Y", sig_y);
+	RTLIL::Cell *cell = addCell(name, ID($slice));
+	cell->parameters[ID(A_WIDTH)] = sig_a.size();
+	cell->parameters[ID(Y_WIDTH)] = sig_y.size();
+	cell->parameters[ID(OFFSET)] = offset;
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(Y), sig_y);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$concat");
-	cell->parameters["\\A_WIDTH"] = sig_a.size();
-	cell->parameters["\\B_WIDTH"] = sig_b.size();
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\B", sig_b);
-	cell->setPort("\\Y", sig_y);
+	RTLIL::Cell *cell = addCell(name, ID($concat));
+	cell->parameters[ID(A_WIDTH)] = sig_a.size();
+	cell->parameters[ID(B_WIDTH)] = sig_b.size();
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(B), sig_b);
+	cell->setPort(ID(Y), sig_y);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const lut, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$lut");
-	cell->parameters["\\LUT"] = lut;
-	cell->parameters["\\WIDTH"] = sig_a.size();
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\Y", sig_y);
+	RTLIL::Cell *cell = addCell(name, ID($lut));
+	cell->parameters[ID(LUT)] = lut;
+	cell->parameters[ID(WIDTH)] = sig_a.size();
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(Y), sig_y);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_y, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$tribuf");
-	cell->parameters["\\WIDTH"] = sig_a.size();
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\EN", sig_en);
-	cell->setPort("\\Y", sig_y);
+	RTLIL::Cell *cell = addCell(name, ID($tribuf));
+	cell->parameters[ID(WIDTH)] = sig_a.size();
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(EN), sig_en);
+	cell->setPort(ID(Y), sig_y);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addAssert(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$assert");
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\EN", sig_en);
+	RTLIL::Cell *cell = addCell(name, ID($assert));
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(EN), sig_en);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addAssume(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$assume");
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\EN", sig_en);
+	RTLIL::Cell *cell = addCell(name, ID($assume));
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(EN), sig_en);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addLive(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$live");
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\EN", sig_en);
+	RTLIL::Cell *cell = addCell(name, ID($live));
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(EN), sig_en);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addFair(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$fair");
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\EN", sig_en);
+	RTLIL::Cell *cell = addCell(name, ID($fair));
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(EN), sig_en);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addCover(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$cover");
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\EN", sig_en);
+	RTLIL::Cell *cell = addCell(name, ID($cover));
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(EN), sig_en);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addEquiv(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$equiv");
-	cell->setPort("\\A", sig_a);
-	cell->setPort("\\B", sig_b);
-	cell->setPort("\\Y", sig_y);
+	RTLIL::Cell *cell = addCell(name, ID($equiv));
+	cell->setPort(ID(A), sig_a);
+	cell->setPort(ID(B), sig_b);
+	cell->setPort(ID(Y), sig_y);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addSr(RTLIL::IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_q, bool set_polarity, bool clr_polarity, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$sr");
-	cell->parameters["\\SET_POLARITY"] = set_polarity;
-	cell->parameters["\\CLR_POLARITY"] = clr_polarity;
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\SET", sig_set);
-	cell->setPort("\\CLR", sig_clr);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($sr));
+	cell->parameters[ID(SET_POLARITY)] = set_polarity;
+	cell->parameters[ID(CLR_POLARITY)] = clr_polarity;
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(SET), sig_set);
+	cell->setPort(ID(CLR), sig_clr);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addFf(RTLIL::IdString name, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$ff");
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($ff));
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$dff");
-	cell->parameters["\\CLK_POLARITY"] = clk_polarity;
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\CLK", sig_clk);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($dff));
+	cell->parameters[ID(CLK_POLARITY)] = clk_polarity;
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(CLK), sig_clk);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addDffe(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$dffe");
-	cell->parameters["\\CLK_POLARITY"] = clk_polarity;
-	cell->parameters["\\EN_POLARITY"] = en_polarity;
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\CLK", sig_clk);
-	cell->setPort("\\EN", sig_en);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($dffe));
+	cell->parameters[ID(CLK_POLARITY)] = clk_polarity;
+	cell->parameters[ID(EN_POLARITY)] = en_polarity;
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(CLK), sig_clk);
+	cell->setPort(ID(EN), sig_en);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2155,16 +2166,16 @@ RTLIL::Cell* RTLIL::Module::addDffe(RTLIL::IdString name, RTLIL::SigSpec sig_clk
 RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr,
 		RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$dffsr");
-	cell->parameters["\\CLK_POLARITY"] = clk_polarity;
-	cell->parameters["\\SET_POLARITY"] = set_polarity;
-	cell->parameters["\\CLR_POLARITY"] = clr_polarity;
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\CLK", sig_clk);
-	cell->setPort("\\SET", sig_set);
-	cell->setPort("\\CLR", sig_clr);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($dffsr));
+	cell->parameters[ID(CLK_POLARITY)] = clk_polarity;
+	cell->parameters[ID(SET_POLARITY)] = set_polarity;
+	cell->parameters[ID(CLR_POLARITY)] = clr_polarity;
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(CLK), sig_clk);
+	cell->setPort(ID(SET), sig_set);
+	cell->setPort(ID(CLR), sig_clr);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2172,27 +2183,27 @@ RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, RTLIL::SigSpec sig_cl
 RTLIL::Cell* RTLIL::Module::addAdff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_arst, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q,
 		RTLIL::Const arst_value, bool clk_polarity, bool arst_polarity, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$adff");
-	cell->parameters["\\CLK_POLARITY"] = clk_polarity;
-	cell->parameters["\\ARST_POLARITY"] = arst_polarity;
-	cell->parameters["\\ARST_VALUE"] = arst_value;
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\CLK", sig_clk);
-	cell->setPort("\\ARST", sig_arst);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($adff));
+	cell->parameters[ID(CLK_POLARITY)] = clk_polarity;
+	cell->parameters[ID(ARST_POLARITY)] = arst_polarity;
+	cell->parameters[ID(ARST_VALUE)] = arst_value;
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(CLK), sig_clk);
+	cell->setPort(ID(ARST), sig_arst);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addDlatch(RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$dlatch");
-	cell->parameters["\\EN_POLARITY"] = en_polarity;
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\EN", sig_en);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($dlatch));
+	cell->parameters[ID(EN_POLARITY)] = en_polarity;
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(EN), sig_en);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2200,25 +2211,25 @@ RTLIL::Cell* RTLIL::Module::addDlatch(RTLIL::IdString name, RTLIL::SigSpec sig_e
 RTLIL::Cell* RTLIL::Module::addDlatchsr(RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr,
 		RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$dlatchsr");
-	cell->parameters["\\EN_POLARITY"] = en_polarity;
-	cell->parameters["\\SET_POLARITY"] = set_polarity;
-	cell->parameters["\\CLR_POLARITY"] = clr_polarity;
-	cell->parameters["\\WIDTH"] = sig_q.size();
-	cell->setPort("\\EN", sig_en);
-	cell->setPort("\\SET", sig_set);
-	cell->setPort("\\CLR", sig_clr);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($dlatchsr));
+	cell->parameters[ID(EN_POLARITY)] = en_polarity;
+	cell->parameters[ID(SET_POLARITY)] = set_polarity;
+	cell->parameters[ID(CLR_POLARITY)] = clr_polarity;
+	cell->parameters[ID(WIDTH)] = sig_q.size();
+	cell->setPort(ID(EN), sig_en);
+	cell->setPort(ID(SET), sig_set);
+	cell->setPort(ID(CLR), sig_clr);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
 
 RTLIL::Cell* RTLIL::Module::addFfGate(RTLIL::IdString name, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, const std::string &src)
 {
-	RTLIL::Cell *cell = addCell(name, "$_FF_");
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	RTLIL::Cell *cell = addCell(name, ID($_FF_));
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2226,9 +2237,9 @@ RTLIL::Cell* RTLIL::Module::addFfGate(RTLIL::IdString name, RTLIL::SigSpec sig_d
 RTLIL::Cell* RTLIL::Module::addDffGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, const std::string &src)
 {
 	RTLIL::Cell *cell = addCell(name, stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N'));
-	cell->setPort("\\C", sig_clk);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	cell->setPort(ID(C), sig_clk);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2236,10 +2247,10 @@ RTLIL::Cell* RTLIL::Module::addDffGate(RTLIL::IdString name, RTLIL::SigSpec sig_
 RTLIL::Cell* RTLIL::Module::addDffeGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity, const std::string &src)
 {
 	RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
-	cell->setPort("\\C", sig_clk);
-	cell->setPort("\\E", sig_en);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	cell->setPort(ID(C), sig_clk);
+	cell->setPort(ID(E), sig_en);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2248,11 +2259,11 @@ RTLIL::Cell* RTLIL::Module::addDffsrGate(RTLIL::IdString name, RTLIL::SigSpec si
 		RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity, const std::string &src)
 {
 	RTLIL::Cell *cell = addCell(name, stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N'));
-	cell->setPort("\\C", sig_clk);
-	cell->setPort("\\S", sig_set);
-	cell->setPort("\\R", sig_clr);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	cell->setPort(ID(C), sig_clk);
+	cell->setPort(ID(S), sig_set);
+	cell->setPort(ID(R), sig_clr);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2261,10 +2272,10 @@ RTLIL::Cell* RTLIL::Module::addAdffGate(RTLIL::IdString name, RTLIL::SigSpec sig
 		bool arst_value, bool clk_polarity, bool arst_polarity, const std::string &src)
 {
 	RTLIL::Cell *cell = addCell(name, stringf("$_DFF_%c%c%c_", clk_polarity ? 'P' : 'N', arst_polarity ? 'P' : 'N', arst_value ? '1' : '0'));
-	cell->setPort("\\C", sig_clk);
-	cell->setPort("\\R", sig_arst);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	cell->setPort(ID(C), sig_clk);
+	cell->setPort(ID(R), sig_arst);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2272,9 +2283,9 @@ RTLIL::Cell* RTLIL::Module::addAdffGate(RTLIL::IdString name, RTLIL::SigSpec sig
 RTLIL::Cell* RTLIL::Module::addDlatchGate(RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, const std::string &src)
 {
 	RTLIL::Cell *cell = addCell(name, stringf("$_DLATCH_%c_", en_polarity ? 'P' : 'N'));
-	cell->setPort("\\E", sig_en);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	cell->setPort(ID(E), sig_en);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2283,11 +2294,11 @@ RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, RTLIL::SigSpec
 		RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity, bool set_polarity, bool clr_polarity, const std::string &src)
 {
 	RTLIL::Cell *cell = addCell(name, stringf("$_DLATCHSR_%c%c%c_", en_polarity ? 'P' : 'N', set_polarity ? 'P' : 'N', clr_polarity ? 'P' : 'N'));
-	cell->setPort("\\E", sig_en);
-	cell->setPort("\\S", sig_set);
-	cell->setPort("\\R", sig_clr);
-	cell->setPort("\\D", sig_d);
-	cell->setPort("\\Q", sig_q);
+	cell->setPort(ID(E), sig_en);
+	cell->setPort(ID(S), sig_set);
+	cell->setPort(ID(R), sig_clr);
+	cell->setPort(ID(D), sig_d);
+	cell->setPort(ID(Q), sig_q);
 	cell->set_src_attribute(src);
 	return cell;
 }
@@ -2295,9 +2306,9 @@ RTLIL::Cell* RTLIL::Module::addDlatchsrGate(RTLIL::IdString name, RTLIL::SigSpec
 RTLIL::SigSpec RTLIL::Module::Anyconst(RTLIL::IdString name, int width, const std::string &src)
 {
 	RTLIL::SigSpec sig = addWire(NEW_ID, width);
-	Cell *cell = addCell(name, "$anyconst");
-	cell->setParam("\\WIDTH", width);
-	cell->setPort("\\Y", sig);
+	Cell *cell = addCell(name, ID($anyconst));
+	cell->setParam(ID(WIDTH), width);
+	cell->setPort(ID(Y), sig);
 	cell->set_src_attribute(src);
 	return sig;
 }
@@ -2305,9 +2316,9 @@ RTLIL::SigSpec RTLIL::Module::Anyconst(RTLIL::IdString name, int width, const st
 RTLIL::SigSpec RTLIL::Module::Anyseq(RTLIL::IdString name, int width, const std::string &src)
 {
 	RTLIL::SigSpec sig = addWire(NEW_ID, width);
-	Cell *cell = addCell(name, "$anyseq");
-	cell->setParam("\\WIDTH", width);
-	cell->setPort("\\Y", sig);
+	Cell *cell = addCell(name, ID($anyseq));
+	cell->setParam(ID(WIDTH), width);
+	cell->setPort(ID(Y), sig);
 	cell->set_src_attribute(src);
 	return sig;
 }
@@ -2315,9 +2326,9 @@ RTLIL::SigSpec RTLIL::Module::Anyseq(RTLIL::IdString name, int width, const std:
 RTLIL::SigSpec RTLIL::Module::Allconst(RTLIL::IdString name, int width, const std::string &src)
 {
 	RTLIL::SigSpec sig = addWire(NEW_ID, width);
-	Cell *cell = addCell(name, "$allconst");
-	cell->setParam("\\WIDTH", width);
-	cell->setPort("\\Y", sig);
+	Cell *cell = addCell(name, ID($allconst));
+	cell->setParam(ID(WIDTH), width);
+	cell->setPort(ID(Y), sig);
 	cell->set_src_attribute(src);
 	return sig;
 }
@@ -2325,9 +2336,9 @@ RTLIL::SigSpec RTLIL::Module::Allconst(RTLIL::IdString name, int width, const st
 RTLIL::SigSpec RTLIL::Module::Allseq(RTLIL::IdString name, int width, const std::string &src)
 {
 	RTLIL::SigSpec sig = addWire(NEW_ID, width);
-	Cell *cell = addCell(name, "$allseq");
-	cell->setParam("\\WIDTH", width);
-	cell->setPort("\\Y", sig);
+	Cell *cell = addCell(name, ID($allseq));
+	cell->setParam(ID(WIDTH), width);
+	cell->setPort(ID(Y), sig);
 	cell->set_src_attribute(src);
 	return sig;
 }
@@ -2335,8 +2346,8 @@ RTLIL::SigSpec RTLIL::Module::Allseq(RTLIL::IdString name, int width, const std:
 RTLIL::SigSpec RTLIL::Module::Initstate(RTLIL::IdString name, const std::string &src)
 {
 	RTLIL::SigSpec sig = addWire(NEW_ID);
-	Cell *cell = addCell(name, "$initstate");
-	cell->setPort("\\Y", sig);
+	Cell *cell = addCell(name, ID($initstate));
+	cell->setPort(ID(Y), sig);
 	cell->set_src_attribute(src);
 	return sig;
 }
@@ -2557,56 +2568,56 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
 			type.begins_with("$verific$") || type.begins_with("$array:") || type.begins_with("$extern:"))
 		return;
 
-	if (type == "$mux" || type == "$pmux") {
-		parameters["\\WIDTH"] = GetSize(connections_["\\Y"]);
-		if (type == "$pmux")
-			parameters["\\S_WIDTH"] = GetSize(connections_["\\S"]);
+	if (type == ID($mux) || type == ID($pmux)) {
+		parameters[ID(WIDTH)] = GetSize(connections_[ID(Y)]);
+		if (type == ID($pmux))
+			parameters[ID(S_WIDTH)] = GetSize(connections_[ID(S)]);
 		check();
 		return;
 	}
 
-	if (type == "$lut" || type == "$sop") {
-		parameters["\\WIDTH"] = GetSize(connections_["\\A"]);
+	if (type == ID($lut) || type == ID($sop)) {
+		parameters[ID(WIDTH)] = GetSize(connections_[ID(A)]);
 		return;
 	}
 
-	if (type == "$fa") {
-		parameters["\\WIDTH"] = GetSize(connections_["\\Y"]);
+	if (type == ID($fa)) {
+		parameters[ID(WIDTH)] = GetSize(connections_[ID(Y)]);
 		return;
 	}
 
-	if (type == "$lcu") {
-		parameters["\\WIDTH"] = GetSize(connections_["\\CO"]);
+	if (type == ID($lcu)) {
+		parameters[ID(WIDTH)] = GetSize(connections_[ID(CO)]);
 		return;
 	}
 
-	bool signedness_ab = !type.in("$slice", "$concat", "$macc");
+	bool signedness_ab = !type.in(ID($slice), ID($concat), ID($macc));
 
-	if (connections_.count("\\A")) {
+	if (connections_.count(ID(A))) {
 		if (signedness_ab) {
 			if (set_a_signed)
-				parameters["\\A_SIGNED"] = true;
-			else if (parameters.count("\\A_SIGNED") == 0)
-				parameters["\\A_SIGNED"] = false;
+				parameters[ID(A_SIGNED)] = true;
+			else if (parameters.count(ID(A_SIGNED)) == 0)
+				parameters[ID(A_SIGNED)] = false;
 		}
-		parameters["\\A_WIDTH"] = GetSize(connections_["\\A"]);
+		parameters[ID(A_WIDTH)] = GetSize(connections_[ID(A)]);
 	}
 
-	if (connections_.count("\\B")) {
+	if (connections_.count(ID(B))) {
 		if (signedness_ab) {
 			if (set_b_signed)
-				parameters["\\B_SIGNED"] = true;
-			else if (parameters.count("\\B_SIGNED") == 0)
-				parameters["\\B_SIGNED"] = false;
+				parameters[ID(B_SIGNED)] = true;
+			else if (parameters.count(ID(B_SIGNED)) == 0)
+				parameters[ID(B_SIGNED)] = false;
 		}
-		parameters["\\B_WIDTH"] = GetSize(connections_["\\B"]);
+		parameters[ID(B_WIDTH)] = GetSize(connections_[ID(B)]);
 	}
 
-	if (connections_.count("\\Y"))
-		parameters["\\Y_WIDTH"] = GetSize(connections_["\\Y"]);
+	if (connections_.count(ID(Y)))
+		parameters[ID(Y_WIDTH)] = GetSize(connections_[ID(Y)]);
 
-	if (connections_.count("\\Q"))
-		parameters["\\WIDTH"] = GetSize(connections_["\\Q"]);
+	if (connections_.count(ID(Q)))
+		parameters[ID(WIDTH)] = GetSize(connections_[ID(Q)]);
 
 	check();
 }
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 37b5f984c..c08653b65 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -78,6 +78,8 @@ namespace RTLIL
 	{
 		#undef YOSYS_XTRACE_GET_PUT
 		#undef YOSYS_SORT_ID_FREE_LIST
+		#undef YOSYS_USE_STICKY_IDS
+		#undef YOSYS_NO_IDS_REFCNT
 
 		// the global id string cache
 
@@ -87,13 +89,17 @@ namespace RTLIL
 			~destruct_guard_t() { ok = false; }
 		} destruct_guard;
 
-		static std::vector<int> global_refcount_storage_;
 		static std::vector<char*> global_id_storage_;
 		static dict<char*, int, hash_cstr_ops> global_id_index_;
+	#ifndef YOSYS_NO_IDS_REFCNT
+		static std::vector<int> global_refcount_storage_;
 		static std::vector<int> global_free_idx_list_;
+	#endif
 
+	#ifdef YOSYS_USE_STICKY_IDS
 		static int last_created_idx_ptr_;
 		static int last_created_idx_[8];
+	#endif
 
 		static inline void xtrace_db_dump()
 		{
@@ -110,12 +116,14 @@ namespace RTLIL
 
 		static inline void checkpoint()
 		{
+		#ifdef YOSYS_USE_STICKY_IDS
 			last_created_idx_ptr_ = 0;
 			for (int i = 0; i < 8; i++) {
 				if (last_created_idx_[i])
 					put_reference(last_created_idx_[i]);
 				last_created_idx_[i] = 0;
 			}
+		#endif
 		#ifdef YOSYS_SORT_ID_FREE_LIST
 			std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
 		#endif
@@ -123,36 +131,47 @@ namespace RTLIL
 
 		static inline int get_reference(int idx)
 		{
-			global_refcount_storage_.at(idx)++;
-		#ifdef YOSYS_XTRACE_GET_PUT
-			if (yosys_xtrace) {
-				log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
-			}
+			if (idx) {
+		#ifndef YOSYS_NO_IDS_REFCNT
+				global_refcount_storage_[idx]++;
 		#endif
+		#ifdef YOSYS_XTRACE_GET_PUT
+				if (yosys_xtrace)
+					log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
+		#endif
+			}
 			return idx;
 		}
 
-		static inline int get_reference(const char *p)
+		static int get_reference(const char *p)
 		{
 			log_assert(destruct_guard.ok);
 
-			if (p[0]) {
-				log_assert(p[1] != 0);
-				log_assert(p[0] == '$' || p[0] == '\\');
-			}
+			if (!p[0])
+				return 0;
+
+			log_assert(p[0] == '$' || p[0] == '\\');
+			log_assert(p[1] != 0);
 
 			auto it = global_id_index_.find((char*)p);
 			if (it != global_id_index_.end()) {
+		#ifndef YOSYS_NO_IDS_REFCNT
 				global_refcount_storage_.at(it->second)++;
+		#endif
 		#ifdef YOSYS_XTRACE_GET_PUT
-				if (yosys_xtrace) {
+				if (yosys_xtrace)
 					log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
-				}
 		#endif
 				return it->second;
 			}
 
+		#ifndef YOSYS_NO_IDS_REFCNT
 			if (global_free_idx_list_.empty()) {
+				if (global_id_storage_.empty()) {
+					global_refcount_storage_.push_back(0);
+					global_id_storage_.push_back((char*)"");
+					global_id_index_[global_id_storage_.back()] = 0;
+				}
 				log_assert(global_id_storage_.size() < 0x40000000);
 				global_free_idx_list_.push_back(global_id_storage_.size());
 				global_id_storage_.push_back(nullptr);
@@ -164,13 +183,15 @@ namespace RTLIL
 			global_id_storage_.at(idx) = strdup(p);
 			global_id_index_[global_id_storage_.at(idx)] = idx;
 			global_refcount_storage_.at(idx)++;
-
-			// Avoid Create->Delete->Create pattern
-			if (last_created_idx_[last_created_idx_ptr_])
-				put_reference(last_created_idx_[last_created_idx_ptr_]);
-			last_created_idx_[last_created_idx_ptr_] = idx;
-			get_reference(last_created_idx_[last_created_idx_ptr_]);
-			last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
+		#else
+			if (global_id_storage_.empty()) {
+				global_id_storage_.push_back((char*)"");
+				global_id_index_[global_id_storage_.back()] = 0;
+			}
+			int idx = global_id_storage_.size();
+			global_id_storage_.push_back(strdup(p));
+			global_id_index_[global_id_storage_.back()] = idx;
+		#endif
 
 			if (yosys_xtrace) {
 				log("#X# New IdString '%s' with index %d.\n", p, idx);
@@ -178,18 +199,28 @@ namespace RTLIL
 			}
 
 		#ifdef YOSYS_XTRACE_GET_PUT
-			if (yosys_xtrace) {
+			if (yosys_xtrace)
 				log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
-			}
 		#endif
+
+		#ifdef YOSYS_USE_STICKY_IDS
+			// Avoid Create->Delete->Create pattern
+			if (last_created_idx_[last_created_idx_ptr_])
+				put_reference(last_created_idx_[last_created_idx_ptr_]);
+			last_created_idx_[last_created_idx_ptr_] = idx;
+			get_reference(last_created_idx_[last_created_idx_ptr_]);
+			last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
+		#endif
+
 			return idx;
 		}
 
+	#ifndef YOSYS_NO_IDS_REFCNT
 		static inline void put_reference(int idx)
 		{
 			// put_reference() may be called from destructors after the destructor of
 			// global_refcount_storage_ has been run. in this case we simply do nothing.
-			if (!destruct_guard.ok)
+			if (!destruct_guard.ok || !idx)
 				return;
 
 		#ifdef YOSYS_XTRACE_GET_PUT
@@ -198,11 +229,13 @@ namespace RTLIL
 			}
 		#endif
 
-			log_assert(global_refcount_storage_.at(idx) > 0);
+			int &refcount = global_refcount_storage_[idx];
 
-			if (--global_refcount_storage_.at(idx) != 0)
+			if (--refcount > 0)
 				return;
 
+			log_assert(refcount == 0);
+
 			if (yosys_xtrace) {
 				log("#X# Removed IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
 				log_backtrace("-X- ", yosys_xtrace-1);
@@ -213,46 +246,50 @@ namespace RTLIL
 			global_id_storage_.at(idx) = nullptr;
 			global_free_idx_list_.push_back(idx);
 		}
+	#else
+		static inline void put_reference(int) { }
+	#endif
 
 		// the actual IdString object is just is a single int
 
 		int index_;
 
-		IdString() : index_(get_reference("")) { }
-		IdString(const char *str) : index_(get_reference(str)) { }
-		IdString(const IdString &str) : index_(get_reference(str.index_)) { }
-		IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
-		~IdString() { put_reference(index_); }
+		inline IdString() : index_(0) { }
+		inline IdString(const char *str) : index_(get_reference(str)) { }
+		inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
+		inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
+		inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
+		inline ~IdString() { put_reference(index_); }
 
-		void operator=(const IdString &rhs) {
+		inline void operator=(const IdString &rhs) {
 			put_reference(index_);
 			index_ = get_reference(rhs.index_);
 		}
 
-		void operator=(const char *rhs) {
+		inline void operator=(const char *rhs) {
 			IdString id(rhs);
 			*this = id;
 		}
 
-		void operator=(const std::string &rhs) {
+		inline void operator=(const std::string &rhs) {
 			IdString id(rhs);
 			*this = id;
 		}
 
-		const char *c_str() const {
+		inline const char *c_str() const {
 			return global_id_storage_.at(index_);
 		}
 
-		std::string str() const {
+		inline std::string str() const {
 			return std::string(global_id_storage_.at(index_));
 		}
 
-		bool operator<(const IdString &rhs) const {
+		inline bool operator<(const IdString &rhs) const {
 			return index_ < rhs.index_;
 		}
 
-		bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
-		bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
+		inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
+		inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
 
 		// The methods below are just convenience functions for better compatibility with std::string.
 
@@ -332,6 +369,14 @@ namespace RTLIL
 		bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
 	};
 
+	namespace ID {
+		// defined in rtlil.cc, initialized in yosys.cc
+		extern IdString A, B, Y;
+		extern IdString keep;
+		extern IdString whitebox;
+		extern IdString blackbox;
+	};
+
 	static inline std::string escape_id(std::string str) {
 		if (str.size() > 0 && str[0] != '\\' && str[0] != '$')
 			return "\\" + str;
@@ -604,7 +649,7 @@ struct RTLIL::AttrObject
 	bool get_bool_attribute(RTLIL::IdString id) const;
 
 	bool get_blackbox_attribute(bool ignore_wb=false) const {
-		return get_bool_attribute("\\blackbox") || (!ignore_wb && get_bool_attribute("\\whitebox"));
+		return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox));
 	}
 
 	void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
@@ -1339,8 +1384,8 @@ public:
 	void fixup_parameters(bool set_a_signed = false, bool set_b_signed = false);
 
 	bool has_keep_attr() const {
-		return get_bool_attribute("\\keep") || (module && module->design && module->design->module(type) &&
-				module->design->module(type)->get_bool_attribute("\\keep"));
+		return get_bool_attribute(ID::keep) || (module && module->design && module->design->module(type) &&
+				module->design->module(type)->get_bool_attribute(ID::keep));
 	}
 
 	template<typename T> void rewrite_sigspecs(T &functor);
diff --git a/kernel/satgen.h b/kernel/satgen.h
index 596f522ec..de480f28e 100644
--- a/kernel/satgen.h
+++ b/kernel/satgen.h
@@ -224,8 +224,8 @@ struct SatGen
 	void extendSignalWidth(std::vector<int> &vec_a, std::vector<int> &vec_b, RTLIL::Cell *cell, size_t y_width = 0, bool forced_signed = false)
 	{
 		bool is_signed = forced_signed;
-		if (!forced_signed && cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters.count("\\B_SIGNED") > 0)
-			is_signed = cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool();
+		if (!forced_signed && cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters.count(ID(B_SIGNED)) > 0)
+			is_signed = cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool();
 		while (vec_a.size() < vec_b.size() || vec_a.size() < y_width)
 			vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->CONST_FALSE);
 		while (vec_b.size() < vec_a.size() || vec_b.size() < y_width)
@@ -241,7 +241,7 @@ struct SatGen
 
 	void extendSignalWidthUnary(std::vector<int> &vec_a, std::vector<int> &vec_y, RTLIL::Cell *cell, bool forced_signed = false)
 	{
-		bool is_signed = forced_signed || (cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool());
+		bool is_signed = forced_signed || (cell->parameters.count(ID(A_SIGNED)) > 0 && cell->parameters[ID(A_SIGNED)].as_bool());
 		while (vec_a.size() < vec_y.size())
 			vec_a.push_back(is_signed && vec_a.size() > 0 ? vec_a.back() : ez->CONST_FALSE);
 		while (vec_y.size() < vec_a.size())
@@ -277,13 +277,13 @@ struct SatGen
 	bool importCell(RTLIL::Cell *cell, int timestep = -1)
 	{
 		bool arith_undef_handled = false;
-		bool is_arith_compare = cell->type.in("$lt", "$le", "$ge", "$gt");
+		bool is_arith_compare = cell->type.in(ID($lt), ID($le), ID($ge), ID($gt));
 
-		if (model_undef && (cell->type.in("$add", "$sub", "$mul", "$div", "$mod") || is_arith_compare))
+		if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod)) || is_arith_compare))
 		{
-			std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 			if (is_arith_compare)
 				extendSignalWidth(undef_a, undef_b, cell, true);
 			else
@@ -293,8 +293,8 @@ struct SatGen
 			int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
 			int undef_y_bit = ez->OR(undef_any_a, undef_any_b);
 
-			if (cell->type == "$div" || cell->type == "$mod") {
-				std::vector<int> b = importSigSpec(cell->getPort("\\B"), timestep);
+			if (cell->type == ID($div) || cell->type == ID($mod)) {
+				std::vector<int> b = importSigSpec(cell->getPort(ID(B)), timestep);
 				undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b)));
 			}
 
@@ -310,68 +310,68 @@ struct SatGen
 			arith_undef_handled = true;
 		}
 
-		if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_",
-				"$and", "$or", "$xor", "$xnor", "$add", "$sub"))
+		if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_),
+				ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($sub)))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			extendSignalWidth(a, b, y, cell);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 
-			if (cell->type == "$and" || cell->type == "$_AND_")
+			if (cell->type == ID($and) || cell->type == ID($_AND_))
 				ez->assume(ez->vec_eq(ez->vec_and(a, b), yy));
-			if (cell->type == "$_NAND_")
+			if (cell->type == ID($_NAND_))
 				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_and(a, b)), yy));
-			if (cell->type == "$or" || cell->type == "$_OR_")
+			if (cell->type == ID($or) || cell->type == ID($_OR_))
 				ez->assume(ez->vec_eq(ez->vec_or(a, b), yy));
-			if (cell->type == "$_NOR_")
+			if (cell->type == ID($_NOR_))
 				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_or(a, b)), yy));
-			if (cell->type == "$xor" || cell->type == "$_XOR_")
+			if (cell->type == ID($xor) || cell->type == ID($_XOR_))
 				ez->assume(ez->vec_eq(ez->vec_xor(a, b), yy));
-			if (cell->type == "$xnor" || cell->type == "$_XNOR_")
+			if (cell->type == ID($xnor) || cell->type == ID($_XNOR_))
 				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(a, b)), yy));
-			if (cell->type == "$_ANDNOT_")
+			if (cell->type == ID($_ANDNOT_))
 				ez->assume(ez->vec_eq(ez->vec_and(a, ez->vec_not(b)), yy));
-			if (cell->type == "$_ORNOT_")
+			if (cell->type == ID($_ORNOT_))
 				ez->assume(ez->vec_eq(ez->vec_or(a, ez->vec_not(b)), yy));
-			if (cell->type == "$add")
+			if (cell->type == ID($add))
 				ez->assume(ez->vec_eq(ez->vec_add(a, b), yy));
-			if (cell->type == "$sub")
+			if (cell->type == ID($sub))
 				ez->assume(ez->vec_eq(ez->vec_sub(a, b), yy));
 
 			if (model_undef && !arith_undef_handled)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				extendSignalWidth(undef_a, undef_b, undef_y, cell, false);
 
-				if (cell->type.in("$and", "$_AND_", "$_NAND_")) {
+				if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_))) {
 					std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
 					std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
 					std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b0)));
 					ez->assume(ez->vec_eq(yX, undef_y));
 				}
-				else if (cell->type.in("$or", "$_OR_", "$_NOR_")) {
+				else if (cell->type.in(ID($or), ID($_OR_), ID($_NOR_))) {
 					std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
 					std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
 					std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b1)));
 					ez->assume(ez->vec_eq(yX, undef_y));
 				}
-				else if (cell->type.in("$xor", "$xnor", "$_XOR_", "$_XNOR_")) {
+				else if (cell->type.in(ID($xor), ID($xnor), ID($_XOR_), ID($_XNOR_))) {
 					std::vector<int> yX = ez->vec_or(undef_a, undef_b);
 					ez->assume(ez->vec_eq(yX, undef_y));
 				}
-				else if (cell->type == "$_ANDNOT_") {
+				else if (cell->type == ID($_ANDNOT_)) {
 					std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
 					std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
 					std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b1)));
 					ez->assume(ez->vec_eq(yX, undef_y));
 				}
 
-				else if (cell->type == "$_ORNOT_") {
+				else if (cell->type == ID($_ORNOT_)) {
 					std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
 					std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
 					std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b0)));
@@ -384,36 +384,36 @@ struct SatGen
 			}
 			else if (model_undef)
 			{
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				undefGating(y, yy, undef_y);
 			}
 			return true;
 		}
 
-		if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
+		if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
 		{
-			bool aoi_mode = cell->type.in("$_AOI3_", "$_AOI4_");
-			bool three_mode = cell->type.in("$_AOI3_", "$_OAI3_");
+			bool aoi_mode = cell->type.in(ID($_AOI3_), ID($_AOI4_));
+			bool three_mode = cell->type.in(ID($_AOI3_), ID($_OAI3_));
 
-			int a = importDefSigSpec(cell->getPort("\\A"), timestep).at(0);
-			int b = importDefSigSpec(cell->getPort("\\B"), timestep).at(0);
-			int c = importDefSigSpec(cell->getPort("\\C"), timestep).at(0);
-			int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort("\\D"), timestep).at(0);
-			int y = importDefSigSpec(cell->getPort("\\Y"), timestep).at(0);
+			int a = importDefSigSpec(cell->getPort(ID(A)), timestep).at(0);
+			int b = importDefSigSpec(cell->getPort(ID(B)), timestep).at(0);
+			int c = importDefSigSpec(cell->getPort(ID(C)), timestep).at(0);
+			int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort(ID(D)), timestep).at(0);
+			int y = importDefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
 			int yy = model_undef ? ez->literal() : y;
 
-			if (cell->type.in("$_AOI3_", "$_AOI4_"))
+			if (cell->type.in(ID($_AOI3_), ID($_AOI4_)))
 				ez->assume(ez->IFF(ez->NOT(ez->OR(ez->AND(a, b), ez->AND(c, d))), yy));
 			else
 				ez->assume(ez->IFF(ez->NOT(ez->AND(ez->OR(a, b), ez->OR(c, d))), yy));
 
 			if (model_undef)
 			{
-				int undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep).at(0);
-				int undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep).at(0);
-				int undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep).at(0);
-				int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort("\\D"), timestep).at(0);
-				int undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep).at(0);
+				int undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep).at(0);
+				int undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep).at(0);
+				int undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep).at(0);
+				int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort(ID(D)), timestep).at(0);
+				int undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
 
 				if (aoi_mode)
 				{
@@ -456,18 +456,18 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$_NOT_" || cell->type == "$not")
+		if (cell->type == ID($_NOT_) || cell->type == ID($not))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			extendSignalWidthUnary(a, y, cell);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 			ez->assume(ez->vec_eq(ez->vec_not(a), yy));
 
 			if (model_undef) {
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				extendSignalWidthUnary(undef_a, undef_y, cell, false);
 				ez->assume(ez->vec_eq(undef_a, undef_y));
 				undefGating(y, yy, undef_y);
@@ -475,25 +475,25 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$_MUX_" || cell->type == "$mux" || cell->type == "$_NMUX_")
+		if (cell->type == ID($_MUX_) || cell->type == ID($mux) || cell->type == ID($_NMUX_))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> s = importDefSigSpec(cell->getPort("\\S"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> s = importDefSigSpec(cell->getPort(ID(S)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-			if (cell->type == "$_NMUX_")
+			if (cell->type == ID($_NMUX_))
 				ez->assume(ez->vec_eq(ez->vec_not(ez->vec_ite(s.at(0), b, a)), yy));
 			else
 				ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_s = importUndefSigSpec(cell->getPort("\\S"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 
 				std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a, b));
 				std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a, undef_b));
@@ -504,12 +504,12 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$pmux")
+		if (cell->type == ID($pmux))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> s = importDefSigSpec(cell->getPort("\\S"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> s = importDefSigSpec(cell->getPort(ID(S)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 
@@ -522,10 +522,10 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_s = importUndefSigSpec(cell->getPort("\\S"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID(S)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 
 				int maybe_a = ez->CONST_TRUE;
 
@@ -555,15 +555,15 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$pos" || cell->type == "$neg")
+		if (cell->type == ID($pos) || cell->type == ID($neg))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			extendSignalWidthUnary(a, y, cell);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 
-			if (cell->type == "$pos") {
+			if (cell->type == ID($pos)) {
 				ez->assume(ez->vec_eq(a, yy));
 			} else {
 				std::vector<int> zero(a.size(), ez->CONST_FALSE);
@@ -572,11 +572,11 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				extendSignalWidthUnary(undef_a, undef_y, cell);
 
-				if (cell->type == "$pos") {
+				if (cell->type == ID($pos)) {
 					ez->assume(ez->vec_eq(undef_a, undef_y));
 				} else {
 					int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
@@ -589,42 +589,42 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$reduce_and" || cell->type == "$reduce_or" || cell->type == "$reduce_xor" ||
-				cell->type == "$reduce_xnor" || cell->type == "$reduce_bool" || cell->type == "$logic_not")
+		if (cell->type == ID($reduce_and) || cell->type == ID($reduce_or) || cell->type == ID($reduce_xor) ||
+				cell->type == ID($reduce_xnor) || cell->type == ID($reduce_bool) || cell->type == ID($logic_not))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 
-			if (cell->type == "$reduce_and")
+			if (cell->type == ID($reduce_and))
 				ez->SET(ez->expression(ez->OpAnd, a), yy.at(0));
-			if (cell->type == "$reduce_or" || cell->type == "$reduce_bool")
+			if (cell->type == ID($reduce_or) || cell->type == ID($reduce_bool))
 				ez->SET(ez->expression(ez->OpOr, a), yy.at(0));
-			if (cell->type == "$reduce_xor")
+			if (cell->type == ID($reduce_xor))
 				ez->SET(ez->expression(ez->OpXor, a), yy.at(0));
-			if (cell->type == "$reduce_xnor")
+			if (cell->type == ID($reduce_xnor))
 				ez->SET(ez->NOT(ez->expression(ez->OpXor, a)), yy.at(0));
-			if (cell->type == "$logic_not")
+			if (cell->type == ID($logic_not))
 				ez->SET(ez->NOT(ez->expression(ez->OpOr, a)), yy.at(0));
 			for (size_t i = 1; i < y.size(); i++)
 				ez->SET(ez->CONST_FALSE, yy.at(i));
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				int aX = ez->expression(ezSAT::OpOr, undef_a);
 
-				if (cell->type == "$reduce_and") {
+				if (cell->type == ID($reduce_and)) {
 					int a0 = ez->expression(ezSAT::OpOr, ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a)));
 					ez->assume(ez->IFF(ez->AND(ez->NOT(a0), aX), undef_y.at(0)));
 				}
-				else if (cell->type == "$reduce_or" || cell->type == "$reduce_bool" || cell->type == "$logic_not") {
+				else if (cell->type == ID($reduce_or) || cell->type == ID($reduce_bool) || cell->type == ID($logic_not)) {
 					int a1 = ez->expression(ezSAT::OpOr, ez->vec_and(a, ez->vec_not(undef_a)));
 					ez->assume(ez->IFF(ez->AND(ez->NOT(a1), aX), undef_y.at(0)));
 				}
-				else if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor") {
+				else if (cell->type == ID($reduce_xor) || cell->type == ID($reduce_xnor)) {
 					ez->assume(ez->IFF(aX, undef_y.at(0)));
 				} else
 					log_abort();
@@ -637,18 +637,18 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$logic_and" || cell->type == "$logic_or")
+		if (cell->type == ID($logic_and) || cell->type == ID($logic_or))
 		{
-			std::vector<int> vec_a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> vec_b = importDefSigSpec(cell->getPort("\\B"), timestep);
+			std::vector<int> vec_a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> vec_b = importDefSigSpec(cell->getPort(ID(B)), timestep);
 
 			int a = ez->expression(ez->OpOr, vec_a);
 			int b = ez->expression(ez->OpOr, vec_b);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 
-			if (cell->type == "$logic_and")
+			if (cell->type == ID($logic_and))
 				ez->SET(ez->expression(ez->OpAnd, a, b), yy.at(0));
 			else
 				ez->SET(ez->expression(ez->OpOr, a, b), yy.at(0));
@@ -657,9 +657,9 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 
 				int a0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_a), ez->expression(ezSAT::OpOr, undef_a)));
 				int b0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_b), ez->expression(ezSAT::OpOr, undef_b)));
@@ -668,9 +668,9 @@ struct SatGen
 				int aX = ez->expression(ezSAT::OpOr, undef_a);
 				int bX = ez->expression(ezSAT::OpOr, undef_b);
 
-				if (cell->type == "$logic_and")
+				if (cell->type == ID($logic_and))
 					ez->SET(ez->AND(ez->OR(aX, bX), ez->NOT(ez->AND(a1, b1)), ez->NOT(a0), ez->NOT(b0)), undef_y.at(0));
-				else if (cell->type == "$logic_or")
+				else if (cell->type == ID($logic_or))
 					ez->SET(ez->AND(ez->OR(aX, bX), ez->NOT(ez->AND(a0, b0)), ez->NOT(a1), ez->NOT(b1)), undef_y.at(0));
 				else
 					log_abort();
@@ -683,47 +683,47 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt")
+		if (cell->type == ID($lt) || cell->type == ID($le) || cell->type == ID($eq) || cell->type == ID($ne) || cell->type == ID($eqx) || cell->type == ID($nex) || cell->type == ID($ge) || cell->type == ID($gt))
 		{
-			bool is_signed = cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool();
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			bool is_signed = cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool();
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			extendSignalWidth(a, b, cell);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 
-			if (model_undef && (cell->type == "$eqx" || cell->type == "$nex")) {
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
+			if (model_undef && (cell->type == ID($eqx) || cell->type == ID($nex))) {
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
 				extendSignalWidth(undef_a, undef_b, cell, true);
 				a = ez->vec_or(a, undef_a);
 				b = ez->vec_or(b, undef_b);
 			}
 
-			if (cell->type == "$lt")
+			if (cell->type == ID($lt))
 				ez->SET(is_signed ? ez->vec_lt_signed(a, b) : ez->vec_lt_unsigned(a, b), yy.at(0));
-			if (cell->type == "$le")
+			if (cell->type == ID($le))
 				ez->SET(is_signed ? ez->vec_le_signed(a, b) : ez->vec_le_unsigned(a, b), yy.at(0));
-			if (cell->type == "$eq" || cell->type == "$eqx")
+			if (cell->type == ID($eq) || cell->type == ID($eqx))
 				ez->SET(ez->vec_eq(a, b), yy.at(0));
-			if (cell->type == "$ne" || cell->type == "$nex")
+			if (cell->type == ID($ne) || cell->type == ID($nex))
 				ez->SET(ez->vec_ne(a, b), yy.at(0));
-			if (cell->type == "$ge")
+			if (cell->type == ID($ge))
 				ez->SET(is_signed ? ez->vec_ge_signed(a, b) : ez->vec_ge_unsigned(a, b), yy.at(0));
-			if (cell->type == "$gt")
+			if (cell->type == ID($gt))
 				ez->SET(is_signed ? ez->vec_gt_signed(a, b) : ez->vec_gt_unsigned(a, b), yy.at(0));
 			for (size_t i = 1; i < y.size(); i++)
 				ez->SET(ez->CONST_FALSE, yy.at(i));
 
-			if (model_undef && (cell->type == "$eqx" || cell->type == "$nex"))
+			if (model_undef && (cell->type == ID($eqx) || cell->type == ID($nex)))
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				extendSignalWidth(undef_a, undef_b, cell, true);
 
-				if (cell->type == "$eqx")
+				if (cell->type == ID($eqx))
 					yy.at(0) = ez->AND(yy.at(0), ez->vec_eq(undef_a, undef_b));
 				else
 					yy.at(0) = ez->OR(yy.at(0), ez->vec_ne(undef_a, undef_b));
@@ -733,11 +733,11 @@ struct SatGen
 
 				ez->assume(ez->vec_eq(y, yy));
 			}
-			else if (model_undef && (cell->type == "$eq" || cell->type == "$ne"))
+			else if (model_undef && (cell->type == ID($eq) || cell->type == ID($ne)))
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				extendSignalWidth(undef_a, undef_b, cell, true);
 
 				int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
@@ -759,7 +759,7 @@ struct SatGen
 			else
 			{
 				if (model_undef) {
-					std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+					std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 					undefGating(y, yy, undef_y);
 				}
 				log_assert(!model_undef || arith_undef_handled);
@@ -767,15 +767,15 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || cell->type == "$shift" || cell->type == "$shiftx")
+		if (cell->type == ID($shl) || cell->type == ID($shr) || cell->type == ID($sshl) || cell->type == ID($sshr) || cell->type == ID($shift) || cell->type == ID($shiftx))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			int extend_bit = ez->CONST_FALSE;
 
-			if (!cell->type.in("$shift", "$shiftx") && cell->parameters["\\A_SIGNED"].as_bool())
+			if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID(A_SIGNED)].as_bool())
 				extend_bit = a.back();
 
 			while (y.size() < a.size())
@@ -786,29 +786,29 @@ struct SatGen
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 			std::vector<int> shifted_a;
 
-			if (cell->type == "$shl" || cell->type == "$sshl")
+			if (cell->type == ID($shl) || cell->type == ID($sshl))
 				shifted_a = ez->vec_shift_left(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
 
-			if (cell->type == "$shr")
+			if (cell->type == ID($shr))
 				shifted_a = ez->vec_shift_right(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
 
-			if (cell->type == "$sshr")
-				shifted_a = ez->vec_shift_right(a, b, false, cell->parameters["\\A_SIGNED"].as_bool() ? a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
+			if (cell->type == ID($sshr))
+				shifted_a = ez->vec_shift_right(a, b, false, cell->parameters[ID(A_SIGNED)].as_bool() ? a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
 
-			if (cell->type == "$shift" || cell->type == "$shiftx")
-				shifted_a = ez->vec_shift_right(a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
+			if (cell->type == ID($shift) || cell->type == ID($shiftx))
+				shifted_a = ez->vec_shift_right(a, b, cell->parameters[ID(B_SIGNED)].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
 
 			ez->assume(ez->vec_eq(shifted_a, yy));
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				std::vector<int> undef_a_shifted;
 
-				extend_bit = cell->type == "$shiftx" ? ez->CONST_TRUE : ez->CONST_FALSE;
-				if (!cell->type.in("$shift", "$shiftx") && cell->parameters["\\A_SIGNED"].as_bool())
+				extend_bit = cell->type == ID($shiftx) ? ez->CONST_TRUE : ez->CONST_FALSE;
+				if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID(A_SIGNED)].as_bool())
 					extend_bit = undef_a.back();
 
 				while (undef_y.size() < undef_a.size())
@@ -816,20 +816,20 @@ struct SatGen
 				while (undef_y.size() > undef_a.size())
 					undef_a.push_back(extend_bit);
 
-				if (cell->type == "$shl" || cell->type == "$sshl")
+				if (cell->type == ID($shl) || cell->type == ID($sshl))
 					undef_a_shifted = ez->vec_shift_left(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
 
-				if (cell->type == "$shr")
+				if (cell->type == ID($shr))
 					undef_a_shifted = ez->vec_shift_right(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
 
-				if (cell->type == "$sshr")
-					undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters["\\A_SIGNED"].as_bool() ? undef_a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
+				if (cell->type == ID($sshr))
+					undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters[ID(A_SIGNED)].as_bool() ? undef_a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
 
-				if (cell->type == "$shift")
-					undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
+				if (cell->type == ID($shift))
+					undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID(B_SIGNED)].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
 
-				if (cell->type == "$shiftx")
-					undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters["\\B_SIGNED"].as_bool(), ez->CONST_TRUE, ez->CONST_TRUE);
+				if (cell->type == ID($shiftx))
+					undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID(B_SIGNED)].as_bool(), ez->CONST_TRUE, ez->CONST_TRUE);
 
 				int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
 				std::vector<int> undef_all_y_bits(undef_y.size(), undef_any_b);
@@ -839,11 +839,11 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$mul")
+		if (cell->type == ID($mul))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			extendSignalWidth(a, b, y, cell);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
@@ -860,17 +860,17 @@ struct SatGen
 
 			if (model_undef) {
 				log_assert(arith_undef_handled);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				undefGating(y, yy, undef_y);
 			}
 			return true;
 		}
 
-		if (cell->type == "$macc")
+		if (cell->type == ID($macc))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			Macc macc;
 			macc.from_cell(cell);
@@ -919,13 +919,13 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
 
 				int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
 				int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
 
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				ez->assume(ez->vec_eq(undef_y, std::vector<int>(GetSize(y), ez->OR(undef_any_a, undef_any_b))));
 
 				undefGating(y, tmp, undef_y);
@@ -936,17 +936,17 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$div" || cell->type == "$mod")
+		if (cell->type == ID($div) || cell->type == ID($mod))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			extendSignalWidth(a, b, y, cell);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 
 			std::vector<int> a_u, b_u;
-			if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool()) {
+			if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()) {
 				a_u = ez->vec_ite(a.back(), ez->vec_neg(a), a);
 				b_u = ez->vec_ite(b.back(), ez->vec_neg(b), b);
 			} else {
@@ -971,13 +971,13 @@ struct SatGen
 			}
 
 			std::vector<int> y_tmp = ignore_div_by_zero ? yy : ez->vec_var(y.size());
-			if (cell->type == "$div") {
-				if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool())
+			if (cell->type == ID($div)) {
+				if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool())
 					ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(ez->XOR(a.back(), b.back()), ez->vec_neg(y_u), y_u)));
 				else
 					ez->assume(ez->vec_eq(y_tmp, y_u));
 			} else {
-				if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool())
+				if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool())
 					ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(a.back(), ez->vec_neg(chain_buf), chain_buf)));
 				else
 					ez->assume(ez->vec_eq(y_tmp, chain_buf));
@@ -987,20 +987,20 @@ struct SatGen
 				ez->assume(ez->expression(ezSAT::OpOr, b));
 			} else {
 				std::vector<int> div_zero_result;
-				if (cell->type == "$div") {
-					if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool()) {
+				if (cell->type == ID($div)) {
+					if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()) {
 						std::vector<int> all_ones(y.size(), ez->CONST_TRUE);
 						std::vector<int> only_first_one(y.size(), ez->CONST_FALSE);
 						only_first_one.at(0) = ez->CONST_TRUE;
 						div_zero_result = ez->vec_ite(a.back(), only_first_one, all_ones);
 					} else {
-						div_zero_result.insert(div_zero_result.end(), cell->getPort("\\A").size(), ez->CONST_TRUE);
+						div_zero_result.insert(div_zero_result.end(), cell->getPort(ID(A)).size(), ez->CONST_TRUE);
 						div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
 					}
 				} else {
-					int copy_a_bits = min(cell->getPort("\\A").size(), cell->getPort("\\B").size());
+					int copy_a_bits = min(cell->getPort(ID(A)).size(), cell->getPort(ID(B)).size());
 					div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits);
-					if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool())
+					if (cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool())
 						div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back());
 					else
 						div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
@@ -1010,19 +1010,19 @@ struct SatGen
 
 			if (model_undef) {
 				log_assert(arith_undef_handled);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				undefGating(y, yy, undef_y);
 			}
 			return true;
 		}
 
-		if (cell->type == "$lut")
+		if (cell->type == ID($lut))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			std::vector<int> lut;
-			for (auto bit : cell->getParam("\\LUT").bits)
+			for (auto bit : cell->getParam(ID(LUT)).bits)
 				lut.push_back(bit == State::S1 ? ez->CONST_TRUE : ez->CONST_FALSE);
 			while (GetSize(lut) < (1 << GetSize(a)))
 				lut.push_back(ez->CONST_FALSE);
@@ -1030,7 +1030,7 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
 				std::vector<int> t(lut), u(GetSize(t), ez->CONST_FALSE);
 
 				for (int i = GetSize(a)-1; i >= 0; i--)
@@ -1048,7 +1048,7 @@ struct SatGen
 				log_assert(GetSize(t) == 1);
 				log_assert(GetSize(u) == 1);
 				undefGating(y, t, u);
-				ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort("\\Y"), timestep), u));
+				ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort(ID(Y)), timestep), u));
 			}
 			else
 			{
@@ -1066,15 +1066,15 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$sop")
+		if (cell->type == ID($sop))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			int y = importDefSigSpec(cell->getPort("\\Y"), timestep).at(0);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			int y = importDefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
 
-			int width = cell->getParam("\\WIDTH").as_int();
-			int depth = cell->getParam("\\DEPTH").as_int();
+			int width = cell->getParam(ID(WIDTH)).as_int();
+			int depth = cell->getParam(ID(DEPTH)).as_int();
 
-			vector<State> table_raw = cell->getParam("\\TABLE").bits;
+			vector<State> table_raw = cell->getParam(ID(TABLE)).bits;
 			while (GetSize(table_raw) < 2*width*depth)
 				table_raw.push_back(State::S0);
 
@@ -1097,8 +1097,8 @@ struct SatGen
 			if (model_undef)
 			{
 				std::vector<int> products, undef_products;
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				int undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep).at(0);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				int undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep).at(0);
 
 				for (int i = 0; i < depth; i++)
 				{
@@ -1148,13 +1148,13 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$fa")
+		if (cell->type == ID($fa))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> c = importDefSigSpec(cell->getPort("\\C"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
-			std::vector<int> x = importDefSigSpec(cell->getPort("\\X"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> c = importDefSigSpec(cell->getPort(ID(C)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
+			std::vector<int> x = importDefSigSpec(cell->getPort(ID(X)), timestep);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 			std::vector<int> xx = model_undef ? ez->vec_var(x.size()) : x;
@@ -1168,12 +1168,12 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_c = importUndefSigSpec(cell->getPort(ID(C)), timestep);
 
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
-				std::vector<int> undef_x = importUndefSigSpec(cell->getPort("\\X"), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
+				std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep);
 
 				ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c)));
 				ez->assume(ez->vec_eq(undef_x, undef_y));
@@ -1184,12 +1184,12 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$lcu")
+		if (cell->type == ID($lcu))
 		{
-			std::vector<int> p = importDefSigSpec(cell->getPort("\\P"), timestep);
-			std::vector<int> g = importDefSigSpec(cell->getPort("\\G"), timestep);
-			std::vector<int> ci = importDefSigSpec(cell->getPort("\\CI"), timestep);
-			std::vector<int> co = importDefSigSpec(cell->getPort("\\CO"), timestep);
+			std::vector<int> p = importDefSigSpec(cell->getPort(ID(P)), timestep);
+			std::vector<int> g = importDefSigSpec(cell->getPort(ID(G)), timestep);
+			std::vector<int> ci = importDefSigSpec(cell->getPort(ID(CI)), timestep);
+			std::vector<int> co = importDefSigSpec(cell->getPort(ID(CO)), timestep);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(co.size()) : co;
 
@@ -1198,10 +1198,10 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_p = importUndefSigSpec(cell->getPort("\\P"), timestep);
-				std::vector<int> undef_g = importUndefSigSpec(cell->getPort("\\G"), timestep);
-				std::vector<int> undef_ci = importUndefSigSpec(cell->getPort("\\CI"), timestep);
-				std::vector<int> undef_co = importUndefSigSpec(cell->getPort("\\CO"), timestep);
+				std::vector<int> undef_p = importUndefSigSpec(cell->getPort(ID(P)), timestep);
+				std::vector<int> undef_g = importUndefSigSpec(cell->getPort(ID(G)), timestep);
+				std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID(CI)), timestep);
+				std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID(CO)), timestep);
 
 				int undef_any_p = ez->expression(ezSAT::OpOr, undef_p);
 				int undef_any_g = ez->expression(ezSAT::OpOr, undef_g);
@@ -1216,15 +1216,15 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$alu")
+		if (cell->type == ID($alu))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
-			std::vector<int> x = importDefSigSpec(cell->getPort("\\X"), timestep);
-			std::vector<int> ci = importDefSigSpec(cell->getPort("\\CI"), timestep);
-			std::vector<int> bi = importDefSigSpec(cell->getPort("\\BI"), timestep);
-			std::vector<int> co = importDefSigSpec(cell->getPort("\\CO"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> b = importDefSigSpec(cell->getPort(ID(B)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
+			std::vector<int> x = importDefSigSpec(cell->getPort(ID(X)), timestep);
+			std::vector<int> ci = importDefSigSpec(cell->getPort(ID(CI)), timestep);
+			std::vector<int> bi = importDefSigSpec(cell->getPort(ID(BI)), timestep);
+			std::vector<int> co = importDefSigSpec(cell->getPort(ID(CO)), timestep);
 
 			extendSignalWidth(a, b, y, cell);
 			extendSignalWidth(a, b, x, cell);
@@ -1249,14 +1249,14 @@ struct SatGen
 
 			if (model_undef)
 			{
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
-				std::vector<int> undef_ci = importUndefSigSpec(cell->getPort("\\CI"), timestep);
-				std::vector<int> undef_bi = importUndefSigSpec(cell->getPort("\\BI"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID(B)), timestep);
+				std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID(CI)), timestep);
+				std::vector<int> undef_bi = importUndefSigSpec(cell->getPort(ID(BI)), timestep);
 
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
-				std::vector<int> undef_x = importUndefSigSpec(cell->getPort("\\X"), timestep);
-				std::vector<int> undef_co = importUndefSigSpec(cell->getPort("\\CO"), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
+				std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID(X)), timestep);
+				std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID(CO)), timestep);
 
 				extendSignalWidth(undef_a, undef_b, undef_y, cell);
 				extendSignalWidth(undef_a, undef_b, undef_x, cell);
@@ -1282,19 +1282,19 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$slice")
+		if (cell->type == ID($slice))
 		{
-			RTLIL::SigSpec a = cell->getPort("\\A");
-			RTLIL::SigSpec y = cell->getPort("\\Y");
-			ez->assume(signals_eq(a.extract(cell->parameters.at("\\OFFSET").as_int(), y.size()), y, timestep));
+			RTLIL::SigSpec a = cell->getPort(ID(A));
+			RTLIL::SigSpec y = cell->getPort(ID(Y));
+			ez->assume(signals_eq(a.extract(cell->parameters.at(ID(OFFSET)).as_int(), y.size()), y, timestep));
 			return true;
 		}
 
-		if (cell->type == "$concat")
+		if (cell->type == ID($concat))
 		{
-			RTLIL::SigSpec a = cell->getPort("\\A");
-			RTLIL::SigSpec b = cell->getPort("\\B");
-			RTLIL::SigSpec y = cell->getPort("\\Y");
+			RTLIL::SigSpec a = cell->getPort(ID(A));
+			RTLIL::SigSpec b = cell->getPort(ID(B));
+			RTLIL::SigSpec y = cell->getPort(ID(Y));
 
 			RTLIL::SigSpec ab = a;
 			ab.append(b);
@@ -1303,24 +1303,24 @@ struct SatGen
 			return true;
 		}
 
-		if (timestep > 0 && cell->type.in("$ff", "$dff", "$_FF_", "$_DFF_N_", "$_DFF_P_"))
+		if (timestep > 0 && cell->type.in(ID($ff), ID($dff), ID($_FF_), ID($_DFF_N_), ID($_DFF_P_)))
 		{
 			if (timestep == 1)
 			{
-				initial_state.add((*sigmap)(cell->getPort("\\Q")));
+				initial_state.add((*sigmap)(cell->getPort(ID(Q))));
 			}
 			else
 			{
-				std::vector<int> d = importDefSigSpec(cell->getPort("\\D"), timestep-1);
-				std::vector<int> q = importDefSigSpec(cell->getPort("\\Q"), timestep);
+				std::vector<int> d = importDefSigSpec(cell->getPort(ID(D)), timestep-1);
+				std::vector<int> q = importDefSigSpec(cell->getPort(ID(Q)), timestep);
 
 				std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
 				ez->assume(ez->vec_eq(d, qq));
 
 				if (model_undef)
 				{
-					std::vector<int> undef_d = importUndefSigSpec(cell->getPort("\\D"), timestep-1);
-					std::vector<int> undef_q = importUndefSigSpec(cell->getPort("\\Q"), timestep);
+					std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID(D)), timestep-1);
+					std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID(Q)), timestep);
 
 					ez->assume(ez->vec_eq(undef_d, undef_q));
 					undefGating(q, qq, undef_q);
@@ -1329,21 +1329,21 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$anyconst")
+		if (cell->type == ID($anyconst))
 		{
 			if (timestep < 2)
 				return true;
 
-			std::vector<int> d = importDefSigSpec(cell->getPort("\\Y"), timestep-1);
-			std::vector<int> q = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> d = importDefSigSpec(cell->getPort(ID(Y)), timestep-1);
+			std::vector<int> q = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 
 			std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
 			ez->assume(ez->vec_eq(d, qq));
 
 			if (model_undef)
 			{
-				std::vector<int> undef_d = importUndefSigSpec(cell->getPort("\\Y"), timestep-1);
-				std::vector<int> undef_q = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID(Y)), timestep-1);
+				std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 
 				ez->assume(ez->vec_eq(undef_d, undef_q));
 				undefGating(q, qq, undef_q);
@@ -1351,23 +1351,23 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$anyseq")
+		if (cell->type == ID($anyseq))
 		{
 			return true;
 		}
 
-		if (cell->type == "$_BUF_" || cell->type == "$equiv")
+		if (cell->type == ID($_BUF_) || cell->type == ID($equiv))
 		{
-			std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> a = importDefSigSpec(cell->getPort(ID(A)), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			extendSignalWidthUnary(a, y, cell);
 
 			std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
 			ez->assume(ez->vec_eq(a, yy));
 
 			if (model_undef) {
-				std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID(A)), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				extendSignalWidthUnary(undef_a, undef_y, cell, false);
 				ez->assume(ez->vec_eq(undef_a, undef_y));
 				undefGating(y, yy, undef_y);
@@ -1375,18 +1375,18 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$initstate")
+		if (cell->type == ID($initstate))
 		{
 			auto key = make_pair(prefix, timestep);
 			if (initstates.count(key) == 0)
 				initstates[key] = false;
 
-			std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+			std::vector<int> y = importDefSigSpec(cell->getPort(ID(Y)), timestep);
 			log_assert(GetSize(y) == 1);
 			ez->SET(y[0], initstates[key] ? ez->CONST_TRUE : ez->CONST_FALSE);
 
 			if (model_undef) {
-				std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+				std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID(Y)), timestep);
 				log_assert(GetSize(undef_y) == 1);
 				ez->SET(undef_y[0], ez->CONST_FALSE);
 			}
@@ -1394,19 +1394,19 @@ struct SatGen
 			return true;
 		}
 
-		if (cell->type == "$assert")
+		if (cell->type == ID($assert))
 		{
 			std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
-			asserts_a[pf].append((*sigmap)(cell->getPort("\\A")));
-			asserts_en[pf].append((*sigmap)(cell->getPort("\\EN")));
+			asserts_a[pf].append((*sigmap)(cell->getPort(ID(A))));
+			asserts_en[pf].append((*sigmap)(cell->getPort(ID(EN))));
 			return true;
 		}
 
-		if (cell->type == "$assume")
+		if (cell->type == ID($assume))
 		{
 			std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
-			assumes_a[pf].append((*sigmap)(cell->getPort("\\A")));
-			assumes_en[pf].append((*sigmap)(cell->getPort("\\EN")));
+			assumes_a[pf].append((*sigmap)(cell->getPort(ID(A))));
+			assumes_en[pf].append((*sigmap)(cell->getPort(ID(EN))));
 			return true;
 		}
 
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index 5a53f90fd..747f2d739 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -510,10 +510,13 @@ void yosys_setup()
 	if(already_setup)
 		return;
 	already_setup = true;
-	// if there are already IdString objects then we have a global initialization order bug
-	IdString empty_id;
-	log_assert(empty_id.index_ == 0);
-	IdString::get_reference(empty_id.index_);
+
+	RTLIL::ID::A = "\\A";
+	RTLIL::ID::B = "\\B";
+	RTLIL::ID::Y = "\\Y";
+	RTLIL::ID::keep = "\\keep";
+	RTLIL::ID::whitebox = "\\whitebox";
+	RTLIL::ID::blackbox = "\\blackbox";
 
 	#ifdef WITH_PYTHON
 		PyImport_AppendInittab((char*)"libyosys", INIT_MODULE);
@@ -575,9 +578,6 @@ void yosys_shutdown()
 #ifdef WITH_PYTHON
 	Py_Finalize();
 #endif
-
-	IdString empty_id;
-	IdString::put_reference(empty_id.index_);
 }
 
 RTLIL::IdString new_id(std::string file, int line, std::string func)
diff --git a/kernel/yosys.h b/kernel/yosys.h
index 09e8139bb..49716ed52 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -305,8 +305,16 @@ RTLIL::IdString new_id(std::string file, int line, std::string func);
 #define NEW_ID \
 	YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__)
 
-#define ID(_str) \
-	([]() { static YOSYS_NAMESPACE_PREFIX RTLIL::IdString _id(_str); return _id; })()
+// Create a statically allocated IdString object, using for example ID(A) or ID($add).
+//
+// Recipe for Converting old code that is using conversion of strings like "\\A" and
+// "$add" for creating IdStrings: Run below SED command on the .cc file and then use for
+// example "meld foo.cc foo.cc.orig" to manually compile errors, if necessary.
+//
+//  sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' <filename>
+//
+#define ID(_id) ([]() { const char *p = "\\" #_id, *q = p[1] == '$' ? p+1 : p; \
+        static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
 
 RTLIL::Design *yosys_get_design();
 std::string proc_self_dirname();
diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc
index 225c30d9a..cf6752b6e 100644
--- a/passes/opt/muxpack.cc
+++ b/passes/opt/muxpack.cc
@@ -37,22 +37,22 @@ struct ExclusiveDatabase
 		SigBit y_port;
 		pool<Cell*> reduce_or;
 		for (auto cell : module->cells()) {
-			if (cell->type == "$eq") {
-				nonconst_sig = sigmap(cell->getPort("\\A"));
-				const_sig = sigmap(cell->getPort("\\B"));
+			if (cell->type == ID($eq)) {
+				nonconst_sig = sigmap(cell->getPort(ID(A)));
+				const_sig = sigmap(cell->getPort(ID(B)));
 				if (!const_sig.is_fully_const()) {
 					if (!nonconst_sig.is_fully_const())
 						continue;
 					std::swap(nonconst_sig, const_sig);
 				}
-				y_port = sigmap(cell->getPort("\\Y"));
+				y_port = sigmap(cell->getPort(ID(Y)));
 			}
-			else if (cell->type == "$logic_not") {
-				nonconst_sig = sigmap(cell->getPort("\\A"));
+			else if (cell->type == ID($logic_not)) {
+				nonconst_sig = sigmap(cell->getPort(ID(A)));
 				const_sig = Const(State::S0, GetSize(nonconst_sig));
-				y_port = sigmap(cell->getPort("\\Y"));
+				y_port = sigmap(cell->getPort(ID(Y)));
 			}
-			else if (cell->type == "$reduce_or") {
+			else if (cell->type == ID($reduce_or)) {
 				reduce_or.insert(cell);
 				continue;
 			}
@@ -66,7 +66,7 @@ struct ExclusiveDatabase
 		for (auto cell : reduce_or) {
 			nonconst_sig = SigSpec();
 			std::vector<Const> values;
-			SigSpec a_port = sigmap(cell->getPort("\\A"));
+			SigSpec a_port = sigmap(cell->getPort(ID(A)));
 			for (auto bit : a_port) {
 				auto it = sig_cmp_prev.find(bit);
 				if (it == sig_cmp_prev.end()) {
@@ -84,7 +84,7 @@ struct ExclusiveDatabase
 			}
 			if (nonconst_sig.empty())
 				continue;
-			y_port = sigmap(cell->getPort("\\Y"));
+			y_port = sigmap(cell->getPort(ID(Y)));
 			sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values));
 		}
 	}
@@ -135,7 +135,7 @@ struct MuxpackWorker
 	{
 		for (auto wire : module->wires())
 		{
-			if (wire->port_output || wire->get_bool_attribute("\\keep")) {
+			if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
 				for (auto bit : sigmap(wire))
 					sigbit_with_non_chain_users.insert(bit);
 			}
@@ -143,13 +143,13 @@ struct MuxpackWorker
 
 		for (auto cell : module->cells())
 		{
-			if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep"))
+			if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID(keep)))
 			{
-				SigSpec a_sig = sigmap(cell->getPort("\\A"));
+				SigSpec a_sig = sigmap(cell->getPort(ID(A)));
 				SigSpec b_sig;
-				if (cell->type == "$mux")
-					b_sig = sigmap(cell->getPort("\\B"));
-				SigSpec y_sig = sigmap(cell->getPort("\\Y"));
+				if (cell->type == ID($mux))
+					b_sig = sigmap(cell->getPort(ID(B)));
+				SigSpec y_sig = sigmap(cell->getPort(ID(Y)));
    
 				if (sig_chain_next.count(a_sig))
 					for (auto a_bit : a_sig.bits())
@@ -186,16 +186,16 @@ struct MuxpackWorker
 		{
 			log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
 
-			SigSpec a_sig = sigmap(cell->getPort("\\A"));
-			if (cell->type == "$mux") {
-				SigSpec b_sig = sigmap(cell->getPort("\\B"));
+			SigSpec a_sig = sigmap(cell->getPort(ID(A)));
+			if (cell->type == ID($mux)) {
+				SigSpec b_sig = sigmap(cell->getPort(ID(B)));
 				if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
 					goto start_cell;
 
 				if (!sig_chain_prev.count(a_sig))
 					a_sig = b_sig;
 			}
-			else if (cell->type == "$pmux") {
+			else if (cell->type == ID($pmux)) {
 				if (!sig_chain_prev.count(a_sig))
 					goto start_cell;
 			}
@@ -208,8 +208,8 @@ struct MuxpackWorker
 			{
 				Cell *prev_cell = sig_chain_prev.at(a_sig);
 				log_assert(prev_cell);
-				SigSpec s_sig = sigmap(cell->getPort("\\S"));
-				s_sig.append(sigmap(prev_cell->getPort("\\S")));
+				SigSpec s_sig = sigmap(cell->getPort(ID(S)));
+				s_sig.append(sigmap(prev_cell->getPort(ID(S))));
 				if (!excl_db.query(s_sig))
 					goto start_cell;
 			}
@@ -230,7 +230,7 @@ struct MuxpackWorker
 		{
 			chain.push_back(c);
 
-			SigSpec y_sig = sigmap(c->getPort("\\Y"));
+			SigSpec y_sig = sigmap(c->getPort(ID(Y)));
 
 			if (sig_chain_next.count(y_sig) == 0)
 				break;
@@ -269,29 +269,29 @@ struct MuxpackWorker
 			mux_count += cases;
 			pmux_count += 1;
 
-			first_cell->type = "$pmux";
-			SigSpec b_sig = first_cell->getPort("\\B");
-			SigSpec s_sig = first_cell->getPort("\\S");
+			first_cell->type = ID($pmux);
+			SigSpec b_sig = first_cell->getPort(ID(B));
+			SigSpec s_sig = first_cell->getPort(ID(S));
 
 			for (int i = 1; i < cases; i++) {
 				Cell* prev_cell = chain[cursor+i-1];
 				Cell* cursor_cell = chain[cursor+i];
-				if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) {
-					b_sig.append(cursor_cell->getPort("\\B"));
-					s_sig.append(cursor_cell->getPort("\\S"));
+				if (sigmap(prev_cell->getPort(ID(Y))) == sigmap(cursor_cell->getPort(ID(A)))) {
+					b_sig.append(cursor_cell->getPort(ID(B)));
+					s_sig.append(cursor_cell->getPort(ID(S)));
 				}
 				else {
-					log_assert(cursor_cell->type == "$mux");
-					b_sig.append(cursor_cell->getPort("\\A"));
-					s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S")));
+					log_assert(cursor_cell->type == ID($mux));
+					b_sig.append(cursor_cell->getPort(ID(A)));
+					s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S))));
 				}
 				remove_cells.insert(cursor_cell);
 			}
 
-			first_cell->setPort("\\B", b_sig);
-			first_cell->setPort("\\S", s_sig);
-			first_cell->setParam("\\S_WIDTH", GetSize(s_sig));
-			first_cell->setPort("\\Y", last_cell->getPort("\\Y"));
+			first_cell->setPort(ID(B), b_sig);
+			first_cell->setPort(ID(S), s_sig);
+			first_cell->setParam(ID(S_WIDTH), GetSize(s_sig));
+			first_cell->setPort(ID(Y), last_cell->getPort(ID(Y)));
 
 			cursor += cases;
 		}
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 905c95b6c..1d3a85b3a 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -52,7 +52,7 @@ struct keep_cache_t
 			return cache.at(module);
 
 		cache[module] = true;
-		if (!module->get_bool_attribute("\\keep")) {
+		if (!module->get_bool_attribute(ID(keep))) {
 			bool found_keep = false;
 			for (auto cell : module->cells())
 				if (query(cell)) found_keep = true;
@@ -64,7 +64,7 @@ struct keep_cache_t
 
 	bool query(Cell *cell)
 	{
-		if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule"))
+		if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover), ID($specify2), ID($specify3), ID($specrule)))
 			return true;
 
 		if (cell->has_keep_attr())
@@ -122,7 +122,7 @@ void rmunused_module_cells(Module *module, bool verbose)
 
 	for (auto &it : module->wires_) {
 		Wire *wire = it.second;
-		if (wire->port_output || wire->get_bool_attribute("\\keep")) {
+		if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
 			for (auto bit : sigmap(wire))
 			for (auto c : wire2driver[bit])
 				queue.insert(c), unused.erase(c);
@@ -177,8 +177,8 @@ void rmunused_module_cells(Module *module, bool verbose)
 int count_nontrivial_wire_attrs(RTLIL::Wire *w)
 {
 	int count = w->attributes.size();
-	count -= w->attributes.count("\\src");
-	count -= w->attributes.count("\\unused_bits");
+	count -= w->attributes.count(ID(src));
+	count -= w->attributes.count(ID(unused_bits));
 	return count;
 }
 
@@ -297,7 +297,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 			if (!wire->port_input)
 				used_signals_nodrivers.add(sig);
 		}
-		if (wire->get_bool_attribute("\\keep")) {
+		if (wire->get_bool_attribute(ID(keep))) {
 			RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
 			assign_map.apply(sig);
 			used_signals.add(sig);
@@ -311,19 +311,19 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 		log_assert(GetSize(s1) == GetSize(s2));
 
 		Const initval;
-		if (wire->attributes.count("\\init"))
-			initval = wire->attributes.at("\\init");
+		if (wire->attributes.count(ID(init)))
+			initval = wire->attributes.at(ID(init));
 		if (GetSize(initval) != GetSize(wire))
 			initval.bits.resize(GetSize(wire), State::Sx);
 		if (initval.is_fully_undef())
-			wire->attributes.erase("\\init");
+			wire->attributes.erase(ID(init));
 
 		if (GetSize(wire) == 0) {
 			// delete zero-width wires, unless they are module ports
 			if (wire->port_id == 0)
 				goto delete_this_wire;
 		} else
-		if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) {
+		if (wire->port_id != 0 || wire->get_bool_attribute(ID(keep)) || !initval.is_fully_undef()) {
 			// do not delete anything with "keep" or module ports or initialized wires
 		} else
 		if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) {
@@ -357,9 +357,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 				}
 			if (new_conn.first.size() > 0) {
 				if (initval.is_fully_undef())
-					wire->attributes.erase("\\init");
+					wire->attributes.erase(ID(init));
 				else
-					wire->attributes.at("\\init") = initval;
+					wire->attributes.at(ID(init)) = initval;
 				used_signals.add(new_conn.first);
 				used_signals.add(new_conn.second);
 				module->connect(new_conn);
@@ -377,11 +377,11 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 					}
 				}
 				if (unused_bits.empty() || wire->port_id != 0)
-					wire->attributes.erase("\\unused_bits");
+					wire->attributes.erase(ID(unused_bits));
 				else
-					wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits);
+					wire->attributes[ID(unused_bits)] = RTLIL::Const(unused_bits);
 			} else {
-				wire->attributes.erase("\\unused_bits");
+				wire->attributes.erase(ID(unused_bits));
 			}
 		}
 	}
@@ -413,18 +413,18 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 	dict<SigBit, State> qbits;
 
 	for (auto cell : module->cells())
-		if (fftypes.cell_known(cell->type) && cell->hasPort("\\Q"))
+		if (fftypes.cell_known(cell->type) && cell->hasPort(ID(Q)))
 		{
-			SigSpec sig = cell->getPort("\\Q");
+			SigSpec sig = cell->getPort(ID(Q));
 
 			for (int i = 0; i < GetSize(sig); i++)
 			{
 				SigBit bit = sig[i];
 
-				if (bit.wire == nullptr || bit.wire->attributes.count("\\init") == 0)
+				if (bit.wire == nullptr || bit.wire->attributes.count(ID(init)) == 0)
 					continue;
 
-				Const init = bit.wire->attributes.at("\\init");
+				Const init = bit.wire->attributes.at(ID(init));
 
 				if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz)
 					continue;
@@ -439,10 +439,10 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 		if (!purge_mode && wire->name[0] == '\\')
 			continue;
 
-		if (wire->attributes.count("\\init") == 0)
+		if (wire->attributes.count(ID(init)) == 0)
 			continue;
 
-		Const init = wire->attributes.at("\\init");
+		Const init = wire->attributes.at(ID(init));
 
 		for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++)
 		{
@@ -465,7 +465,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 		if (verbose)
 			log_debug("  removing redundant init attribute on %s.\n", log_id(wire));
 
-		wire->attributes.erase("\\init");
+		wire->attributes.erase(ID(init));
 		did_something = true;
 	next_wire:;
 	}
@@ -480,10 +480,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
 
 	std::vector<RTLIL::Cell*> delcells;
 	for (auto cell : module->cells())
-		if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) {
-			bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool();
-			RTLIL::SigSpec a = cell->getPort("\\A");
-			RTLIL::SigSpec y = cell->getPort("\\Y");
+		if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) {
+			bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool();
+			RTLIL::SigSpec a = cell->getPort(ID(A));
+			RTLIL::SigSpec y = cell->getPort(ID(Y));
 			a.extend_u0(GetSize(y), is_signed);
 			module->connect(y, a);
 			delcells.push_back(cell);
@@ -491,7 +491,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
 	for (auto cell : delcells) {
 		if (verbose)
 			log_debug("  removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
-					log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A")));
+					log_signal(cell->getPort(ID(Y))), log_signal(cell->getPort(ID(A))));
 		module->remove(cell);
 	}
 	if (!delcells.empty())
diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc
index 1699a6454..7defef442 100644
--- a/passes/opt/opt_demorgan.cc
+++ b/passes/opt/opt_demorgan.cc
@@ -35,10 +35,10 @@ void demorgan_worker(
 	//TODO: Add support for reduce_xor
 	//DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number)
 
-	if( (cell->type != "$reduce_and") && (cell->type != "$reduce_or") )
+	if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) )
 		return;
 
-	auto insig = sigmap(cell->getPort("\\A"));
+	auto insig = sigmap(cell->getPort(ID(A)));
 	log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig));
 	int num_inverted = 0;
 	for(int i=0; i<GetSize(insig); i++)
@@ -51,7 +51,7 @@ void demorgan_worker(
 		bool inverted = false;
 		for(auto x : ports)
 		{
-			if(x.port == "\\Y" && x.cell->type == "$_NOT_")
+			if(x.port == ID(Y) && x.cell->type == ID($_NOT_))
 			{
 				inverted = true;
 				break;
@@ -85,7 +85,7 @@ void demorgan_worker(
 		RTLIL::Cell* srcinv = NULL;
 		for(auto x : ports)
 		{
-			if(x.port == "\\Y" && x.cell->type == "$_NOT_")
+			if(x.port == ID(Y) && x.cell->type == ID($_NOT_))
 			{
 				srcinv = x.cell;
 				break;
@@ -103,7 +103,7 @@ void demorgan_worker(
 		//We ARE inverted - bypass it
 		//Don't automatically delete the inverter since other stuff might still use it
 		else
-			insig[i] = srcinv->getPort("\\A");
+			insig[i] = srcinv->getPort(ID(A));
 	}
 
 	//Cosmetic fixup: If our input is just a scrambled version of one bus, rearrange it
@@ -151,20 +151,20 @@ void demorgan_worker(
 	}
 
 	//Push the new input signal back to the reduction (after bypassing/adding inverters)
-	cell->setPort("\\A", insig);
+	cell->setPort(ID(A), insig);
 
 	//Change the cell type
-	if(cell->type == "$reduce_and")
-		cell->type = "$reduce_or";
-	else if(cell->type == "$reduce_or")
-		cell->type = "$reduce_and";
+	if(cell->type == ID($reduce_and))
+		cell->type = ID($reduce_or);
+	else if(cell->type == ID($reduce_or))
+		cell->type = ID($reduce_and);
 	//don't change XOR
 
 	//Add an inverter to the output
-	auto inverted_output = cell->getPort("\\Y");
+	auto inverted_output = cell->getPort(ID(Y));
 	auto uninverted_output = m->addWire(NEW_ID);
 	m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output);
-	cell->setPort("\\Y", uninverted_output);
+	cell->setPort(ID(Y), uninverted_output);
 }
 
 struct OptDemorganPass : public Pass {
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 1512cea1b..cb89e90ca 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -51,9 +51,9 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
 	}
 
 	for (auto wire : module->wires()) {
-		if (wire->attributes.count("\\init")) {
+		if (wire->attributes.count(ID(init))) {
 			SigSpec sig = sigmap(wire);
-			Const initval = wire->attributes.at("\\init");
+			Const initval = wire->attributes.at(ID(init));
 			for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) {
 				if (initval[i] == State::S0 || initval[i] == State::S1)
 					initbits[sig[i]] = make_pair(wire, initval[i]);
@@ -61,7 +61,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
 		}
 		if (wire->port_input)
 			driven_signals.add(sigmap(wire));
-		if (wire->port_output || wire->get_bool_attribute("\\keep"))
+		if (wire->port_output || wire->get_bool_attribute(ID(keep)))
 			used_signals.add(sigmap(wire));
 		all_signals.add(sigmap(wire));
 	}
@@ -99,18 +99,18 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
 
 		for (auto wire : revisit_initwires) {
 			SigSpec sig = sm2(wire);
-			Const initval = wire->attributes.at("\\init");
+			Const initval = wire->attributes.at(ID(init));
 			for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) {
 				if (SigBit(initval[i]) == sig[i])
 					initval[i] = State::Sx;
 			}
 			if (initval.is_fully_undef()) {
 				log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire));
-				wire->attributes.erase("\\init");
+				wire->attributes.erase(ID(init));
 				did_something = true;
-			} else if (initval != wire->attributes.at("\\init")) {
+			} else if (initval != wire->attributes.at(ID(init))) {
 				log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval));
-				wire->attributes["\\init"] = initval;
+				wire->attributes[ID(init)] = initval;
 				did_something = true;
 			}
 		}
@@ -135,14 +135,14 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
 
 bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap)
 {
-	std::string b_name = cell->hasPort("\\B") ? "\\B" : "\\A";
+	IdString b_name = cell->hasPort(ID(B)) ? ID(B) : ID(A);
 
-	bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
-	bool b_signed = cell->parameters.at(b_name + "_SIGNED").as_bool();
+	bool a_signed = cell->parameters.at(ID(A_SIGNED)).as_bool();
+	bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool();
 
-	RTLIL::SigSpec sig_a = sigmap(cell->getPort("\\A"));
+	RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID(A)));
 	RTLIL::SigSpec sig_b = sigmap(cell->getPort(b_name));
-	RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y"));
+	RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID(Y)));
 
 	sig_a.extend_u0(sig_y.size(), a_signed);
 	sig_b.extend_u0(sig_y.size(), b_signed);
@@ -157,10 +157,10 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
 		int group_idx = GRP_DYN;
 		RTLIL::SigBit bit_a = bits_a[i], bit_b = bits_b[i];
 
-		if (cell->type == "$or" && (bit_a == RTLIL::State::S1 || bit_b == RTLIL::State::S1))
+		if (cell->type == ID($or) && (bit_a == RTLIL::State::S1 || bit_b == RTLIL::State::S1))
 			bit_a = bit_b = RTLIL::State::S1;
 
-		if (cell->type == "$and" && (bit_a == RTLIL::State::S0 || bit_b == RTLIL::State::S0))
+		if (cell->type == ID($and) && (bit_a == RTLIL::State::S0 || bit_b == RTLIL::State::S0))
 			bit_a = bit_b = RTLIL::State::S0;
 
 		if (bit_a.wire == NULL && bit_b.wire == NULL)
@@ -200,7 +200,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
 			new_b.append_bit(it.first.second);
 		}
 
-		if (cell->type.in("$and", "$or") && i == GRP_CONST_A) {
+		if (cell->type.in(ID($and), ID($or)) && i == GRP_CONST_A) {
 			log_debug("  Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a));
 			module->connect(new_y, new_b);
 			module->connect(new_conn);
@@ -209,24 +209,24 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
 
 		RTLIL::Cell *c = module->addCell(NEW_ID, cell->type);
 
-		c->setPort("\\A", new_a);
-		c->parameters["\\A_WIDTH"] = new_a.size();
-		c->parameters["\\A_SIGNED"] = false;
+		c->setPort(ID(A), new_a);
+		c->parameters[ID(A_WIDTH)] = new_a.size();
+		c->parameters[ID(A_SIGNED)] = false;
 
-		if (b_name == "\\B") {
-			c->setPort("\\B", new_b);
-			c->parameters["\\B_WIDTH"] = new_b.size();
-			c->parameters["\\B_SIGNED"] = false;
+		if (b_name == ID(B)) {
+			c->setPort(ID(B), new_b);
+			c->parameters[ID(B_WIDTH)] = new_b.size();
+			c->parameters[ID(B_SIGNED)] = false;
 		}
 
-		c->setPort("\\Y", new_y);
-		c->parameters["\\Y_WIDTH"] = new_y->width;
+		c->setPort(ID(Y), new_y);
+		c->parameters[ID(Y_WIDTH)] = new_y->width;
 		c->check();
 
 		module->connect(new_conn);
 
 		log_debug("  New cell `%s': A=%s", log_id(c), log_signal(new_a));
-		if (b_name == "\\B")
+		if (b_name == ID(B))
 			log_debug(", B=%s", log_signal(new_b));
 		log_debug("\n");
 	}
@@ -368,12 +368,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
 	for (auto cell : module->cells())
 		if (design->selected(module, cell) && cell->type[0] == '$') {
-			if (cell->type.in("$_NOT_", "$not", "$logic_not") &&
-					cell->getPort("\\A").size() == 1 && cell->getPort("\\Y").size() == 1)
-				invert_map[assign_map(cell->getPort("\\Y"))] = assign_map(cell->getPort("\\A"));
-			if (cell->type.in("$mux", "$_MUX_") &&
-					cell->getPort("\\A") == SigSpec(State::S1) && cell->getPort("\\B") == SigSpec(State::S0))
-				invert_map[assign_map(cell->getPort("\\Y"))] = assign_map(cell->getPort("\\S"));
+			if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) &&
+					cell->getPort(ID(A)).size() == 1 && cell->getPort(ID(Y)).size() == 1)
+				invert_map[assign_map(cell->getPort(ID(Y)))] = assign_map(cell->getPort(ID(A)));
+			if (cell->type.in(ID($mux), ID($_MUX_)) &&
+					cell->getPort(ID(A)) == SigSpec(State::S1) && cell->getPort(ID(B)) == SigSpec(State::S0))
+				invert_map[assign_map(cell->getPort(ID(Y)))] = assign_map(cell->getPort(ID(S)));
 			if (ct_combinational.cell_known(cell->type))
 				for (auto &conn : cell->connections()) {
 					RTLIL::SigSpec sig = assign_map(conn.second);
@@ -397,66 +397,66 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 	for (auto cell : cells.sorted)
 	{
 #define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
-#define ACTION_DO_Y(_v_) ACTION_DO("\\Y", RTLIL::SigSpec(RTLIL::State::S ## _v_))
+#define ACTION_DO_Y(_v_) ACTION_DO(ID(Y), RTLIL::SigSpec(RTLIL::State::S ## _v_))
 
 		if (clkinv)
 		{
-			if (cell->type.in("$dff", "$dffe", "$dffsr", "$adff", "$fsm", "$memrd", "$memwr"))
-				handle_polarity_inv(cell, "\\CLK", "\\CLK_POLARITY", assign_map, invert_map);
+			if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($adff), ID($fsm), ID($memrd), ID($memwr)))
+				handle_polarity_inv(cell, ID(CLK), ID(CLK_POLARITY), assign_map, invert_map);
 
-			if (cell->type.in("$sr", "$dffsr", "$dlatchsr")) {
-				handle_polarity_inv(cell, "\\SET", "\\SET_POLARITY", assign_map, invert_map);
-				handle_polarity_inv(cell, "\\CLR", "\\CLR_POLARITY", assign_map, invert_map);
+			if (cell->type.in(ID($sr), ID($dffsr), ID($dlatchsr))) {
+				handle_polarity_inv(cell, ID(SET), ID(SET_POLARITY), assign_map, invert_map);
+				handle_polarity_inv(cell, ID(CLR), ID(CLR_POLARITY), assign_map, invert_map);
 			}
 
-			if (cell->type.in("$dffe", "$dlatch", "$dlatchsr"))
-				handle_polarity_inv(cell, "\\EN", "\\EN_POLARITY", assign_map, invert_map);
+			if (cell->type.in(ID($dffe), ID($dlatch), ID($dlatchsr)))
+				handle_polarity_inv(cell, ID(EN), ID(EN_POLARITY), assign_map, invert_map);
 
-			handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", "\\S", assign_map, invert_map);
-			handle_clkpol_celltype_swap(cell, "$_SR_?N_", "$_SR_?P_", "\\R", assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID(S), assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_SR_?N_", "$_SR_?P_", ID(R), assign_map, invert_map);
 
-			handle_clkpol_celltype_swap(cell, "$_DFF_N_", "$_DFF_P_", "\\C", assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFF_N_", "$_DFF_P_", ID(C), assign_map, invert_map);
 
-			handle_clkpol_celltype_swap(cell, "$_DFFE_N?_", "$_DFFE_P?_", "\\C", assign_map, invert_map);
-			handle_clkpol_celltype_swap(cell, "$_DFFE_?N_", "$_DFFE_?P_", "\\E", assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFFE_N?_", "$_DFFE_P?_", ID(C), assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFFE_?N_", "$_DFFE_?P_", ID(E), assign_map, invert_map);
 
-			handle_clkpol_celltype_swap(cell, "$_DFF_N??_", "$_DFF_P??_", "\\C", assign_map, invert_map);
-			handle_clkpol_celltype_swap(cell, "$_DFF_?N?_", "$_DFF_?P?_", "\\R", assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFF_N??_", "$_DFF_P??_", ID(C), assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFF_?N?_", "$_DFF_?P?_", ID(R), assign_map, invert_map);
 
-			handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", "\\C", assign_map, invert_map);
-			handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", "\\S", assign_map, invert_map);
-			handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", "\\R", assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", ID(C), assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", ID(S), assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", ID(R), assign_map, invert_map);
 
-			handle_clkpol_celltype_swap(cell, "$_DLATCH_N_", "$_DLATCH_P_", "\\E", assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DLATCH_N_", "$_DLATCH_P_", ID(E), assign_map, invert_map);
 
-			handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", "\\E", assign_map, invert_map);
-			handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", "\\S", assign_map, invert_map);
-			handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", "\\R", assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", ID(E), assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", ID(S), assign_map, invert_map);
+			handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID(R), assign_map, invert_map);
 		}
 
 		bool detect_const_and = false;
 		bool detect_const_or = false;
 
-		if (cell->type.in("$reduce_and", "$_AND_"))
+		if (cell->type.in(ID($reduce_and), ID($_AND_)))
 			detect_const_and = true;
 
-		if (cell->type.in("$and", "$logic_and") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1 && !cell->getParam("\\A_SIGNED").as_bool())
+		if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())
 			detect_const_and = true;
 
-		if (cell->type.in("$reduce_or", "$reduce_bool", "$_OR_"))
+		if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($_OR_)))
 			detect_const_or = true;
 
-		if (cell->type.in("$or", "$logic_or") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1 && !cell->getParam("\\A_SIGNED").as_bool())
+		if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())
 			detect_const_or = true;
 
 		if (detect_const_and || detect_const_or)
 		{
-			pool<SigBit> input_bits = assign_map(cell->getPort("\\A")).to_sigbit_pool();
+			pool<SigBit> input_bits = assign_map(cell->getPort(ID(A))).to_sigbit_pool();
 			bool found_zero = false, found_one = false, found_undef = false, found_inv = false, many_conconst = false;
 			SigBit non_const_input = State::Sm;
 
-			if (cell->hasPort("\\B")) {
-				vector<SigBit> more_bits = assign_map(cell->getPort("\\B")).to_sigbit_vector();
+			if (cell->hasPort(ID(B))) {
+				vector<SigBit> more_bits = assign_map(cell->getPort(ID(B))).to_sigbit_vector();
 				input_bits.insert(more_bits.begin(), more_bits.end());
 			}
 
@@ -496,14 +496,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			}
 		}
 
-		if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor", "$neg") &&
-				GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\Y")) == 1)
+		if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) &&
+				GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(Y))) == 1)
 		{
-			if (cell->type == "$reduce_xnor") {
+			if (cell->type == ID($reduce_xnor)) {
 				cover("opt.opt_expr.reduce_xnor_not");
 				log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n",
 						log_id(cell->type), log_id(cell->name), log_id(module));
-				cell->type = "$not";
+				cell->type = ID($not);
 				did_something = true;
 			} else {
 				cover("opt.opt_expr.unary_buffer");
@@ -514,15 +514,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
 		if (do_fine)
 		{
-			if (cell->type.in("$not", "$pos", "$and", "$or", "$xor", "$xnor"))
+			if (cell->type.in(ID($not), ID($pos), ID($and), ID($or), ID($xor), ID($xnor)))
 				if (group_cell_inputs(module, cell, true, assign_map))
 					goto next_cell;
 
-			if (cell->type.in("$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool"))
+			if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_and), ID($reduce_bool)))
 			{
-				SigBit neutral_bit = cell->type == "$reduce_and" ? State::S1 : State::S0;
+				SigBit neutral_bit = cell->type == ID($reduce_and) ? State::S1 : State::S0;
 
-				RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
+				RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
 				RTLIL::SigSpec new_sig_a;
 
 				for (auto bit : sig_a)
@@ -535,17 +535,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str());
 					log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
 							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a));
-					cell->setPort("\\A", new_sig_a);
-					cell->parameters.at("\\A_WIDTH") = GetSize(new_sig_a);
+					cell->setPort(ID(A), new_sig_a);
+					cell->parameters.at(ID(A_WIDTH)) = GetSize(new_sig_a);
 					did_something = true;
 				}
 			}
 
-			if (cell->type.in("$logic_and", "$logic_or"))
+			if (cell->type.in(ID($logic_and), ID($logic_or)))
 			{
 				SigBit neutral_bit = State::S0;
 
-				RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
+				RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
 				RTLIL::SigSpec new_sig_b;
 
 				for (auto bit : sig_b)
@@ -558,15 +558,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str());
 					log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
 							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b));
-					cell->setPort("\\B", new_sig_b);
-					cell->parameters.at("\\B_WIDTH") = GetSize(new_sig_b);
+					cell->setPort(ID(B), new_sig_b);
+					cell->parameters.at(ID(B_WIDTH)) = GetSize(new_sig_b);
 					did_something = true;
 				}
 			}
 
-			if (cell->type == "$reduce_and")
+			if (cell->type == ID($reduce_and))
 			{
-				RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
+				RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
 
 				RTLIL::State new_a = RTLIL::State::S1;
 				for (auto &bit : sig_a.to_sigbit_vector())
@@ -584,15 +584,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					cover("opt.opt_expr.fine.$reduce_and");
 					log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
-					cell->setPort("\\A", sig_a = new_a);
-					cell->parameters.at("\\A_WIDTH") = 1;
+					cell->setPort(ID(A), sig_a = new_a);
+					cell->parameters.at(ID(A_WIDTH)) = 1;
 					did_something = true;
 				}
 			}
 
-			if (cell->type.in("$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool"))
+			if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_bool)))
 			{
-				RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
+				RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
 
 				RTLIL::State new_a = RTLIL::State::S0;
 				for (auto &bit : sig_a.to_sigbit_vector())
@@ -610,15 +610,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
 					log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
-					cell->setPort("\\A", sig_a = new_a);
-					cell->parameters.at("\\A_WIDTH") = 1;
+					cell->setPort(ID(A), sig_a = new_a);
+					cell->parameters.at(ID(A_WIDTH)) = 1;
 					did_something = true;
 				}
 			}
 
-			if (cell->type.in("$logic_and", "$logic_or"))
+			if (cell->type.in(ID($logic_and), ID($logic_or)))
 			{
-				RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
+				RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
 
 				RTLIL::State new_b = RTLIL::State::S0;
 				for (auto &bit : sig_b.to_sigbit_vector())
@@ -636,17 +636,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
 					log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
-					cell->setPort("\\B", sig_b = new_b);
-					cell->parameters.at("\\B_WIDTH") = 1;
+					cell->setPort(ID(B), sig_b = new_b);
+					cell->parameters.at(ID(B_WIDTH)) = 1;
 					did_something = true;
 				}
 			}
 
-			if (cell->type.in("$add", "$sub")) {
-				RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
-				RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
-				RTLIL::SigSpec sig_y = cell->getPort("\\Y");
-				bool sub = cell->type == "$sub";
+			if (cell->type.in(ID($add), ID($sub)))
+			{
+				RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
+				RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
+				RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
+				bool sub = cell->type == ID($sub);
 
 				int i;
 				for (i = 0; i < GetSize(sig_y); i++) {
@@ -659,22 +660,69 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 				}
 				if (i > 0) {
 					cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str());
+					cell->setPort(ID(A), sig_a.extract_end(i));
+					cell->setPort(ID(B), sig_b.extract_end(i));
+					cell->setPort(ID(Y), sig_y.extract_end(i));
+					cell->fixup_parameters();
+					did_something = true;
+				}
+			}
+
+			if (cell->type == "$alu")
+			{
+				RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
+				RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
+				RTLIL::SigBit sig_ci = assign_map(cell->getPort("\\CI"));
+				RTLIL::SigBit sig_bi = assign_map(cell->getPort("\\BI"));
+				RTLIL::SigSpec sig_x = cell->getPort("\\X");
+				RTLIL::SigSpec sig_y = cell->getPort("\\Y");
+				RTLIL::SigSpec sig_co = cell->getPort("\\CO");
+
+				if (sig_ci.wire || sig_bi.wire)
+					goto next_cell;
+
+				bool sub = (sig_ci == State::S1 && sig_bi == State::S1);
+
+				// If not a subtraction, yet there is a carry or B is inverted
+				//   then no optimisation is possible as carry will not be constant
+				if (!sub && (sig_ci != State::S0 || sig_bi != State::S0))
+					goto next_cell;
+
+				int i;
+				for (i = 0; i < GetSize(sig_y); i++) {
+					if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) {
+						module->connect(sig_x[i], sub ? module->Not(NEW_ID, sig_a[i]).as_bit() : sig_a[i]);
+						module->connect(sig_y[i], sig_a[i]);
+						module->connect(sig_co[i], sub ? State::S1 : State::S0);
+					}
+					else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) {
+						module->connect(sig_x[i], sig_b[i]);
+						module->connect(sig_y[i], sig_b[i]);
+						module->connect(sig_co[i], State::S0);
+					}
+					else
+						break;
+				}
+				if (i > 0) {
+					cover("opt.opt_expr.fine.$alu");
 					cell->setPort("\\A", sig_a.extract_end(i));
 					cell->setPort("\\B", sig_b.extract_end(i));
+					cell->setPort("\\X", sig_x.extract_end(i));
 					cell->setPort("\\Y", sig_y.extract_end(i));
+					cell->setPort("\\CO", sig_co.extract_end(i));
 					cell->fixup_parameters();
 					did_something = true;
 				}
 			}
 		}
 
-		if (cell->type.in("$reduce_xor", "$reduce_xnor", "$shift", "$shiftx", "$shl", "$shr", "$sshl", "$sshr",
-					"$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow"))
+		if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr),
+					ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow)))
 		{
-			RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
-			RTLIL::SigSpec sig_b = cell->hasPort("\\B") ? assign_map(cell->getPort("\\B")) : RTLIL::SigSpec();
+			RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
+			RTLIL::SigSpec sig_b = cell->hasPort(ID(B)) ? assign_map(cell->getPort(ID(B))) : RTLIL::SigSpec();
 
-			if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx"))
+			if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
 				sig_a = RTLIL::SigSpec();
 
 			for (auto &bit : sig_a.to_sigbit_vector())
@@ -689,7 +737,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 		found_the_x_bit:
 				cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
 						"$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str());
-				if (cell->type.in("$reduce_xor", "$reduce_xnor", "$lt", "$le", "$ge", "$gt"))
+				if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
 					replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::State::Sx);
 				else
 					replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort("\\Y").size()));
@@ -697,36 +745,36 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			}
 		}
 
-		if (cell->type.in("$_NOT_", "$not", "$logic_not") && cell->getPort("\\Y").size() == 1 &&
-				invert_map.count(assign_map(cell->getPort("\\A"))) != 0) {
+		if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID(Y)).size() == 1 &&
+				invert_map.count(assign_map(cell->getPort(ID(A)))) != 0) {
 			cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
 			replace_cell(assign_map, module, cell, "double_invert", "\\Y", invert_map.at(assign_map(cell->getPort("\\A"))));
 			goto next_cell;
 		}
 
-		if (cell->type.in("$_MUX_", "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) {
+		if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID(S)))) != 0) {
 			cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
 			log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
-			RTLIL::SigSpec tmp = cell->getPort("\\A");
-			cell->setPort("\\A", cell->getPort("\\B"));
-			cell->setPort("\\B", tmp);
-			cell->setPort("\\S", invert_map.at(assign_map(cell->getPort("\\S"))));
+			RTLIL::SigSpec tmp = cell->getPort(ID(A));
+			cell->setPort(ID(A), cell->getPort(ID(B)));
+			cell->setPort(ID(B), tmp);
+			cell->setPort(ID(S), invert_map.at(assign_map(cell->getPort(ID(S)))));
 			did_something = true;
 			goto next_cell;
 		}
 
-		if (cell->type == "$_NOT_") {
-			RTLIL::SigSpec input = cell->getPort("\\A");
+		if (cell->type == ID($_NOT_)) {
+			RTLIL::SigSpec input = cell->getPort(ID(A));
 			assign_map.apply(input);
 			if (input.match("1")) ACTION_DO_Y(0);
 			if (input.match("0")) ACTION_DO_Y(1);
 			if (input.match("*")) ACTION_DO_Y(x);
 		}
 
-		if (cell->type == "$_AND_") {
+		if (cell->type == ID($_AND_)) {
 			RTLIL::SigSpec input;
-			input.append(cell->getPort("\\B"));
-			input.append(cell->getPort("\\A"));
+			input.append(cell->getPort(ID(B)));
+			input.append(cell->getPort(ID(A)));
 			assign_map.apply(input);
 			if (input.match(" 0")) ACTION_DO_Y(0);
 			if (input.match("0 ")) ACTION_DO_Y(0);
@@ -738,14 +786,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 				if (input.match(" *")) ACTION_DO_Y(0);
 				if (input.match("* ")) ACTION_DO_Y(0);
 			}
-			if (input.match(" 1")) ACTION_DO("\\Y", input.extract(1, 1));
-			if (input.match("1 ")) ACTION_DO("\\Y", input.extract(0, 1));
+			if (input.match(" 1")) ACTION_DO(ID(Y), input.extract(1, 1));
+			if (input.match("1 ")) ACTION_DO(ID(Y), input.extract(0, 1));
 		}
 
-		if (cell->type == "$_OR_") {
+		if (cell->type == ID($_OR_)) {
 			RTLIL::SigSpec input;
-			input.append(cell->getPort("\\B"));
-			input.append(cell->getPort("\\A"));
+			input.append(cell->getPort(ID(B)));
+			input.append(cell->getPort(ID(A)));
 			assign_map.apply(input);
 			if (input.match(" 1")) ACTION_DO_Y(1);
 			if (input.match("1 ")) ACTION_DO_Y(1);
@@ -757,14 +805,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 				if (input.match(" *")) ACTION_DO_Y(1);
 				if (input.match("* ")) ACTION_DO_Y(1);
 			}
-			if (input.match(" 0")) ACTION_DO("\\Y", input.extract(1, 1));
-			if (input.match("0 ")) ACTION_DO("\\Y", input.extract(0, 1));
+			if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1));
+			if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1));
 		}
 
-		if (cell->type == "$_XOR_") {
+		if (cell->type == ID($_XOR_)) {
 			RTLIL::SigSpec input;
-			input.append(cell->getPort("\\B"));
-			input.append(cell->getPort("\\A"));
+			input.append(cell->getPort(ID(B)));
+			input.append(cell->getPort(ID(A)));
 			assign_map.apply(input);
 			if (input.match("00")) ACTION_DO_Y(0);
 			if (input.match("01")) ACTION_DO_Y(1);
@@ -772,27 +820,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			if (input.match("11")) ACTION_DO_Y(0);
 			if (input.match(" *")) ACTION_DO_Y(x);
 			if (input.match("* ")) ACTION_DO_Y(x);
-			if (input.match(" 0")) ACTION_DO("\\Y", input.extract(1, 1));
-			if (input.match("0 ")) ACTION_DO("\\Y", input.extract(0, 1));
+			if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1));
+			if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1));
 		}
 
-		if (cell->type == "$_MUX_") {
+		if (cell->type == ID($_MUX_)) {
 			RTLIL::SigSpec input;
-			input.append(cell->getPort("\\S"));
-			input.append(cell->getPort("\\B"));
-			input.append(cell->getPort("\\A"));
+			input.append(cell->getPort(ID(S)));
+			input.append(cell->getPort(ID(B)));
+			input.append(cell->getPort(ID(A)));
 			assign_map.apply(input);
 			if (input.extract(2, 1) == input.extract(1, 1))
-				ACTION_DO("\\Y", input.extract(2, 1));
-			if (input.match("  0")) ACTION_DO("\\Y", input.extract(2, 1));
-			if (input.match("  1")) ACTION_DO("\\Y", input.extract(1, 1));
-			if (input.match("01 ")) ACTION_DO("\\Y", input.extract(0, 1));
+				ACTION_DO(ID(Y), input.extract(2, 1));
+			if (input.match("  0")) ACTION_DO(ID(Y), input.extract(2, 1));
+			if (input.match("  1")) ACTION_DO(ID(Y), input.extract(1, 1));
+			if (input.match("01 ")) ACTION_DO(ID(Y), input.extract(0, 1));
 			if (input.match("10 ")) {
 				cover("opt.opt_expr.mux_to_inv");
-				cell->type = "$_NOT_";
-				cell->setPort("\\A", input.extract(0, 1));
-				cell->unsetPort("\\B");
-				cell->unsetPort("\\S");
+				cell->type = ID($_NOT_);
+				cell->setPort(ID(A), input.extract(0, 1));
+				cell->unsetPort(ID(B));
+				cell->unsetPort(ID(S));
 				goto next_cell;
 			}
 			if (input.match("11 ")) ACTION_DO_Y(1);
@@ -801,38 +849,38 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			if (input.match("01*")) ACTION_DO_Y(x);
 			if (input.match("10*")) ACTION_DO_Y(x);
 			if (mux_undef) {
-				if (input.match("*  ")) ACTION_DO("\\Y", input.extract(1, 1));
-				if (input.match(" * ")) ACTION_DO("\\Y", input.extract(2, 1));
-				if (input.match("  *")) ACTION_DO("\\Y", input.extract(2, 1));
+				if (input.match("*  ")) ACTION_DO(ID(Y), input.extract(1, 1));
+				if (input.match(" * ")) ACTION_DO(ID(Y), input.extract(2, 1));
+				if (input.match("  *")) ACTION_DO(ID(Y), input.extract(2, 1));
 			}
 		}
 
-		if (cell->type.in("$_TBUF_", "$tribuf")) {
-			RTLIL::SigSpec input = cell->getPort(cell->type == "$_TBUF_" ? "\\E" : "\\EN");
-			RTLIL::SigSpec a = cell->getPort("\\A");
+		if (cell->type.in(ID($_TBUF_), ID($tribuf))) {
+			RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? ID(E) : ID(EN));
+			RTLIL::SigSpec a = cell->getPort(ID(A));
 			assign_map.apply(input);
 			assign_map.apply(a);
 			if (input == State::S1)
-				ACTION_DO("\\Y", cell->getPort("\\A"));
+				ACTION_DO(ID(Y), cell->getPort(ID(A)));
 			if (input == State::S0 && !a.is_fully_undef()) {
 				cover("opt.opt_expr.action_" S__LINE__);
 				log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
 					cell->type.c_str(), cell->name.c_str(), module->name.c_str());
-				cell->setPort("\\A", SigSpec(State::Sx, GetSize(a)));
+				cell->setPort(ID(A), SigSpec(State::Sx, GetSize(a)));
 				did_something = true;
 				goto next_cell;
 			}
 		}
 
-		if (cell->type.in("$eq", "$ne", "$eqx", "$nex"))
+		if (cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
 		{
-			RTLIL::SigSpec a = cell->getPort("\\A");
-			RTLIL::SigSpec b = cell->getPort("\\B");
+			RTLIL::SigSpec a = cell->getPort(ID(A));
+			RTLIL::SigSpec b = cell->getPort(ID(B));
 
-			if (cell->parameters["\\A_WIDTH"].as_int() != cell->parameters["\\B_WIDTH"].as_int()) {
-				int width = max(cell->parameters["\\A_WIDTH"].as_int(), cell->parameters["\\B_WIDTH"].as_int());
-				a.extend_u0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
-				b.extend_u0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
+			if (cell->parameters[ID(A_WIDTH)].as_int() != cell->parameters[ID(B_WIDTH)].as_int()) {
+				int width = max(cell->parameters[ID(A_WIDTH)].as_int(), cell->parameters[ID(B_WIDTH)].as_int());
+				a.extend_u0(width, cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool());
+				b.extend_u0(width, cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool());
 			}
 
 			RTLIL::SigSpec new_a, new_b;
@@ -841,8 +889,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			for (int i = 0; i < GetSize(a); i++) {
 				if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) {
 					cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
-					RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in("$eq", "$eqx") ?  RTLIL::State::S0 : RTLIL::State::S1);
-					new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false);
+					RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ?  RTLIL::State::S0 : RTLIL::State::S1);
+					new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false);
 					replace_cell(assign_map, module, cell, "isneq", "\\Y", new_y);
 					goto next_cell;
 				}
@@ -854,83 +902,83 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
 			if (new_a.size() == 0) {
 				cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
-				RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in("$eq", "$eqx") ?  RTLIL::State::S1 : RTLIL::State::S0);
-				new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false);
-				replace_cell(assign_map, module, cell, "empty", "\\Y", new_y);
+				RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ?  RTLIL::State::S1 : RTLIL::State::S0);
+				new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false);
+				replace_cell(assign_map, module, cell, "empty", ID(Y), new_y);
 				goto next_cell;
 			}
 
 			if (new_a.size() < a.size() || new_b.size() < b.size()) {
 				cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
-				cell->setPort("\\A", new_a);
-				cell->setPort("\\B", new_b);
-				cell->parameters["\\A_WIDTH"] = new_a.size();
-				cell->parameters["\\B_WIDTH"] = new_b.size();
+				cell->setPort(ID(A), new_a);
+				cell->setPort(ID(B), new_b);
+				cell->parameters[ID(A_WIDTH)] = new_a.size();
+				cell->parameters[ID(B_WIDTH)] = new_b.size();
 			}
 		}
 
-		if (cell->type.in("$eq", "$ne") && cell->parameters["\\Y_WIDTH"].as_int() == 1 &&
-				cell->parameters["\\A_WIDTH"].as_int() == 1 && cell->parameters["\\B_WIDTH"].as_int() == 1)
+		if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID(Y_WIDTH)].as_int() == 1 &&
+				cell->parameters[ID(A_WIDTH)].as_int() == 1 && cell->parameters[ID(B_WIDTH)].as_int() == 1)
 		{
-			RTLIL::SigSpec a = assign_map(cell->getPort("\\A"));
-			RTLIL::SigSpec b = assign_map(cell->getPort("\\B"));
+			RTLIL::SigSpec a = assign_map(cell->getPort(ID(A)));
+			RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
 
 			if (a.is_fully_const() && !b.is_fully_const()) {
 				cover_list("opt.opt_expr.eqneq.swapconst", "$eq", "$ne", cell->type.str());
-				cell->setPort("\\A", b);
-				cell->setPort("\\B", a);
+				cell->setPort(ID(A), b);
+				cell->setPort(ID(B), a);
 				std::swap(a, b);
 			}
 
 			if (b.is_fully_const()) {
-				if (b.as_bool() == (cell->type == "$eq")) {
+				if (b.as_bool() == (cell->type == ID($eq))) {
 					RTLIL::SigSpec input = b;
-					ACTION_DO("\\Y", cell->getPort("\\A"));
+					ACTION_DO(ID(Y), cell->getPort(ID(A)));
 				} else {
 					cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
 					log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
-					cell->type = "$not";
-					cell->parameters.erase("\\B_WIDTH");
-					cell->parameters.erase("\\B_SIGNED");
-					cell->unsetPort("\\B");
+					cell->type = ID($not);
+					cell->parameters.erase(ID(B_WIDTH));
+					cell->parameters.erase(ID(B_SIGNED));
+					cell->unsetPort(ID(B));
 					did_something = true;
 				}
 				goto next_cell;
 			}
 		}
 
-		if (cell->type.in("$eq", "$ne") &&
-				(assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero()))
+		if (cell->type.in(ID($eq), ID($ne)) &&
+				(assign_map(cell->getPort(ID(A))).is_fully_zero() || assign_map(cell->getPort(ID(B))).is_fully_zero()))
 		{
 			cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
 			log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
 					log_id(module), "$eq" ? "$logic_not" : "$reduce_bool");
-			cell->type = cell->type == "$eq" ? "$logic_not" : "$reduce_bool";
-			if (assign_map(cell->getPort("\\A")).is_fully_zero()) {
-				cell->setPort("\\A", cell->getPort("\\B"));
-				cell->setParam("\\A_SIGNED", cell->getParam("\\B_SIGNED"));
-				cell->setParam("\\A_WIDTH", cell->getParam("\\B_WIDTH"));
+			cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool);
+			if (assign_map(cell->getPort(ID(A))).is_fully_zero()) {
+				cell->setPort(ID(A), cell->getPort(ID(B)));
+				cell->setParam(ID(A_SIGNED), cell->getParam(ID(B_SIGNED)));
+				cell->setParam(ID(A_WIDTH), cell->getParam(ID(B_WIDTH)));
 			}
-			cell->unsetPort("\\B");
-			cell->unsetParam("\\B_SIGNED");
-			cell->unsetParam("\\B_WIDTH");
+			cell->unsetPort(ID(B));
+			cell->unsetParam(ID(B_SIGNED));
+			cell->unsetParam(ID(B_WIDTH));
 			did_something = true;
 			goto next_cell;
 		}
 
-		if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx") && assign_map(cell->getPort("\\B")).is_fully_const())
+		if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID(B))).is_fully_const())
 		{
-			bool sign_ext = cell->type == "$sshr" && cell->getParam("\\A_SIGNED").as_bool();
-			int shift_bits = assign_map(cell->getPort("\\B")).as_int(cell->type.in("$shift", "$shiftx") && cell->getParam("\\B_SIGNED").as_bool());
+			bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID(A_SIGNED)).as_bool();
+			int shift_bits = assign_map(cell->getPort(ID(B))).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID(B_SIGNED)).as_bool());
 
-			if (cell->type.in("$shl", "$sshl"))
+			if (cell->type.in(ID($shl), ID($sshl)))
 				shift_bits *= -1;
 
-			RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
-			RTLIL::SigSpec sig_y(cell->type == "$shiftx" ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam("\\Y_WIDTH").as_int());
+			RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
+			RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID(Y_WIDTH)).as_int());
 
 			if (GetSize(sig_a) < GetSize(sig_y))
-				sig_a.extend_u0(GetSize(sig_y), cell->getParam("\\A_SIGNED").as_bool());
+				sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID(A_SIGNED)).as_bool());
 
 			for (int i = 0; i < GetSize(sig_y); i++) {
 				int idx = i + shift_bits;
@@ -943,9 +991,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
 
 			log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
-					log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort("\\B"))), shift_bits, log_id(module), log_signal(sig_y));
+					log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID(B)))), shift_bits, log_id(module), log_signal(sig_y));
 
-			module->connect(cell->getPort("\\Y"), sig_y);
+			module->connect(cell->getPort(ID(Y)), sig_y);
 			module->remove(cell);
 
 			did_something = true;
@@ -958,41 +1006,41 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			bool identity_wrt_b = false;
 			bool arith_inverse = false;
 
-			if (cell->type.in("$add", "$sub", "$or", "$xor"))
+			if (cell->type.in(ID($add), ID($sub), ID($or), ID($xor)))
 			{
-				RTLIL::SigSpec a = assign_map(cell->getPort("\\A"));
-				RTLIL::SigSpec b = assign_map(cell->getPort("\\B"));
+				RTLIL::SigSpec a = assign_map(cell->getPort(ID(A)));
+				RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
 
-				if (cell->type != "$sub" && a.is_fully_const() && a.as_bool() == false)
+				if (cell->type != ID($sub) && a.is_fully_const() && a.as_bool() == false)
 					identity_wrt_b = true;
 
 				if (b.is_fully_const() && b.as_bool() == false)
 					identity_wrt_a = true;
 			}
 
-			if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx"))
+			if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
 			{
-				RTLIL::SigSpec b = assign_map(cell->getPort("\\B"));
+				RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
 
 				if (b.is_fully_const() && b.as_bool() == false)
 					identity_wrt_a = true;
 			}
 
-			if (cell->type == "$mul")
+			if (cell->type == ID($mul))
 			{
-				RTLIL::SigSpec a = assign_map(cell->getPort("\\A"));
-				RTLIL::SigSpec b = assign_map(cell->getPort("\\B"));
+				RTLIL::SigSpec a = assign_map(cell->getPort(ID(A)));
+				RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
 
-				if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam("\\A_SIGNED").as_bool(), arith_inverse))
+				if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam(ID(A_SIGNED)).as_bool(), arith_inverse))
 					identity_wrt_b = true;
 				else
-				if (b.is_fully_const() && is_one_or_minus_one(b.as_const(), cell->getParam("\\B_SIGNED").as_bool(), arith_inverse))
+				if (b.is_fully_const() && is_one_or_minus_one(b.as_const(), cell->getParam(ID(B_SIGNED)).as_bool(), arith_inverse))
 					identity_wrt_a = true;
 			}
 
-			if (cell->type == "$div")
+			if (cell->type == ID($div))
 			{
-				RTLIL::SigSpec b = assign_map(cell->getPort("\\B"));
+				RTLIL::SigSpec b = assign_map(cell->getPort(ID(B)));
 
 				if (b.is_fully_const() && b.size() <= 32 && b.as_int() == 1)
 					identity_wrt_a = true;
@@ -1009,15 +1057,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
 
 				if (!identity_wrt_a) {
-					cell->setPort("\\A", cell->getPort("\\B"));
-					cell->parameters.at("\\A_WIDTH") = cell->parameters.at("\\B_WIDTH");
-					cell->parameters.at("\\A_SIGNED") = cell->parameters.at("\\B_SIGNED");
+					cell->setPort(ID(A), cell->getPort(ID(B)));
+					cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH));
+					cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED));
 				}
 
-				cell->type = arith_inverse ? "$neg" : "$pos";
-				cell->unsetPort("\\B");
-				cell->parameters.erase("\\B_WIDTH");
-				cell->parameters.erase("\\B_SIGNED");
+				cell->type = arith_inverse ? ID($neg) : ID($pos);
+				cell->unsetPort(ID(B));
+				cell->parameters.erase(ID(B_WIDTH));
+				cell->parameters.erase(ID(B_SIGNED));
 				cell->check();
 
 				did_something = true;
@@ -1025,91 +1073,91 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			}
 		}
 
-		if (mux_bool && cell->type.in("$mux", "$_MUX_") &&
-				cell->getPort("\\A") == State::S0 && cell->getPort("\\B") == State::S1) {
+		if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
+				cell->getPort(ID(A)) == State::S0 && cell->getPort(ID(B)) == State::S1) {
 			cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str());
-			replace_cell(assign_map, module, cell, "mux_bool", "\\Y", cell->getPort("\\S"));
+			replace_cell(assign_map, module, cell, "mux_bool", ID(Y), cell->getPort(ID(S)));
 			goto next_cell;
 		}
 
-		if (mux_bool && cell->type.in("$mux", "$_MUX_") &&
-				cell->getPort("\\A") == State::S1 && cell->getPort("\\B") == State::S0) {
+		if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
+				cell->getPort(ID(A)) == State::S1 && cell->getPort(ID(B)) == State::S0) {
 			cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
 			log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
-			cell->setPort("\\A", cell->getPort("\\S"));
-			cell->unsetPort("\\B");
-			cell->unsetPort("\\S");
-			if (cell->type == "$mux") {
-				Const width = cell->parameters["\\WIDTH"];
-				cell->parameters["\\A_WIDTH"] = width;
-				cell->parameters["\\Y_WIDTH"] = width;
-				cell->parameters["\\A_SIGNED"] = 0;
-				cell->parameters.erase("\\WIDTH");
-				cell->type = "$not";
+			cell->setPort(ID(A), cell->getPort(ID(S)));
+			cell->unsetPort(ID(B));
+			cell->unsetPort(ID(S));
+			if (cell->type == ID($mux)) {
+				Const width = cell->parameters[ID(WIDTH)];
+				cell->parameters[ID(A_WIDTH)] = width;
+				cell->parameters[ID(Y_WIDTH)] = width;
+				cell->parameters[ID(A_SIGNED)] = 0;
+				cell->parameters.erase(ID(WIDTH));
+				cell->type = ID($not);
 			} else
-				cell->type = "$_NOT_";
+				cell->type = ID($_NOT_);
 			did_something = true;
 			goto next_cell;
 		}
 
-		if (consume_x && mux_bool && cell->type.in("$mux", "$_MUX_") && cell->getPort("\\A") == State::S0) {
+		if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(A)) == State::S0) {
 			cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
 			log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
-			cell->setPort("\\A", cell->getPort("\\S"));
-			cell->unsetPort("\\S");
-			if (cell->type == "$mux") {
-				Const width = cell->parameters["\\WIDTH"];
-				cell->parameters["\\A_WIDTH"] = width;
-				cell->parameters["\\B_WIDTH"] = width;
-				cell->parameters["\\Y_WIDTH"] = width;
-				cell->parameters["\\A_SIGNED"] = 0;
-				cell->parameters["\\B_SIGNED"] = 0;
-				cell->parameters.erase("\\WIDTH");
-				cell->type = "$and";
+			cell->setPort(ID(A), cell->getPort(ID(S)));
+			cell->unsetPort(ID(S));
+			if (cell->type == ID($mux)) {
+				Const width = cell->parameters[ID(WIDTH)];
+				cell->parameters[ID(A_WIDTH)] = width;
+				cell->parameters[ID(B_WIDTH)] = width;
+				cell->parameters[ID(Y_WIDTH)] = width;
+				cell->parameters[ID(A_SIGNED)] = 0;
+				cell->parameters[ID(B_SIGNED)] = 0;
+				cell->parameters.erase(ID(WIDTH));
+				cell->type = ID($and);
 			} else
-				cell->type = "$_AND_";
+				cell->type = ID($_AND_);
 			did_something = true;
 			goto next_cell;
 		}
 
-		if (consume_x && mux_bool && cell->type.in("$mux", "$_MUX_") && cell->getPort("\\B") == State::S1) {
+		if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(B)) == State::S1) {
 			cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
 			log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
-			cell->setPort("\\B", cell->getPort("\\S"));
-			cell->unsetPort("\\S");
-			if (cell->type == "$mux") {
-				Const width = cell->parameters["\\WIDTH"];
-				cell->parameters["\\A_WIDTH"] = width;
-				cell->parameters["\\B_WIDTH"] = width;
-				cell->parameters["\\Y_WIDTH"] = width;
-				cell->parameters["\\A_SIGNED"] = 0;
-				cell->parameters["\\B_SIGNED"] = 0;
-				cell->parameters.erase("\\WIDTH");
-				cell->type = "$or";
+			cell->setPort(ID(B), cell->getPort(ID(S)));
+			cell->unsetPort(ID(S));
+			if (cell->type == ID($mux)) {
+				Const width = cell->parameters[ID(WIDTH)];
+				cell->parameters[ID(A_WIDTH)] = width;
+				cell->parameters[ID(B_WIDTH)] = width;
+				cell->parameters[ID(Y_WIDTH)] = width;
+				cell->parameters[ID(A_SIGNED)] = 0;
+				cell->parameters[ID(B_SIGNED)] = 0;
+				cell->parameters.erase(ID(WIDTH));
+				cell->type = ID($or);
 			} else
-				cell->type = "$_OR_";
+				cell->type = ID($_OR_);
 			did_something = true;
 			goto next_cell;
 		}
 
-		if (mux_undef && cell->type.in("$mux", "$pmux")) {
+		if (mux_undef && cell->type.in(ID($mux), ID($pmux))) {
 			RTLIL::SigSpec new_a, new_b, new_s;
-			int width = cell->getPort("\\A").size();
-			if ((cell->getPort("\\A").is_fully_undef() && cell->getPort("\\B").is_fully_undef()) ||
-					cell->getPort("\\S").is_fully_undef()) {
+			int width = cell->getPort(ID(A)).size();
+			if ((cell->getPort(ID(A)).is_fully_undef() && cell->getPort(ID(B)).is_fully_undef()) ||
+					cell->getPort(ID(S)).is_fully_undef()) {
 				cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str());
-				replace_cell(assign_map, module, cell, "mux_undef", "\\Y", cell->getPort("\\A"));
+				replace_cell(assign_map, module, cell, "mux_undef", ID(Y), cell->getPort(ID(A)));
 				goto next_cell;
 			}
-			for (int i = 0; i < cell->getPort("\\S").size(); i++) {
-				RTLIL::SigSpec old_b = cell->getPort("\\B").extract(i*width, width);
-				RTLIL::SigSpec old_s = cell->getPort("\\S").extract(i, 1);
+			for (int i = 0; i < cell->getPort(ID(S)).size(); i++) {
+				RTLIL::SigSpec old_b = cell->getPort(ID(B)).extract(i*width, width);
+				RTLIL::SigSpec old_s = cell->getPort(ID(S)).extract(i, 1);
 				if (old_b.is_fully_undef() || old_s.is_fully_undef())
 					continue;
 				new_b.append(old_b);
 				new_s.append(old_s);
 			}
-			new_a = cell->getPort("\\A");
+			new_a = cell->getPort(ID(A));
 			if (new_a.is_fully_undef() && new_s.size() > 0) {
 				new_a = new_b.extract((new_s.size()-1)*width, width);
 				new_b = new_b.extract(0, (new_s.size()-1)*width);
@@ -1117,27 +1165,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			}
 			if (new_s.size() == 0) {
 				cover_list("opt.opt_expr.mux_empty", "$mux", "$pmux", cell->type.str());
-				replace_cell(assign_map, module, cell, "mux_empty", "\\Y", new_a);
+				replace_cell(assign_map, module, cell, "mux_empty", ID(Y), new_a);
 				goto next_cell;
 			}
 			if (new_a == RTLIL::SigSpec(RTLIL::State::S0) && new_b == RTLIL::SigSpec(RTLIL::State::S1)) {
 				cover_list("opt.opt_expr.mux_sel01", "$mux", "$pmux", cell->type.str());
-				replace_cell(assign_map, module, cell, "mux_sel01", "\\Y", new_s);
+				replace_cell(assign_map, module, cell, "mux_sel01", ID(Y), new_s);
 				goto next_cell;
 			}
-			if (cell->getPort("\\S").size() != new_s.size()) {
+			if (cell->getPort(ID(S)).size() != new_s.size()) {
 				cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
 				log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
-						GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
-				cell->setPort("\\A", new_a);
-				cell->setPort("\\B", new_b);
-				cell->setPort("\\S", new_s);
+						GetSize(cell->getPort(ID(S))) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
+				cell->setPort(ID(A), new_a);
+				cell->setPort(ID(B), new_b);
+				cell->setPort(ID(S), new_s);
 				if (new_s.size() > 1) {
-					cell->type = "$pmux";
-					cell->parameters["\\S_WIDTH"] = new_s.size();
+					cell->type = ID($pmux);
+					cell->parameters[ID(S_WIDTH)] = new_s.size();
 				} else {
-					cell->type = "$mux";
-					cell->parameters.erase("\\S_WIDTH");
+					cell->type = ID($mux);
+					cell->parameters.erase(ID(S_WIDTH));
 				}
 				did_something = true;
 			}
@@ -1145,30 +1193,30 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
 #define FOLD_1ARG_CELL(_t) \
 		if (cell->type == "$" #_t) { \
-			RTLIL::SigSpec a = cell->getPort("\\A"); \
+			RTLIL::SigSpec a = cell->getPort(ID(A)); \
 			assign_map.apply(a); \
 			if (a.is_fully_const()) { \
 				RTLIL::Const dummy_arg(RTLIL::State::S0, 1); \
 				RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), dummy_arg, \
-						cell->parameters["\\A_SIGNED"].as_bool(), false, \
-						cell->parameters["\\Y_WIDTH"].as_int())); \
+						cell->parameters[ID(A_SIGNED)].as_bool(), false, \
+						cell->parameters[ID(Y_WIDTH)].as_int())); \
 				cover("opt.opt_expr.const.$" #_t); \
-				replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), "\\Y", y); \
+				replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID(Y), y); \
 				goto next_cell; \
 			} \
 		}
 #define FOLD_2ARG_CELL(_t) \
 		if (cell->type == "$" #_t) { \
-			RTLIL::SigSpec a = cell->getPort("\\A"); \
-			RTLIL::SigSpec b = cell->getPort("\\B"); \
+			RTLIL::SigSpec a = cell->getPort(ID(A)); \
+			RTLIL::SigSpec b = cell->getPort(ID(B)); \
 			assign_map.apply(a), assign_map.apply(b); \
 			if (a.is_fully_const() && b.is_fully_const()) { \
 				RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), \
-						cell->parameters["\\A_SIGNED"].as_bool(), \
-						cell->parameters["\\B_SIGNED"].as_bool(), \
-						cell->parameters["\\Y_WIDTH"].as_int())); \
+						cell->parameters[ID(A_SIGNED)].as_bool(), \
+						cell->parameters[ID(B_SIGNED)].as_bool(), \
+						cell->parameters[ID(Y_WIDTH)].as_int())); \
 				cover("opt.opt_expr.const.$" #_t); \
-				replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), "\\Y", y); \
+				replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID(Y), y); \
 				goto next_cell; \
 			} \
 		}
@@ -1214,25 +1262,25 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 		FOLD_1ARG_CELL(neg)
 
 		// be very conservative with optimizing $mux cells as we do not want to break mux trees
-		if (cell->type == "$mux") {
-			RTLIL::SigSpec input = assign_map(cell->getPort("\\S"));
-			RTLIL::SigSpec inA = assign_map(cell->getPort("\\A"));
-			RTLIL::SigSpec inB = assign_map(cell->getPort("\\B"));
+		if (cell->type == ID($mux)) {
+			RTLIL::SigSpec input = assign_map(cell->getPort(ID(S)));
+			RTLIL::SigSpec inA = assign_map(cell->getPort(ID(A)));
+			RTLIL::SigSpec inB = assign_map(cell->getPort(ID(B)));
 			if (input.is_fully_const())
-				ACTION_DO("\\Y", input.as_bool() ? cell->getPort("\\B") : cell->getPort("\\A"));
+				ACTION_DO(ID(Y), input.as_bool() ? cell->getPort(ID(B)) : cell->getPort(ID(A)));
 			else if (inA == inB)
-				ACTION_DO("\\Y", cell->getPort("\\A"));
+				ACTION_DO(ID(Y), cell->getPort(ID(A)));
 		}
 
-		if (!keepdc && cell->type == "$mul")
+		if (!keepdc && cell->type == ID($mul))
 		{
-			bool a_signed = cell->parameters["\\A_SIGNED"].as_bool();
-			bool b_signed = cell->parameters["\\B_SIGNED"].as_bool();
+			bool a_signed = cell->parameters[ID(A_SIGNED)].as_bool();
+			bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool();
 			bool swapped_ab = false;
 
-			RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
-			RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
-			RTLIL::SigSpec sig_y = assign_map(cell->getPort("\\Y"));
+			RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
+			RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
+			RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID(Y)));
 
 			if (sig_b.is_fully_const() && sig_b.size() <= 32)
 				std::swap(sig_a, sig_b), std::swap(a_signed, b_signed), swapped_ab = true;
@@ -1267,9 +1315,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 								a_val, cell->name.c_str(), module->name.c_str(), i);
 
 						if (!swapped_ab) {
-							cell->setPort("\\A", cell->getPort("\\B"));
-							cell->parameters.at("\\A_WIDTH") = cell->parameters.at("\\B_WIDTH");
-							cell->parameters.at("\\A_SIGNED") = cell->parameters.at("\\B_SIGNED");
+							cell->setPort(ID(A), cell->getPort(ID(B)));
+							cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH));
+							cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED));
 						}
 
 						std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
@@ -1277,10 +1325,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 						while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
 							new_b.pop_back();
 
-						cell->type = "$shl";
-						cell->parameters["\\B_WIDTH"] = GetSize(new_b);
-						cell->parameters["\\B_SIGNED"] = false;
-						cell->setPort("\\B", new_b);
+						cell->type = ID($shl);
+						cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
+						cell->parameters[ID(B_SIGNED)] = false;
+						cell->setPort(ID(B), new_b);
 						cell->check();
 
 						did_something = true;
@@ -1289,11 +1337,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			}
 		}
 
-		if (!keepdc && cell->type.in("$div", "$mod"))
+		if (!keepdc && cell->type.in(ID($div), ID($mod)))
 		{
-			bool b_signed = cell->parameters["\\B_SIGNED"].as_bool();
-			SigSpec sig_b = assign_map(cell->getPort("\\B"));
-			SigSpec sig_y = assign_map(cell->getPort("\\Y"));
+			bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool();
+			SigSpec sig_b = assign_map(cell->getPort(ID(B)));
+			SigSpec sig_y = assign_map(cell->getPort(ID(Y)));
 
 			if (sig_b.is_fully_def() && sig_b.size() <= 32)
 			{
@@ -1316,7 +1364,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 				for (int i = 1; i < (b_signed ? sig_b.size()-1 : sig_b.size()); i++)
 					if (b_val == (1 << i))
 					{
-						if (cell->type == "$div")
+						if (cell->type == ID($div))
 						{
 							cover("opt.opt_expr.div_shift");
 
@@ -1328,10 +1376,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 							while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
 								new_b.pop_back();
 
-							cell->type = "$shr";
-							cell->parameters["\\B_WIDTH"] = GetSize(new_b);
-							cell->parameters["\\B_SIGNED"] = false;
-							cell->setPort("\\B", new_b);
+							cell->type = ID($shr);
+							cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
+							cell->parameters[ID(B_SIGNED)] = false;
+							cell->setPort(ID(B), new_b);
 							cell->check();
 						}
 						else
@@ -1346,9 +1394,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 							if (b_signed)
 								new_b.push_back(State::S0);
 
-							cell->type = "$and";
-							cell->parameters["\\B_WIDTH"] = GetSize(new_b);
-							cell->setPort("\\B", new_b);
+							cell->type = ID($and);
+							cell->parameters[ID(B_WIDTH)] = GetSize(new_b);
+							cell->setPort(ID(B), new_b);
 							cell->check();
 						}
 
@@ -1360,7 +1408,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
 		// remove redundant pairs of bits in ==, ===, !=, and !==
 		// replace cell with const driver if inputs can't be equal
-		if (do_fine && cell->type.in("$eq", "$ne", "$eqx", "$nex"))
+		if (do_fine && cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
 		{
 			pool<pair<SigBit, SigBit>> redundant_cache;
 			mfp<SigBit> contradiction_cache;
@@ -1368,14 +1416,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 			contradiction_cache.promote(State::S0);
 			contradiction_cache.promote(State::S1);
 
-			int a_width = cell->getParam("\\A_WIDTH").as_int();
-			int b_width = cell->getParam("\\B_WIDTH").as_int();
+			int a_width = cell->getParam(ID(A_WIDTH)).as_int();
+			int b_width = cell->getParam(ID(B_WIDTH)).as_int();
 
-			bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
+			bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 			int width = is_signed ? std::min(a_width, b_width) : std::max(a_width, b_width);
 
-			SigSpec sig_a = cell->getPort("\\A");
-			SigSpec sig_b = cell->getPort("\\B");
+			SigSpec sig_a = cell->getPort(ID(A));
+			SigSpec sig_b = cell->getPort(ID(B));
 
 			int redundant_bits = 0;
 
@@ -1405,8 +1453,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
 			if (contradiction_cache.find(State::S0) == contradiction_cache.find(State::S1))
 			{
-				SigSpec y_sig = cell->getPort("\\Y");
-				Const y_value(cell->type.in("$eq", "$eqx") ? 0 : 1, GetSize(y_sig));
+				SigSpec y_sig = cell->getPort(ID(Y));
+				Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig));
 
 				log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n",
 					log_id(cell), log_id(module), log_signal(y_value));
@@ -1423,10 +1471,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 				log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
 						redundant_bits, log_id(cell->type), log_id(cell), log_id(module));
 
-				cell->setPort("\\A", sig_a);
-				cell->setPort("\\B", sig_b);
-				cell->setParam("\\A_WIDTH", GetSize(sig_a));
-				cell->setParam("\\B_WIDTH", GetSize(sig_b));
+				cell->setPort(ID(A), sig_a);
+				cell->setPort(ID(B), sig_b);
+				cell->setParam(ID(A_WIDTH), GetSize(sig_a));
+				cell->setParam(ID(B_WIDTH), GetSize(sig_b));
 
 				did_something = true;
 				goto next_cell;
@@ -1434,57 +1482,57 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 		}
 
 		// simplify comparisons
-		if (do_fine && cell->type.in("$lt", "$ge", "$gt", "$le"))
+		if (do_fine && cell->type.in(ID($lt), ID($ge), ID($gt), ID($le)))
 		{
 			IdString cmp_type = cell->type;
-			SigSpec var_sig = cell->getPort("\\A");
-			SigSpec const_sig = cell->getPort("\\B");
-			int var_width = cell->parameters["\\A_WIDTH"].as_int();
-			int const_width = cell->parameters["\\B_WIDTH"].as_int();
-			bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
+			SigSpec var_sig = cell->getPort(ID(A));
+			SigSpec const_sig = cell->getPort(ID(B));
+			int var_width = cell->parameters[ID(A_WIDTH)].as_int();
+			int const_width = cell->parameters[ID(B_WIDTH)].as_int();
+			bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 
 			if (!const_sig.is_fully_const())
 			{
 				std::swap(var_sig, const_sig);
 				std::swap(var_width, const_width);
-				if (cmp_type == "$gt")
-					cmp_type = "$lt";
-				else if (cmp_type == "$lt")
-					cmp_type = "$gt";
-				else if (cmp_type == "$ge")
-					cmp_type = "$le";
-				else if (cmp_type == "$le")
-					cmp_type = "$ge";
+				if (cmp_type == ID($gt))
+					cmp_type = ID($lt);
+				else if (cmp_type == ID($lt))
+					cmp_type = ID($gt);
+				else if (cmp_type == ID($ge))
+					cmp_type = ID($le);
+				else if (cmp_type == ID($le))
+					cmp_type = ID($ge);
 			}
 
 			if (const_sig.is_fully_def() && const_sig.is_fully_const())
 			{
 				std::string condition, replacement;
-				SigSpec replace_sig(State::S0, GetSize(cell->getPort("\\Y")));
+				SigSpec replace_sig(State::S0, GetSize(cell->getPort(ID(Y))));
 				bool replace = false;
 				bool remove = false;
 
 				if (!is_signed)
 				{ /* unsigned */
-					if (const_sig.is_fully_zero() && cmp_type == "$lt") {
+					if (const_sig.is_fully_zero() && cmp_type == ID($lt)) {
 						condition   = "unsigned X<0";
 						replacement = "constant 0";
 						replace_sig[0] = State::S0;
 						replace = true;
 					}
-					if (const_sig.is_fully_zero() && cmp_type == "$ge") {
+					if (const_sig.is_fully_zero() && cmp_type == ID($ge)) {
 						condition   = "unsigned X>=0";
 						replacement = "constant 1";
 						replace_sig[0] = State::S1;
 						replace = true;
 					}
-					if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$gt") {
+					if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == ID($gt)) {
 						condition   = "unsigned X>~0";
 						replacement = "constant 0";
 						replace_sig[0] = State::S0;
 						replace = true;
 					}
-					if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$le") {
+					if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == ID($le)) {
 						condition   = "unsigned X<=~0";
 						replacement = "constant 1";
 						replace_sig[0] = State::S1;
@@ -1499,18 +1547,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 							var_high_sig[i - const_bit_hot] = var_sig[i];
 						}
 
-						if (cmp_type == "$lt")
+						if (cmp_type == ID($lt))
 						{
 							condition   = stringf("unsigned X<%s", log_signal(const_sig));
 							replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot);
-							module->addLogicNot(NEW_ID, var_high_sig, cell->getPort("\\Y"));
+							module->addLogicNot(NEW_ID, var_high_sig, cell->getPort(ID(Y)));
 							remove = true;
 						}
-						if (cmp_type == "$ge")
+						if (cmp_type == ID($ge))
 						{
 							condition   = stringf("unsigned X>=%s", log_signal(const_sig));
 							replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot);
-							module->addReduceOr(NEW_ID, var_high_sig, cell->getPort("\\Y"));
+							module->addReduceOr(NEW_ID, var_high_sig, cell->getPort(ID(Y)));
 							remove = true;
 						}
 					}
@@ -1519,19 +1567,19 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					if(const_bit_set >= var_width)
 					{
 						string cmp_name;
-						if (cmp_type == "$lt" || cmp_type == "$le")
+						if (cmp_type == ID($lt) || cmp_type == ID($le))
 						{
-							if (cmp_type == "$lt") cmp_name = "<";
-							if (cmp_type == "$le") cmp_name = "<=";
+							if (cmp_type == ID($lt)) cmp_name = "<";
+							if (cmp_type == ID($le)) cmp_name = "<=";
 							condition   = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig));
 							replacement = "constant 1";
 							replace_sig[0] = State::S1;
 							replace = true;
 						}
-						if (cmp_type == "$gt" || cmp_type == "$ge")
+						if (cmp_type == ID($gt) || cmp_type == ID($ge))
 						{
-							if (cmp_type == "$gt") cmp_name = ">";
-							if (cmp_type == "$ge") cmp_name = ">=";
+							if (cmp_type == ID($gt)) cmp_name = ">";
+							if (cmp_type == ID($ge)) cmp_name = ">=";
 							condition   = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig));
 							replacement = "constant 0";
 							replace_sig[0] = State::S0;
@@ -1541,18 +1589,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 				}
 				else
 				{ /* signed */
-					if (const_sig.is_fully_zero() && cmp_type == "$lt")
+					if (const_sig.is_fully_zero() && cmp_type == ID($lt))
 					{
 						condition   = "signed X<0";
 						replacement = stringf("X[%d]", var_width - 1);
 						replace_sig[0] = var_sig[var_width - 1];
 						replace = true;
 					}
-					if (const_sig.is_fully_zero() && cmp_type == "$ge")
+					if (const_sig.is_fully_zero() && cmp_type == ID($ge))
 					{
 						condition   = "signed X>=0";
 						replacement = stringf("X[%d]", var_width - 1);
-						module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort("\\Y"));
+						module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort(ID(Y)));
 						remove = true;
 					}
 				}
@@ -1562,7 +1610,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 					log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n",
 							log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
 					if (replace)
-						module->connect(cell->getPort("\\Y"), replace_sig);
+						module->connect(cell->getPort(ID(Y)), replace_sig);
 					module->remove(cell);
 					did_something = true;
 					goto next_cell;
diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc
index 4c199ba72..e9d72044b 100644
--- a/passes/opt/opt_lut.cc
+++ b/passes/opt/opt_lut.cc
@@ -40,9 +40,9 @@ struct OptLutWorker
 
 	bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
 	{
-		SigSpec lut_input = sigmap(lut->getPort("\\A"));
-		int lut_width = lut->getParam("\\WIDTH").as_int();
-		Const lut_table = lut->getParam("\\LUT");
+		SigSpec lut_input = sigmap(lut->getPort(ID(A)));
+		int lut_width = lut->getParam(ID(WIDTH)).as_int();
+		Const lut_table = lut->getParam(ID(LUT));
 		int lut_index = 0;
 
 		for (int i = 0; i < lut_width; i++)
@@ -99,16 +99,16 @@ struct OptLutWorker
 		log("Discovering LUTs.\n");
 		for (auto cell : module->selected_cells())
 		{
-			if (cell->type == "$lut")
+			if (cell->type == ID($lut))
 			{
 				if (cell->has_keep_attr())
 					continue;
-				SigBit lut_output = cell->getPort("\\Y");
-				if (lut_output.wire->get_bool_attribute("\\keep"))
+				SigBit lut_output = cell->getPort(ID(Y));
+				if (lut_output.wire->get_bool_attribute(ID(keep)))
 					continue;
 
-				int lut_width = cell->getParam("\\WIDTH").as_int();
-				SigSpec lut_input = cell->getPort("\\A");
+				int lut_width = cell->getParam(ID(WIDTH)).as_int();
+				SigSpec lut_input = cell->getPort(ID(A));
 				int lut_arity = 0;
 
 				log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
@@ -205,7 +205,7 @@ struct OptLutWorker
 			}
 
 			auto lut = worklist.pop();
-			SigSpec lut_input = sigmap(lut->getPort("\\A"));
+			SigSpec lut_input = sigmap(lut->getPort(ID(A)));
 			pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
 
 			vector<SigBit> lut_inputs;
@@ -267,7 +267,7 @@ struct OptLutWorker
 					log_debug("  Not eliminating cell (connected to dedicated logic).\n");
 				else
 				{
-					SigSpec lut_output = lut->getPort("\\Y");
+					SigSpec lut_output = lut->getPort(ID(Y));
 					for (auto &port : index.query_ports(lut_output))
 					{
 						if (port.cell != lut && luts.count(port.cell))
@@ -303,13 +303,13 @@ struct OptLutWorker
 			}
 
 			auto lutA = worklist.pop();
-			SigSpec lutA_input = sigmap(lutA->getPort("\\A"));
-			SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]);
-			int lutA_width = lutA->getParam("\\WIDTH").as_int();
+			SigSpec lutA_input = sigmap(lutA->getPort(ID(A)));
+			SigSpec lutA_output = sigmap(lutA->getPort(ID(Y))[0]);
+			int lutA_width = lutA->getParam(ID(WIDTH)).as_int();
 			int lutA_arity = luts_arity[lutA];
 			pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[lutA];
 
-			auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y"));
+			auto lutA_output_ports = index.query_ports(lutA->getPort(ID(Y)));
 			if (lutA_output_ports.size() != 2)
 				continue;
 
@@ -321,15 +321,15 @@ struct OptLutWorker
 				if (luts.count(port.cell))
 				{
 					auto lutB = port.cell;
-					SigSpec lutB_input = sigmap(lutB->getPort("\\A"));
-					SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]);
-					int lutB_width = lutB->getParam("\\WIDTH").as_int();
+					SigSpec lutB_input = sigmap(lutB->getPort(ID(A)));
+					SigSpec lutB_output = sigmap(lutB->getPort(ID(Y))[0]);
+					int lutB_width = lutB->getParam(ID(WIDTH)).as_int();
 					int lutB_arity = luts_arity[lutB];
 					pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
 
 					log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
 
-					if (index.query_is_output(lutA->getPort("\\Y")))
+					if (index.query_is_output(lutA->getPort(ID(Y))))
 					{
 						log_debug("  Not combining LUTs (cascade connection feeds module output).\n");
 						continue;
@@ -372,7 +372,7 @@ struct OptLutWorker
 						log_debug("  Not combining LUTs into cell A (combined LUT wider than cell A).\n");
 					else if (lutB_dlogic_inputs.size() > 0)
 						log_debug("  Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
-					else if (lutB->get_bool_attribute("\\lut_keep"))
+					else if (lutB->get_bool_attribute(ID(lut_keep)))
 						log_debug("  Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
 					else
 						combine_mask |= COMBINE_A;
@@ -380,7 +380,7 @@ struct OptLutWorker
 						log_debug("  Not combining LUTs into cell B (combined LUT wider than cell B).\n");
 					else if (lutA_dlogic_inputs.size() > 0)
 						log_debug("  Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
-					else if (lutA->get_bool_attribute("\\lut_keep"))
+					else if (lutA->get_bool_attribute(ID(lut_keep)))
 						log_debug("  Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
 					else
 						combine_mask |= COMBINE_B;
@@ -440,8 +440,8 @@ struct OptLutWorker
 							lutR_unique.insert(bit);
 					}
 
-					int lutM_width = lutM->getParam("\\WIDTH").as_int();
-					SigSpec lutM_input = sigmap(lutM->getPort("\\A"));
+					int lutM_width = lutM->getParam(ID(WIDTH)).as_int();
+					SigSpec lutM_input = sigmap(lutM->getPort(ID(A)));
 					std::vector<SigBit> lutM_new_inputs;
 					for (int i = 0; i < lutM_width; i++)
 					{
@@ -482,13 +482,13 @@ struct OptLutWorker
 						lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs);
 					}
 
-					log_debug("  Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
-					log_debug("  Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
+					log_debug("  Cell A truth table: %s.\n", lutA->getParam(ID(LUT)).as_string().c_str());
+					log_debug("  Cell B truth table: %s.\n", lutB->getParam(ID(LUT)).as_string().c_str());
 					log_debug("  Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
 
-					lutM->setParam("\\LUT", lutM_new_table);
-					lutM->setPort("\\A", lutM_new_inputs);
-					lutM->setPort("\\Y", lutB_output);
+					lutM->setParam(ID(LUT), lutM_new_table);
+					lutM->setPort(ID(A), lutM_new_inputs);
+					lutM->setPort(ID(Y), lutB_output);
 
 					luts_arity[lutM] = lutM_arity;
 					luts.erase(lutR);
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index cac7c0a6f..aa1a5c75c 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -47,8 +47,8 @@ struct OptMergeWorker
 
 	static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
 	{
-		SigSpec sig_s = conn.at("\\S");
-		SigSpec sig_b = conn.at("\\B");
+		SigSpec sig_s = conn.at(ID(S));
+		SigSpec sig_b = conn.at(ID(B));
 
 		int s_width = GetSize(sig_s);
 		int width = GetSize(sig_b) / s_width;
@@ -59,12 +59,12 @@ struct OptMergeWorker
 
 		std::sort(sb_pairs.begin(), sb_pairs.end());
 
-		conn["\\S"] = SigSpec();
-		conn["\\B"] = SigSpec();
+		conn[ID(S)] = SigSpec();
+		conn[ID(B)] = SigSpec();
 
 		for (auto &it : sb_pairs) {
-			conn["\\S"].append(it.first);
-			conn["\\B"].append(it.second);
+			conn[ID(S)].append(it.first);
+			conn[ID(B)].append(it.second);
 		}
 	}
 
@@ -94,32 +94,32 @@ struct OptMergeWorker
 		const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections();
 		dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn;
 
-		if (cell->type.in("$and", "$or", "$xor", "$xnor", "$add", "$mul",
-				"$logic_and", "$logic_or", "$_AND_", "$_OR_", "$_XOR_")) {
+		if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
+				ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
 			alt_conn = *conn;
-			if (assign_map(alt_conn.at("\\A")) < assign_map(alt_conn.at("\\B"))) {
-				alt_conn["\\A"] = conn->at("\\B");
-				alt_conn["\\B"] = conn->at("\\A");
+			if (assign_map(alt_conn.at(ID(A))) < assign_map(alt_conn.at(ID(B)))) {
+				alt_conn[ID(A)] = conn->at(ID(B));
+				alt_conn[ID(B)] = conn->at(ID(A));
 			}
 			conn = &alt_conn;
 		} else
-		if (cell->type.in("$reduce_xor", "$reduce_xnor")) {
+		if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
 			alt_conn = *conn;
-			assign_map.apply(alt_conn.at("\\A"));
-			alt_conn.at("\\A").sort();
+			assign_map.apply(alt_conn.at(ID(A)));
+			alt_conn.at(ID(A)).sort();
 			conn = &alt_conn;
 		} else
-		if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool")) {
+		if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
 			alt_conn = *conn;
-			assign_map.apply(alt_conn.at("\\A"));
-			alt_conn.at("\\A").sort_and_unify();
+			assign_map.apply(alt_conn.at(ID(A)));
+			alt_conn.at(ID(A)).sort_and_unify();
 			conn = &alt_conn;
 		} else
-		if (cell->type == "$pmux") {
+		if (cell->type == ID($pmux)) {
 			alt_conn = *conn;
-			assign_map.apply(alt_conn.at("\\A"));
-			assign_map.apply(alt_conn.at("\\B"));
-			assign_map.apply(alt_conn.at("\\S"));
+			assign_map.apply(alt_conn.at(ID(A)));
+			assign_map.apply(alt_conn.at(ID(B)));
+			assign_map.apply(alt_conn.at(ID(S)));
 			sort_pmux_conn(alt_conn);
 			conn = &alt_conn;
 		}
@@ -189,28 +189,28 @@ struct OptMergeWorker
 				assign_map.apply(it.second);
 		}
 
-		if (cell1->type == "$and" || cell1->type == "$or" || cell1->type == "$xor" || cell1->type == "$xnor" || cell1->type == "$add" || cell1->type == "$mul" ||
-				cell1->type == "$logic_and" || cell1->type == "$logic_or" || cell1->type == "$_AND_" || cell1->type == "$_OR_" || cell1->type == "$_XOR_") {
-			if (conn1.at("\\A") < conn1.at("\\B")) {
-				RTLIL::SigSpec tmp = conn1["\\A"];
-				conn1["\\A"] = conn1["\\B"];
-				conn1["\\B"] = tmp;
+		if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) ||
+				cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) {
+			if (conn1.at(ID(A)) < conn1.at(ID(B))) {
+				RTLIL::SigSpec tmp = conn1[ID(A)];
+				conn1[ID(A)] = conn1[ID(B)];
+				conn1[ID(B)] = tmp;
 			}
-			if (conn2.at("\\A") < conn2.at("\\B")) {
-				RTLIL::SigSpec tmp = conn2["\\A"];
-				conn2["\\A"] = conn2["\\B"];
-				conn2["\\B"] = tmp;
+			if (conn2.at(ID(A)) < conn2.at(ID(B))) {
+				RTLIL::SigSpec tmp = conn2[ID(A)];
+				conn2[ID(A)] = conn2[ID(B)];
+				conn2[ID(B)] = tmp;
 			}
 		} else
-		if (cell1->type == "$reduce_xor" || cell1->type == "$reduce_xnor") {
-			conn1["\\A"].sort();
-			conn2["\\A"].sort();
+		if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) {
+			conn1[ID(A)].sort();
+			conn2[ID(A)].sort();
 		} else
-		if (cell1->type == "$reduce_and" || cell1->type == "$reduce_or" || cell1->type == "$reduce_bool") {
-			conn1["\\A"].sort_and_unify();
-			conn2["\\A"].sort_and_unify();
+		if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) {
+			conn1[ID(A)].sort_and_unify();
+			conn2[ID(A)].sort_and_unify();
 		} else
-		if (cell1->type == "$pmux") {
+		if (cell1->type == ID($pmux)) {
 			sort_pmux_conn(conn1);
 			sort_pmux_conn(conn2);
 		}
@@ -222,9 +222,9 @@ struct OptMergeWorker
 			return true;
 		}
 
-		if (cell1->type.begins_with("$") && conn1.count("\\Q") != 0) {
-			std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort("\\Q")).to_sigbit_vector();
-			std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort("\\Q")).to_sigbit_vector();
+		if (cell1->type.begins_with("$") && conn1.count(ID(Q)) != 0) {
+			std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector();
+			std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector();
 			for (size_t i = 0; i < q1.size(); i++)
 				if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) {
 					lt = q1.at(i) < q2.at(i);
@@ -271,24 +271,24 @@ struct OptMergeWorker
 		ct.setup_stdcells_mem();
 
 		if (mode_nomux) {
-			ct.cell_types.erase("$mux");
-			ct.cell_types.erase("$pmux");
+			ct.cell_types.erase(ID($mux));
+			ct.cell_types.erase(ID($pmux));
 		}
 
-		ct.cell_types.erase("$tribuf");
-		ct.cell_types.erase("$_TBUF_");
-		ct.cell_types.erase("$anyseq");
-		ct.cell_types.erase("$anyconst");
-		ct.cell_types.erase("$allseq");
-		ct.cell_types.erase("$allconst");
+		ct.cell_types.erase(ID($tribuf));
+		ct.cell_types.erase(ID($_TBUF_));
+		ct.cell_types.erase(ID($anyseq));
+		ct.cell_types.erase(ID($anyconst));
+		ct.cell_types.erase(ID($allseq));
+		ct.cell_types.erase(ID($allconst));
 
 		log("Finding identical cells in module `%s'.\n", module->name.c_str());
 		assign_map.set(module);
 
 		dff_init_map.set(module);
 		for (auto &it : module->wires_)
-			if (it.second->attributes.count("\\init") != 0) {
-				Const initval = it.second->attributes.at("\\init");
+			if (it.second->attributes.count(ID(init)) != 0) {
+				Const initval = it.second->attributes.at(ID(init));
 				for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++)
 					if (initval[i] == State::S0 || initval[i] == State::S1)
 						dff_init_map.add(SigBit(it.second, i), initval[i]);
diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc
index 4b96fe524..61f194569 100644
--- a/passes/opt/opt_muxtree.cc
+++ b/passes/opt/opt_muxtree.cc
@@ -84,12 +84,12 @@ struct OptMuxtreeWorker
 		//	.const_deactivated
 		for (auto cell : module->cells())
 		{
-			if (cell->type.in("$mux", "$pmux"))
+			if (cell->type.in(ID($mux), ID($pmux)))
 			{
-				RTLIL::SigSpec sig_a = cell->getPort("\\A");
-				RTLIL::SigSpec sig_b = cell->getPort("\\B");
-				RTLIL::SigSpec sig_s = cell->getPort("\\S");
-				RTLIL::SigSpec sig_y = cell->getPort("\\Y");
+				RTLIL::SigSpec sig_a = cell->getPort(ID(A));
+				RTLIL::SigSpec sig_b = cell->getPort(ID(B));
+				RTLIL::SigSpec sig_s = cell->getPort(ID(S));
+				RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 
 				muxinfo_t muxinfo;
 				muxinfo.cell = cell;
@@ -137,7 +137,7 @@ struct OptMuxtreeWorker
 			}
 		}
 		for (auto wire : module->wires()) {
-			if (wire->port_output || wire->get_bool_attribute("\\keep"))
+			if (wire->port_output || wire->get_bool_attribute(ID(keep)))
 				for (int idx : sig2bits(RTLIL::SigSpec(wire)))
 					bit2info[idx].seen_non_mux = true;
 		}
@@ -227,10 +227,10 @@ struct OptMuxtreeWorker
 				continue;
 			}
 
-			RTLIL::SigSpec sig_a = mi.cell->getPort("\\A");
-			RTLIL::SigSpec sig_b = mi.cell->getPort("\\B");
-			RTLIL::SigSpec sig_s = mi.cell->getPort("\\S");
-			RTLIL::SigSpec sig_y = mi.cell->getPort("\\Y");
+			RTLIL::SigSpec sig_a = mi.cell->getPort(ID(A));
+			RTLIL::SigSpec sig_b = mi.cell->getPort(ID(B));
+			RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S));
+			RTLIL::SigSpec sig_y = mi.cell->getPort(ID(Y));
 
 			RTLIL::SigSpec sig_ports = sig_b;
 			sig_ports.append(sig_a);
@@ -255,14 +255,14 @@ struct OptMuxtreeWorker
 					}
 				}
 
-				mi.cell->setPort("\\A", new_sig_a);
-				mi.cell->setPort("\\B", new_sig_b);
-				mi.cell->setPort("\\S", new_sig_s);
+				mi.cell->setPort(ID(A), new_sig_a);
+				mi.cell->setPort(ID(B), new_sig_b);
+				mi.cell->setPort(ID(S), new_sig_s);
 				if (GetSize(new_sig_s) == 1) {
-					mi.cell->type = "$mux";
-					mi.cell->parameters.erase("\\S_WIDTH");
+					mi.cell->type = ID($mux);
+					mi.cell->parameters.erase(ID(S_WIDTH));
 				} else {
-					mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(GetSize(new_sig_s));
+					mi.cell->parameters[ID(S_WIDTH)] = RTLIL::Const(GetSize(new_sig_s));
 				}
 			}
 		}
@@ -364,9 +364,9 @@ struct OptMuxtreeWorker
 
 		int width = 0;
 		idict<int> ctrl_bits;
-		if (portname == "\\B")
-			width = GetSize(muxinfo.cell->getPort("\\A"));
-		for (int bit : sig2bits(muxinfo.cell->getPort("\\S"), false))
+		if (portname == ID(B))
+			width = GetSize(muxinfo.cell->getPort(ID(A)));
+		for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false))
 			ctrl_bits(bit);
 
 		int port_idx = 0, port_off = 0;
@@ -414,8 +414,8 @@ struct OptMuxtreeWorker
 
 		// set input ports to constants if we find known active or inactive signals
 		if (do_replace_known) {
-			replace_known(knowledge, muxinfo, "\\A");
-			replace_known(knowledge, muxinfo, "\\B");
+			replace_known(knowledge, muxinfo, ID(A));
+			replace_known(knowledge, muxinfo, ID(B));
 		}
 
 		// if there is a constant activated port we just use it
diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc
index d99f1ca6a..332e0443e 100644
--- a/passes/opt/opt_reduce.cc
+++ b/passes/opt/opt_reduce.cc
@@ -43,13 +43,13 @@ struct OptReduceWorker
 			return;
 		cells.erase(cell);
 
-		RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
+		RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
 		pool<RTLIL::SigBit> new_sig_a_bits;
 
 		for (auto &bit : sig_a.to_sigbit_set())
 		{
 			if (bit == RTLIL::State::S0) {
-				if (cell->type == "$reduce_and") {
+				if (cell->type == ID($reduce_and)) {
 					new_sig_a_bits.clear();
 					new_sig_a_bits.insert(RTLIL::State::S0);
 					break;
@@ -57,7 +57,7 @@ struct OptReduceWorker
 				continue;
 			}
 			if (bit == RTLIL::State::S1) {
-				if (cell->type == "$reduce_or") {
+				if (cell->type == ID($reduce_or)) {
 					new_sig_a_bits.clear();
 					new_sig_a_bits.insert(RTLIL::State::S1);
 					break;
@@ -73,8 +73,8 @@ struct OptReduceWorker
 			for (auto child_cell : drivers.find(bit)) {
 				if (child_cell->type == cell->type) {
 					opt_reduce(cells, drivers, child_cell);
-					if (child_cell->getPort("\\Y")[0] == bit) {
-						pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort("\\A")).to_sigbit_pool();
+					if (child_cell->getPort(ID(Y))[0] == bit) {
+						pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort(ID(A))).to_sigbit_pool();
 						new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end());
 					} else
 						new_sig_a_bits.insert(RTLIL::State::S0);
@@ -87,22 +87,22 @@ struct OptReduceWorker
 
 		RTLIL::SigSpec new_sig_a(new_sig_a_bits);
 
-		if (new_sig_a != sig_a || sig_a.size() != cell->getPort("\\A").size()) {
+		if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID(A)).size()) {
 			log("    New input vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_a));
 			did_something = true;
 			total_count++;
 		}
 
-		cell->setPort("\\A", new_sig_a);
-		cell->parameters["\\A_WIDTH"] = RTLIL::Const(new_sig_a.size());
+		cell->setPort(ID(A), new_sig_a);
+		cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size());
 		return;
 	}
 
 	void opt_mux(RTLIL::Cell *cell)
 	{
-		RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
-		RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
-		RTLIL::SigSpec sig_s = assign_map(cell->getPort("\\S"));
+		RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
+		RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
+		RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S)));
 
 		RTLIL::SigSpec new_sig_b, new_sig_s;
 		pool<RTLIL::SigSpec> handled_sig;
@@ -123,15 +123,15 @@ struct OptReduceWorker
 
 			if (this_s.size() > 1)
 			{
-				RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, "$reduce_or");
-				reduce_or_cell->setPort("\\A", this_s);
-				reduce_or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
-				reduce_or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(this_s.size());
-				reduce_or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
+				RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or));
+				reduce_or_cell->setPort(ID(A), this_s);
+				reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0);
+				reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size());
+				reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1);
 
 				RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID);
 				this_s = RTLIL::SigSpec(reduce_or_wire);
-				reduce_or_cell->setPort("\\Y", this_s);
+				reduce_or_cell->setPort(ID(Y), this_s);
 			}
 
 			new_sig_b.append(this_b);
@@ -147,28 +147,28 @@ struct OptReduceWorker
 
 		if (new_sig_s.size() == 0)
 		{
-			module->connect(RTLIL::SigSig(cell->getPort("\\Y"), cell->getPort("\\A")));
-			assign_map.add(cell->getPort("\\Y"), cell->getPort("\\A"));
+			module->connect(RTLIL::SigSig(cell->getPort(ID(Y)), cell->getPort(ID(A))));
+			assign_map.add(cell->getPort(ID(Y)), cell->getPort(ID(A)));
 			module->remove(cell);
 		}
 		else
 		{
-			cell->setPort("\\B", new_sig_b);
-			cell->setPort("\\S", new_sig_s);
+			cell->setPort(ID(B), new_sig_b);
+			cell->setPort(ID(S), new_sig_s);
 			if (new_sig_s.size() > 1) {
-				cell->parameters["\\S_WIDTH"] = RTLIL::Const(new_sig_s.size());
+				cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size());
 			} else {
-				cell->type = "$mux";
-				cell->parameters.erase("\\S_WIDTH");
+				cell->type = ID($mux);
+				cell->parameters.erase(ID(S_WIDTH));
 			}
 		}
 	}
 
 	void opt_mux_bits(RTLIL::Cell *cell)
 	{
-		std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort("\\A")).to_sigbit_vector();
-		std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort("\\B")).to_sigbit_vector();
-		std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort("\\Y")).to_sigbit_vector();
+		std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID(A))).to_sigbit_vector();
+		std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID(B))).to_sigbit_vector();
+		std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID(Y))).to_sigbit_vector();
 
 		std::vector<RTLIL::SigBit> new_sig_y;
 		RTLIL::SigSig old_sig_conn;
@@ -209,29 +209,29 @@ struct OptReduceWorker
 		if (new_sig_y.size() != sig_y.size())
 		{
 			log("    Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
-			log("      Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")),
-					log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y")));
+			log("      Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))),
+					log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y))));
 
-			cell->setPort("\\A", RTLIL::SigSpec());
+			cell->setPort(ID(A), RTLIL::SigSpec());
 			for (auto &in_tuple : consolidated_in_tuples) {
-				RTLIL::SigSpec new_a = cell->getPort("\\A");
+				RTLIL::SigSpec new_a = cell->getPort(ID(A));
 				new_a.append(in_tuple.at(0));
-				cell->setPort("\\A", new_a);
+				cell->setPort(ID(A), new_a);
 			}
 
-			cell->setPort("\\B", RTLIL::SigSpec());
-			for (int i = 1; i <= cell->getPort("\\S").size(); i++)
+			cell->setPort(ID(B), RTLIL::SigSpec());
+			for (int i = 1; i <= cell->getPort(ID(S)).size(); i++)
 				for (auto &in_tuple : consolidated_in_tuples) {
-					RTLIL::SigSpec new_b = cell->getPort("\\B");
+					RTLIL::SigSpec new_b = cell->getPort(ID(B));
 					new_b.append(in_tuple.at(i));
-					cell->setPort("\\B", new_b);
+					cell->setPort(ID(B), new_b);
 				}
 
-			cell->parameters["\\WIDTH"] = RTLIL::Const(new_sig_y.size());
-			cell->setPort("\\Y", new_sig_y);
+			cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size());
+			cell->setPort(ID(Y), new_sig_y);
 
-			log("      New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")),
-					log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y")));
+			log("      New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))),
+					log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y))));
 			log("      New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
 
 			module->connect(old_sig_conn);
@@ -253,15 +253,15 @@ struct OptReduceWorker
 		SigPool mem_wren_sigs;
 		for (auto &cell_it : module->cells_) {
 			RTLIL::Cell *cell = cell_it.second;
-			if (cell->type == "$mem")
-				mem_wren_sigs.add(assign_map(cell->getPort("\\WR_EN")));
-			if (cell->type == "$memwr")
-				mem_wren_sigs.add(assign_map(cell->getPort("\\EN")));
+			if (cell->type == ID($mem))
+				mem_wren_sigs.add(assign_map(cell->getPort(ID(WR_EN))));
+			if (cell->type == ID($memwr))
+				mem_wren_sigs.add(assign_map(cell->getPort(ID(EN))));
 		}
 		for (auto &cell_it : module->cells_) {
 			RTLIL::Cell *cell = cell_it.second;
-			if (cell->type == "$dff" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Q"))))
-				mem_wren_sigs.add(assign_map(cell->getPort("\\D")));
+			if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Q)))))
+				mem_wren_sigs.add(assign_map(cell->getPort(ID(D))));
 		}
 
 		bool keep_expanding_mem_wren_sigs = true;
@@ -269,12 +269,12 @@ struct OptReduceWorker
 			keep_expanding_mem_wren_sigs = false;
 			for (auto &cell_it : module->cells_) {
 				RTLIL::Cell *cell = cell_it.second;
-				if (cell->type == "$mux" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y")))) {
-					if (!mem_wren_sigs.check_all(assign_map(cell->getPort("\\A"))) ||
-							!mem_wren_sigs.check_all(assign_map(cell->getPort("\\B"))))
+				if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y))))) {
+					if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(A)))) ||
+							!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(B)))))
 						keep_expanding_mem_wren_sigs = true;
-					mem_wren_sigs.add(assign_map(cell->getPort("\\A")));
-					mem_wren_sigs.add(assign_map(cell->getPort("\\B")));
+					mem_wren_sigs.add(assign_map(cell->getPort(ID(A))));
+					mem_wren_sigs.add(assign_map(cell->getPort(ID(B))));
 				}
 			}
 		}
@@ -286,7 +286,7 @@ struct OptReduceWorker
 			// merge trees of reduce_* cells to one single cell and unify input vectors
 			// (only handle reduce_and and reduce_or for various reasons)
 
-			const char *type_list[] = { "$reduce_or", "$reduce_and" };
+			const IdString type_list[] = { ID($reduce_or), ID($reduce_and) };
 			for (auto type : type_list)
 			{
 				SigSet<RTLIL::Cell*> drivers;
@@ -296,7 +296,7 @@ struct OptReduceWorker
 					RTLIL::Cell *cell = cell_it.second;
 					if (cell->type != type || !design->selected(module, cell))
 						continue;
-					drivers.insert(assign_map(cell->getPort("\\Y")), cell);
+					drivers.insert(assign_map(cell->getPort(ID(Y))), cell);
 					cells.insert(cell);
 				}
 
@@ -311,14 +311,14 @@ struct OptReduceWorker
 			std::vector<RTLIL::Cell*> cells;
 
 			for (auto &it : module->cells_)
-				if ((it.second->type == "$mux" || it.second->type == "$pmux") && design->selected(module, it.second))
+				if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second))
 					cells.push_back(it.second);
 
 			for (auto cell : cells)
 			{
 				// this optimization is to aggressive for most coarse-grain applications.
 				// but we always want it for multiplexers driving write enable ports.
-				if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y"))))
+				if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y)))))
 					opt_mux_bits(cell);
 
 				opt_mux(cell);
diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc
index 8d42a37c3..4ba61e512 100644
--- a/passes/opt/opt_rmdff.cc
+++ b/passes/opt/opt_rmdff.cc
@@ -41,7 +41,7 @@ void remove_init_attr(SigSpec sig)
 	for (auto bit : assign_map(sig))
 		if (init_attributes.count(bit))
 			for (auto wbit : init_attributes.at(bit))
-				wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx;
+				wbit.wire->attributes.at(ID(init))[wbit.offset] = State::Sx;
 }
 
 bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
@@ -49,17 +49,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 	SigSpec sig_set, sig_clr;
 	State pol_set, pol_clr;
 
-	if (cell->hasPort("\\S"))
-		sig_set = cell->getPort("\\S");
+	if (cell->hasPort(ID(S)))
+		sig_set = cell->getPort(ID(S));
 
-	if (cell->hasPort("\\R"))
-		sig_clr = cell->getPort("\\R");
+	if (cell->hasPort(ID(R)))
+		sig_clr = cell->getPort(ID(R));
 
-	if (cell->hasPort("\\SET"))
-		sig_set = cell->getPort("\\SET");
+	if (cell->hasPort(ID(SET)))
+		sig_set = cell->getPort(ID(SET));
 
-	if (cell->hasPort("\\CLR"))
-		sig_clr = cell->getPort("\\CLR");
+	if (cell->hasPort(ID(CLR)))
+		sig_clr = cell->getPort(ID(CLR));
 
 	log_assert(GetSize(sig_set) == GetSize(sig_clr));
 
@@ -71,17 +71,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 		pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
 		pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
 	} else
-	if (cell->type.in("$dffsr", "$dlatchsr")) {
-		pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0;
-		pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0;
+	if (cell->type.in(ID($dffsr), ID($dlatchsr))) {
+		pol_set = cell->parameters[ID(SET_POLARITY)].as_bool() ? State::S1 : State::S0;
+		pol_clr = cell->parameters[ID(CLR_POLARITY)].as_bool() ? State::S1 : State::S0;
 	} else
 		log_abort();
 
 	State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
 	State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;
 
-	SigSpec sig_d = cell->getPort("\\D");
-	SigSpec sig_q = cell->getPort("\\Q");
+	SigSpec sig_d = cell->getPort(ID(D));
+	SigSpec sig_q = cell->getPort(ID(Q));
 
 	bool did_something = false;
 	bool proper_sr = false;
@@ -137,20 +137,20 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 		return true;
 	}
 
-	if (cell->type.in("$dffsr", "$dlatchsr"))
+	if (cell->type.in(ID($dffsr), ID($dlatchsr)))
 	{
-		cell->setParam("\\WIDTH", GetSize(sig_d));
-		cell->setPort("\\SET", sig_set);
-		cell->setPort("\\CLR", sig_clr);
-		cell->setPort("\\D", sig_d);
-		cell->setPort("\\Q", sig_q);
+		cell->setParam(ID(WIDTH), GetSize(sig_d));
+		cell->setPort(ID(SET), sig_set);
+		cell->setPort(ID(CLR), sig_clr);
+		cell->setPort(ID(D), sig_d);
+		cell->setPort(ID(Q), sig_q);
 	}
 	else
 	{
-		cell->setPort("\\S", sig_set);
-		cell->setPort("\\R", sig_clr);
-		cell->setPort("\\D", sig_d);
-		cell->setPort("\\Q", sig_q);
+		cell->setPort(ID(S), sig_set);
+		cell->setPort(ID(R), sig_clr);
+		cell->setPort(ID(D), sig_d);
+		cell->setPort(ID(Q), sig_q);
 	}
 
 	if (proper_sr)
@@ -159,36 +159,36 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 	if (used_pol_set && used_pol_clr && pol_set != pol_clr)
 		return did_something;
 
-	if (cell->type == "$dlatchsr")
+	if (cell->type == ID($dlatchsr))
 		return did_something;
 
 	State unified_pol = used_pol_set ? pol_set : pol_clr;
 
-	if (cell->type == "$dffsr")
+	if (cell->type == ID($dffsr))
 	{
 		if (hasreset)
 		{
 			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));
 
-			cell->type = "$adff";
-			cell->setParam("\\ARST_POLARITY", unified_pol);
-			cell->setParam("\\ARST_VALUE", reset_val);
-			cell->setPort("\\ARST", sig_reset);
+			cell->type = ID($adff);
+			cell->setParam(ID(ARST_POLARITY), unified_pol);
+			cell->setParam(ID(ARST_VALUE), reset_val);
+			cell->setPort(ID(ARST), sig_reset);
 
-			cell->unsetParam("\\SET_POLARITY");
-			cell->unsetParam("\\CLR_POLARITY");
-			cell->unsetPort("\\SET");
-			cell->unsetPort("\\CLR");
+			cell->unsetParam(ID(SET_POLARITY));
+			cell->unsetParam(ID(CLR_POLARITY));
+			cell->unsetPort(ID(SET));
+			cell->unsetPort(ID(CLR));
 		}
 		else
 		{
 			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod));
 
-			cell->type = "$dff";
-			cell->unsetParam("\\SET_POLARITY");
-			cell->unsetParam("\\CLR_POLARITY");
-			cell->unsetPort("\\SET");
-			cell->unsetPort("\\CLR");
+			cell->type = ID($dff);
+			cell->unsetParam(ID(SET_POLARITY));
+			cell->unsetParam(ID(CLR_POLARITY));
+			cell->unsetPort(ID(SET));
+			cell->unsetPort(ID(CLR));
 		}
 
 		return true;
@@ -208,8 +208,8 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 		log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod));
 
 		cell->type = new_type;
-		cell->unsetPort("\\S");
-		cell->unsetPort("\\R");
+		cell->unsetPort(ID(S));
+		cell->unsetPort(ID(R));
 
 		return true;
 	}
@@ -222,18 +222,18 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
 	SigSpec sig_e;
 	State on_state, off_state;
 
-	if (dlatch->type == "$dlatch") {
-		sig_e = assign_map(dlatch->getPort("\\EN"));
-		on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0;
-		off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1;
+	if (dlatch->type == ID($dlatch)) {
+		sig_e = assign_map(dlatch->getPort(ID(EN)));
+		on_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S1 : State::S0;
+		off_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S0 : State::S1;
 	} else
-	if (dlatch->type == "$_DLATCH_P_") {
-		sig_e = assign_map(dlatch->getPort("\\E"));
+	if (dlatch->type == ID($_DLATCH_P_)) {
+		sig_e = assign_map(dlatch->getPort(ID(E)));
 		on_state = State::S1;
 		off_state = State::S0;
 	} else
-	if (dlatch->type == "$_DLATCH_N_") {
-		sig_e = assign_map(dlatch->getPort("\\E"));
+	if (dlatch->type == ID($_DLATCH_N_)) {
+		sig_e = assign_map(dlatch->getPort(ID(E)));
 		on_state = State::S0;
 		off_state = State::S1;
 	} else
@@ -242,15 +242,15 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
 	if (sig_e == off_state)
 	{
 		RTLIL::Const val_init;
-		for (auto bit : dff_init_map(dlatch->getPort("\\Q")))
+		for (auto bit : dff_init_map(dlatch->getPort(ID(Q))))
 			val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx);
-		mod->connect(dlatch->getPort("\\Q"), val_init);
+		mod->connect(dlatch->getPort(ID(Q)), val_init);
 		goto delete_dlatch;
 	}
 
 	if (sig_e == on_state)
 	{
-		mod->connect(dlatch->getPort("\\Q"), dlatch->getPort("\\D"));
+		mod->connect(dlatch->getPort(ID(Q)), dlatch->getPort(ID(D)));
 		goto delete_dlatch;
 	}
 
@@ -258,7 +258,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
 
 delete_dlatch:
 	log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod));
-	remove_init_attr(dlatch->getPort("\\Q"));
+	remove_init_attr(dlatch->getPort(ID(Q)));
 	mod->remove(dlatch);
 	return true;
 }
@@ -268,24 +268,24 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 	RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
 	RTLIL::Const val_cp, val_rp, val_rv, val_ep;
 
-	if (dff->type == "$_FF_") {
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
+	if (dff->type == ID($_FF_)) {
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
 	}
-	else if (dff->type == "$_DFF_N_" || dff->type == "$_DFF_P_") {
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
-		sig_c = dff->getPort("\\C");
-		val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1);
+	else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) {
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
+		sig_c = dff->getPort(ID(C));
+		val_cp = RTLIL::Const(dff->type == ID($_DFF_P_), 1);
 	}
 	else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 &&
 			(dff->type[6] == 'N' || dff->type[6] == 'P') &&
 			(dff->type[7] == 'N' || dff->type[7] == 'P') &&
 			(dff->type[8] == '0' || dff->type[8] == '1')) {
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
-		sig_c = dff->getPort("\\C");
-		sig_r = dff->getPort("\\R");
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
+		sig_c = dff->getPort(ID(C));
+		sig_r = dff->getPort(ID(R));
 		val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
 		val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
 		val_rv = RTLIL::Const(dff->type[8] == '1', 1);
@@ -293,39 +293,39 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 	else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 &&
 			(dff->type[7] == 'N' || dff->type[7] == 'P') &&
 			(dff->type[8] == 'N' || dff->type[8] == 'P')) {
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
-		sig_c = dff->getPort("\\C");
-		sig_e = dff->getPort("\\E");
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
+		sig_c = dff->getPort(ID(C));
+		sig_e = dff->getPort(ID(E));
 		val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
 		val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
 	}
-	else if (dff->type == "$ff") {
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
+	else if (dff->type == ID($ff)) {
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
 	}
-	else if (dff->type == "$dff") {
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
-		sig_c = dff->getPort("\\CLK");
-		val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
+	else if (dff->type == ID($dff)) {
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
+		sig_c = dff->getPort(ID(CLK));
+		val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
 	}
-	else if (dff->type == "$dffe") {
-		sig_e = dff->getPort("\\EN");
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
-		sig_c = dff->getPort("\\CLK");
-		val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
-		val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1);
+	else if (dff->type == ID($dffe)) {
+		sig_e = dff->getPort(ID(EN));
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
+		sig_c = dff->getPort(ID(CLK));
+		val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
+		val_ep = RTLIL::Const(dff->parameters[ID(EN_POLARITY)].as_bool(), 1);
 	}
-	else if (dff->type == "$adff") {
-		sig_d = dff->getPort("\\D");
-		sig_q = dff->getPort("\\Q");
-		sig_c = dff->getPort("\\CLK");
-		sig_r = dff->getPort("\\ARST");
-		val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
-		val_rp = RTLIL::Const(dff->parameters["\\ARST_POLARITY"].as_bool(), 1);
-		val_rv = dff->parameters["\\ARST_VALUE"];
+	else if (dff->type == ID($adff)) {
+		sig_d = dff->getPort(ID(D));
+		sig_q = dff->getPort(ID(Q));
+		sig_c = dff->getPort(ID(CLK));
+		sig_r = dff->getPort(ID(ARST));
+		val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
+		val_rp = RTLIL::Const(dff->parameters[ID(ARST_POLARITY)].as_bool(), 1);
+		val_rv = dff->parameters[ID(ARST_VALUE)];
 	}
 	else
 		log_abort();
@@ -343,12 +343,12 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 		val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
 	}
 
-	if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) {
+	if (dff->type.in(ID($ff), ID($dff)) && mux_drivers.has(sig_d)) {
 		std::set<RTLIL::Cell*> muxes;
 		mux_drivers.find(sig_d, muxes);
 		for (auto mux : muxes) {
-			RTLIL::SigSpec sig_a = assign_map(mux->getPort("\\A"));
-			RTLIL::SigSpec sig_b = assign_map(mux->getPort("\\B"));
+			RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID(A)));
+			RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID(B)));
 			if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) {
 				mod->connect(sig_q, sig_b);
 				goto delete_dff;
@@ -420,17 +420,17 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 
 		log("Removing unused reset from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
 
-		if (dff->type == "$adff") {
-			dff->type = "$dff";
-			dff->unsetPort("\\ARST");
-			dff->unsetParam("\\ARST_POLARITY");
-			dff->unsetParam("\\ARST_VALUE");
+		if (dff->type == ID($adff)) {
+			dff->type = ID($dff);
+			dff->unsetPort(ID(ARST));
+			dff->unsetParam(ID(ARST_POLARITY));
+			dff->unsetParam(ID(ARST_VALUE));
 			return true;
 		}
 
 		log_assert(dff->type.begins_with("$_DFF_"));
 		dff->type = stringf("$_DFF_%c_", + dff->type[6]);
-		dff->unsetPort("\\R");
+		dff->unsetPort(ID(R));
 	}
 
 	// If enable signal is present, and is fully constant
@@ -445,16 +445,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 
 		log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
 
-		if (dff->type == "$dffe") {
-			dff->type = "$dff";
-			dff->unsetPort("\\EN");
-			dff->unsetParam("\\EN_POLARITY");
+		if (dff->type == ID($dffe)) {
+			dff->type = ID($dff);
+			dff->unsetPort(ID(EN));
+			dff->unsetParam(ID(EN_POLARITY));
 			return true;
 		}
 
 		log_assert(dff->type.begins_with("$_DFFE_"));
 		dff->type = stringf("$_DFF_%c_", + dff->type[7]);
-		dff->unsetPort("\\E");
+		dff->unsetPort(ID(E));
 	}
 
 	if (sat && has_init && (!sig_r.size() || val_init == val_rv))
@@ -509,9 +509,9 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 				log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0,
 						position, log_id(dff), log_id(dff->type), log_id(mod));
 
-				SigSpec tmp = dff->getPort("\\D");
+				SigSpec tmp = dff->getPort(ID(D));
 				tmp[position] = sigbit_init_val;
-				dff->setPort("\\D", tmp);
+				dff->setPort(ID(D), tmp);
 
 				removed_sigbits = true;
 			}
@@ -528,7 +528,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 
 delete_dff:
 	log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
-	remove_init_attr(dff->getPort("\\Q"));
+	remove_init_attr(dff->getPort(ID(Q)));
 	mod->remove(dff);
 
 	for (auto &entry : bit2driver)
@@ -588,8 +588,8 @@ struct OptRmdffPass : public Pass {
 
 			for (auto wire : module->wires())
 			{
-				if (wire->attributes.count("\\init") != 0) {
-					Const initval = wire->attributes.at("\\init");
+				if (wire->attributes.count(ID(init)) != 0) {
+					Const initval = wire->attributes.at(ID(init));
 					for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++)
 						if (initval[i] == State::S0 || initval[i] == State::S1)
 							dff_init_map.add(SigBit(wire, i), initval[i]);
@@ -624,29 +624,29 @@ struct OptRmdffPass : public Pass {
 						}
 				}
 
-				if (cell->type.in("$mux", "$pmux")) {
-					if (cell->getPort("\\A").size() == cell->getPort("\\B").size())
-						mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell);
+				if (cell->type.in(ID($mux), ID($pmux))) {
+					if (cell->getPort(ID(A)).size() == cell->getPort(ID(B)).size())
+						mux_drivers.insert(assign_map(cell->getPort(ID(Y))), cell);
 					continue;
 				}
 
 				if (!design->selected(module, cell))
 					continue;
 
-				if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_",
-						"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr",
-						"$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_",
-						"$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr"))
+				if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
+						ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), ID($dffsr),
+						ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
+						ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($dlatchsr)))
 					dffsr_list.push_back(cell->name);
 
-				if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_",
-						"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
-						"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_",
-						"$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_",
-						"$ff", "$dff", "$dffe", "$adff"))
+				if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_),
+						ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
+						ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
+						ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
+						ID($ff), ID($dff), ID($dffe), ID($adff)))
 					dff_list.push_back(cell->name);
 
-				if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_"))
+				if (cell->type.in(ID($dlatch), ID($_DLATCH_P_), ID($_DLATCH_N_)))
 					dlatch_list.push_back(cell->name);
 			}
 
diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc
index 65d8b8f32..3e34bfbbd 100644
--- a/passes/opt/pmux2shiftx.cc
+++ b/passes/opt/pmux2shiftx.cc
@@ -46,7 +46,7 @@ struct OnehotDatabase
 
 		for (auto wire : module->wires())
 		{
-			auto it = wire->attributes.find("\\init");
+			auto it = wire->attributes.find(ID(init));
 			if (it == wire->attributes.end())
 				continue;
 
@@ -63,19 +63,19 @@ struct OnehotDatabase
 			vector<SigSpec> inputs;
 			SigSpec output;
 
-			if (cell->type.in("$adff", "$dff", "$dffe", "$dlatch", "$ff"))
+			if (cell->type.in(ID($adff), ID($dff), ID($dffe), ID($dlatch), ID($ff)))
 			{
-				output = cell->getPort("\\Q");
-				if (cell->type == "$adff")
-					inputs.push_back(cell->getParam("\\ARST_VALUE"));
-				inputs.push_back(cell->getPort("\\D"));
+				output = cell->getPort(ID(Q));
+				if (cell->type == ID($adff))
+					inputs.push_back(cell->getParam(ID(ARST_VALUE)));
+				inputs.push_back(cell->getPort(ID(D)));
 			}
 
-			if (cell->type.in("$mux", "$pmux"))
+			if (cell->type.in(ID($mux), ID($pmux)))
 			{
-				output = cell->getPort("\\Y");
-				inputs.push_back(cell->getPort("\\A"));
-				SigSpec B = cell->getPort("\\B");
+				output = cell->getPort(ID(Y));
+				inputs.push_back(cell->getPort(ID(A)));
+				SigSpec B = cell->getPort(ID(B));
 				for (int i = 0; i < GetSize(B); i += GetSize(output))
 					inputs.push_back(B.extract(i, GetSize(output)));
 			}
@@ -292,23 +292,23 @@ struct Pmux2ShiftxPass : public Pass {
 
 			for (auto cell : module->cells())
 			{
-				if (cell->type == "$eq")
+				if (cell->type == ID($eq))
 				{
 					dict<SigBit, State> bits;
 
-					SigSpec A = sigmap(cell->getPort("\\A"));
-					SigSpec B = sigmap(cell->getPort("\\B"));
+					SigSpec A = sigmap(cell->getPort(ID(A)));
+					SigSpec B = sigmap(cell->getPort(ID(B)));
 
-					int a_width = cell->getParam("\\A_WIDTH").as_int();
-					int b_width = cell->getParam("\\B_WIDTH").as_int();
+					int a_width = cell->getParam(ID(A_WIDTH)).as_int();
+					int b_width = cell->getParam(ID(B_WIDTH)).as_int();
 
 					if (a_width < b_width) {
-						bool a_signed = cell->getParam("\\A_SIGNED").as_int();
+						bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
 						A.extend_u0(b_width, a_signed);
 					}
 
 					if (b_width < a_width) {
-						bool b_signed = cell->getParam("\\B_SIGNED").as_int();
+						bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
 						B.extend_u0(a_width, b_signed);
 					}
 
@@ -335,15 +335,15 @@ struct Pmux2ShiftxPass : public Pass {
 						entry.second.bits.push_back(it.second);
 					}
 
-					eqdb[sigmap(cell->getPort("\\Y")[0])] = entry;
+					eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry;
 					goto next_cell;
 				}
 
-				if (cell->type == "$logic_not")
+				if (cell->type == ID($logic_not))
 				{
 					dict<SigBit, State> bits;
 
-					SigSpec A = sigmap(cell->getPort("\\A"));
+					SigSpec A = sigmap(cell->getPort(ID(A)));
 
 					for (int i = 0; i < GetSize(A); i++)
 						bits[A[i]] = State::S0;
@@ -356,7 +356,7 @@ struct Pmux2ShiftxPass : public Pass {
 						entry.second.bits.push_back(it.second);
 					}
 
-					eqdb[sigmap(cell->getPort("\\Y")[0])] = entry;
+					eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry;
 					goto next_cell;
 				}
 		next_cell:;
@@ -364,11 +364,11 @@ struct Pmux2ShiftxPass : public Pass {
 
 			for (auto cell : module->selected_cells())
 			{
-				if (cell->type != "$pmux")
+				if (cell->type != ID($pmux))
 					continue;
 
 				string src = cell->get_src_attribute();
-				int width = cell->getParam("\\WIDTH").as_int();
+				int width = cell->getParam(ID(WIDTH)).as_int();
 				int width_bits = ceil_log2(width);
 				int extwidth = width;
 
@@ -377,9 +377,9 @@ struct Pmux2ShiftxPass : public Pass {
 
 				dict<SigSpec, pool<int>> seldb;
 
-				SigSpec A = cell->getPort("\\A");
-				SigSpec B = cell->getPort("\\B");
-				SigSpec S = sigmap(cell->getPort("\\S"));
+				SigSpec A = cell->getPort(ID(A));
+				SigSpec B = cell->getPort(ID(B));
+				SigSpec S = sigmap(cell->getPort(ID(S)));
 				for (int i = 0; i < GetSize(S); i++)
 				{
 					if (!eqdb.count(S[i]))
@@ -400,8 +400,8 @@ struct Pmux2ShiftxPass : public Pass {
 					log("  data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits);
 				}
 
-				SigSpec updated_S = cell->getPort("\\S");
-				SigSpec updated_B = cell->getPort("\\B");
+				SigSpec updated_S = cell->getPort(ID(S));
+				SigSpec updated_B = cell->getPort(ID(B));
 
 				while (!seldb.empty())
 				{
@@ -727,9 +727,9 @@ struct Pmux2ShiftxPass : public Pass {
 				}
 
 				// update $pmux cell
-				cell->setPort("\\S", updated_S);
-				cell->setPort("\\B", updated_B);
-				cell->setParam("\\S_WIDTH", GetSize(updated_S));
+				cell->setPort(ID(S), updated_S);
+				cell->setPort(ID(B), updated_B);
+				cell->setParam(ID(S_WIDTH), GetSize(updated_S));
 			}
 		}
 	}
@@ -779,22 +779,22 @@ struct OnehotPass : public Pass {
 
 			for (auto cell : module->selected_cells())
 			{
-				if (cell->type != "$eq")
+				if (cell->type != ID($eq))
 					continue;
 
-				SigSpec A = sigmap(cell->getPort("\\A"));
-				SigSpec B = sigmap(cell->getPort("\\B"));
+				SigSpec A = sigmap(cell->getPort(ID(A)));
+				SigSpec B = sigmap(cell->getPort(ID(B)));
 
-				int a_width = cell->getParam("\\A_WIDTH").as_int();
-				int b_width = cell->getParam("\\B_WIDTH").as_int();
+				int a_width = cell->getParam(ID(A_WIDTH)).as_int();
+				int b_width = cell->getParam(ID(B_WIDTH)).as_int();
 
 				if (a_width < b_width) {
-					bool a_signed = cell->getParam("\\A_SIGNED").as_int();
+					bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
 					A.extend_u0(b_width, a_signed);
 				}
 
 				if (b_width < a_width) {
-					bool b_signed = cell->getParam("\\B_SIGNED").as_int();
+					bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
 					B.extend_u0(a_width, b_signed);
 				}
 
@@ -830,7 +830,7 @@ struct OnehotPass : public Pass {
 					continue;
 				}
 
-				SigSpec Y = cell->getPort("\\Y");
+				SigSpec Y = cell->getPort(ID(Y));
 
 				if (not_onehot)
 				{
diff --git a/passes/opt/share.cc b/passes/opt/share.cc
index 7f66f749f..84290bb97 100644
--- a/passes/opt/share.cc
+++ b/passes/opt/share.cc
@@ -89,8 +89,8 @@ struct ShareWorker
 			queue_bits.clear();
 
 			for (auto &pbit : portbits) {
-				if (pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") {
-					pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort("\\S")).to_sigbit_pool();
+				if (pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) {
+					pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort(ID(S))).to_sigbit_pool();
 					terminal_bits.insert(bits.begin(), bits.end());
 					queue_bits.insert(bits.begin(), bits.end());
 					visited_cells.insert(pbit.cell);
@@ -128,7 +128,7 @@ struct ShareWorker
 	static int bits_macc(RTLIL::Cell *c)
 	{
 		Macc m(c);
-		int width = GetSize(c->getPort("\\Y"));
+		int width = GetSize(c->getPort(ID(Y)));
 		return bits_macc(m, width);
 	}
 
@@ -242,7 +242,7 @@ struct ShareWorker
 	{
 		Macc m1(c1), m2(c2), supermacc;
 
-		int w1 = GetSize(c1->getPort("\\Y")), w2 = GetSize(c2->getPort("\\Y"));
+		int w1 = GetSize(c1->getPort(ID(Y))), w2 = GetSize(c2->getPort(ID(Y)));
 		int width = max(w1, w2);
 
 		m1.optimize(w1);
@@ -328,11 +328,11 @@ struct ShareWorker
 		{
 			RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width);
 
-			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort("\\Y")));
-			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort("\\Y")));
+			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID(Y))));
+			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID(Y))));
 
-			supercell->setParam("\\Y_WIDTH", width);
-			supercell->setPort("\\Y", sig_y);
+			supercell->setParam(ID(Y_WIDTH), width);
+			supercell->setPort(ID(Y), sig_y);
 
 			supermacc.optimize(width);
 			supermacc.to_cell(supercell);
@@ -368,22 +368,22 @@ struct ShareWorker
 				continue;
 			}
 
-			if (cell->type == "$memrd") {
-				if (cell->parameters.at("\\CLK_ENABLE").as_bool())
+			if (cell->type == ID($memrd)) {
+				if (cell->parameters.at(ID(CLK_ENABLE)).as_bool())
 					continue;
-				if (config.opt_aggressive || !modwalker.sigmap(cell->getPort("\\ADDR")).is_fully_const())
+				if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID(ADDR))).is_fully_const())
 					shareable_cells.insert(cell);
 				continue;
 			}
 
-			if (cell->type.in("$mul", "$div", "$mod")) {
-				if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 4)
+			if (cell->type.in(ID($mul), ID($div), ID($mod))) {
+				if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 4)
 					shareable_cells.insert(cell);
 				continue;
 			}
 
-			if (cell->type.in("$shl", "$shr", "$sshl", "$sshr")) {
-				if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 8)
+			if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
+				if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 8)
 					shareable_cells.insert(cell);
 				continue;
 			}
@@ -401,9 +401,9 @@ struct ShareWorker
 		if (c1->type != c2->type)
 			return false;
 
-		if (c1->type == "$memrd")
+		if (c1->type == ID($memrd))
 		{
-			if (c1->parameters.at("\\MEMID").decode_string() != c2->parameters.at("\\MEMID").decode_string())
+			if (c1->parameters.at(ID(MEMID)).decode_string() != c2->parameters.at(ID(MEMID)).decode_string())
 				return false;
 
 			return true;
@@ -413,11 +413,11 @@ struct ShareWorker
 		{
 			if (!config.opt_aggressive)
 			{
-				int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
-				int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
+				int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
+				int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
 
-				int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
-				int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
+				int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
+				int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
 
 				if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
 				if (max(y1_width, y2_width) > 2 * min(y1_width, y2_width)) return false;
@@ -426,17 +426,17 @@ struct ShareWorker
 			return true;
 		}
 
-		if (config.generic_bin_ops.count(c1->type) || c1->type == "$alu")
+		if (config.generic_bin_ops.count(c1->type) || c1->type == ID($alu))
 		{
 			if (!config.opt_aggressive)
 			{
-				int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
-				int b1_width = c1->parameters.at("\\B_WIDTH").as_int();
-				int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
+				int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
+				int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
+				int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
 
-				int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
-				int b2_width = c2->parameters.at("\\B_WIDTH").as_int();
-				int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
+				int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
+				int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
+				int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
 
 				if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
 				if (max(b1_width, b2_width) > 2 * min(b1_width, b2_width)) return false;
@@ -450,13 +450,13 @@ struct ShareWorker
 		{
 			if (!config.opt_aggressive)
 			{
-				int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
-				int b1_width = c1->parameters.at("\\B_WIDTH").as_int();
-				int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
+				int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
+				int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
+				int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
 
-				int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
-				int b2_width = c2->parameters.at("\\B_WIDTH").as_int();
-				int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
+				int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
+				int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
+				int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
 
 				int min1_width = min(a1_width, b1_width);
 				int max1_width = max(a1_width, b1_width);
@@ -472,7 +472,7 @@ struct ShareWorker
 			return true;
 		}
 
-		if (c1->type == "$macc")
+		if (c1->type == ID($macc))
 		{
 			if (!config.opt_aggressive)
 				if (share_macc(c1, c2) > 2 * min(bits_macc(c1), bits_macc(c2))) return false;
@@ -510,27 +510,27 @@ struct ShareWorker
 
 		if (config.generic_uni_ops.count(c1->type))
 		{
-			if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool())
+			if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
 			{
-				RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1;
-				if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) {
-					unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1;
-					RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A");
+				RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
+				if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) {
+					unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
+					RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A));
 					new_a.append_bit(RTLIL::State::S0);
-					unsigned_cell->setPort("\\A", new_a);
+					unsigned_cell->setPort(ID(A), new_a);
 				}
-				unsigned_cell->parameters.at("\\A_SIGNED") = true;
+				unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
 				unsigned_cell->check();
 			}
 
-			bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool();
-			log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool());
+			bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
+			log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
 
-			RTLIL::SigSpec a1 = c1->getPort("\\A");
-			RTLIL::SigSpec y1 = c1->getPort("\\Y");
+			RTLIL::SigSpec a1 = c1->getPort(ID(A));
+			RTLIL::SigSpec y1 = c1->getPort(ID(Y));
 
-			RTLIL::SigSpec a2 = c2->getPort("\\A");
-			RTLIL::SigSpec y2 = c2->getPort("\\Y");
+			RTLIL::SigSpec a2 = c2->getPort(ID(A));
+			RTLIL::SigSpec y2 = c2->getPort(ID(Y));
 
 			int a_width = max(a1.size(), a2.size());
 			int y_width = max(y1.size(), y2.size());
@@ -544,11 +544,11 @@ struct ShareWorker
 			RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
 
 			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
-			supercell->parameters["\\A_SIGNED"] = a_signed;
-			supercell->parameters["\\A_WIDTH"] = a_width;
-			supercell->parameters["\\Y_WIDTH"] = y_width;
-			supercell->setPort("\\A", a);
-			supercell->setPort("\\Y", y);
+			supercell->parameters[ID(A_SIGNED)] = a_signed;
+			supercell->parameters[ID(A_WIDTH)] = a_width;
+			supercell->parameters[ID(Y_WIDTH)] = y_width;
+			supercell->setPort(ID(A), a);
+			supercell->setPort(ID(Y), y);
 
 			supercell_aux.insert(module->addPos(NEW_ID, y, y1));
 			supercell_aux.insert(module->addPos(NEW_ID, y, y2));
@@ -557,54 +557,54 @@ struct ShareWorker
 			return supercell;
 		}
 
-		if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == "$alu")
+		if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == ID($alu))
 		{
 			bool modified_src_cells = false;
 
 			if (config.generic_cbin_ops.count(c1->type))
 			{
-				int score_unflipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int()) +
-						max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int());
+				int score_unflipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()) +
+						max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int());
 
-				int score_flipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int()) +
-						max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int());
+				int score_flipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()) +
+						max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int());
 
 				if (score_flipped < score_unflipped)
 				{
-					RTLIL::SigSpec tmp = c2->getPort("\\A");
-					c2->setPort("\\A", c2->getPort("\\B"));
-					c2->setPort("\\B", tmp);
+					RTLIL::SigSpec tmp = c2->getPort(ID(A));
+					c2->setPort(ID(A), c2->getPort(ID(B)));
+					c2->setPort(ID(B), tmp);
 
-					std::swap(c2->parameters.at("\\A_WIDTH"), c2->parameters.at("\\B_WIDTH"));
-					std::swap(c2->parameters.at("\\A_SIGNED"), c2->parameters.at("\\B_SIGNED"));
+					std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH)));
+					std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED)));
 					modified_src_cells = true;
 				}
 			}
 
-			if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool())
+			if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
 
 			{
-				RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1;
-				if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) {
-					unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1;
-					RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A");
+				RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
+				if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) {
+					unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
+					RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A));
 					new_a.append_bit(RTLIL::State::S0);
-					unsigned_cell->setPort("\\A", new_a);
+					unsigned_cell->setPort(ID(A), new_a);
 				}
-				unsigned_cell->parameters.at("\\A_SIGNED") = true;
+				unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
 				modified_src_cells = true;
 			}
 
-			if (c1->parameters.at("\\B_SIGNED").as_bool() != c2->parameters.at("\\B_SIGNED").as_bool())
+			if (c1->parameters.at(ID(B_SIGNED)).as_bool() != c2->parameters.at(ID(B_SIGNED)).as_bool())
 			{
-				RTLIL::Cell *unsigned_cell = c1->parameters.at("\\B_SIGNED").as_bool() ? c2 : c1;
-				if (unsigned_cell->getPort("\\B").to_sigbit_vector().back() != RTLIL::State::S0) {
-					unsigned_cell->parameters.at("\\B_WIDTH") = unsigned_cell->parameters.at("\\B_WIDTH").as_int() + 1;
-					RTLIL::SigSpec new_b = unsigned_cell->getPort("\\B");
+				RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1;
+				if (unsigned_cell->getPort(ID(B)).to_sigbit_vector().back() != RTLIL::State::S0) {
+					unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1;
+					RTLIL::SigSpec new_b = unsigned_cell->getPort(ID(B));
 					new_b.append_bit(RTLIL::State::S0);
-					unsigned_cell->setPort("\\B", new_b);
+					unsigned_cell->setPort(ID(B), new_b);
 				}
-				unsigned_cell->parameters.at("\\B_SIGNED") = true;
+				unsigned_cell->parameters.at(ID(B_SIGNED)) = true;
 				modified_src_cells = true;
 			}
 
@@ -613,28 +613,28 @@ struct ShareWorker
 				c2->check();
 			}
 
-			bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool();
-			bool b_signed = c1->parameters.at("\\B_SIGNED").as_bool();
+			bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
+			bool b_signed = c1->parameters.at(ID(B_SIGNED)).as_bool();
 
-			log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool());
-			log_assert(b_signed == c2->parameters.at("\\B_SIGNED").as_bool());
+			log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
+			log_assert(b_signed == c2->parameters.at(ID(B_SIGNED)).as_bool());
 
-			if (c1->type == "$shl" || c1->type == "$shr" || c1->type == "$sshl" || c1->type == "$sshr")
+			if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr))
 				b_signed = false;
 
-			RTLIL::SigSpec a1 = c1->getPort("\\A");
-			RTLIL::SigSpec b1 = c1->getPort("\\B");
-			RTLIL::SigSpec y1 = c1->getPort("\\Y");
+			RTLIL::SigSpec a1 = c1->getPort(ID(A));
+			RTLIL::SigSpec b1 = c1->getPort(ID(B));
+			RTLIL::SigSpec y1 = c1->getPort(ID(Y));
 
-			RTLIL::SigSpec a2 = c2->getPort("\\A");
-			RTLIL::SigSpec b2 = c2->getPort("\\B");
-			RTLIL::SigSpec y2 = c2->getPort("\\Y");
+			RTLIL::SigSpec a2 = c2->getPort(ID(A));
+			RTLIL::SigSpec b2 = c2->getPort(ID(B));
+			RTLIL::SigSpec y2 = c2->getPort(ID(Y));
 
 			int a_width = max(a1.size(), a2.size());
 			int b_width = max(b1.size(), b2.size());
 			int y_width = max(y1.size(), y2.size());
 
-			if (c1->type == "$shr" && a_signed)
+			if (c1->type == ID($shr) && a_signed)
 			{
 				a_width = max(y_width, a_width);
 
@@ -660,43 +660,43 @@ struct ShareWorker
 			supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b));
 
 			RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
-			RTLIL::Wire *x = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr;
-			RTLIL::Wire *co = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr;
+			RTLIL::Wire *x = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
+			RTLIL::Wire *co = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
 
 			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
-			supercell->parameters["\\A_SIGNED"] = a_signed;
-			supercell->parameters["\\B_SIGNED"] = b_signed;
-			supercell->parameters["\\A_WIDTH"] = a_width;
-			supercell->parameters["\\B_WIDTH"] = b_width;
-			supercell->parameters["\\Y_WIDTH"] = y_width;
-			supercell->setPort("\\A", a);
-			supercell->setPort("\\B", b);
-			supercell->setPort("\\Y", y);
-			if (c1->type == "$alu") {
+			supercell->parameters[ID(A_SIGNED)] = a_signed;
+			supercell->parameters[ID(B_SIGNED)] = b_signed;
+			supercell->parameters[ID(A_WIDTH)] = a_width;
+			supercell->parameters[ID(B_WIDTH)] = b_width;
+			supercell->parameters[ID(Y_WIDTH)] = y_width;
+			supercell->setPort(ID(A), a);
+			supercell->setPort(ID(B), b);
+			supercell->setPort(ID(Y), y);
+			if (c1->type == ID($alu)) {
 				RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID);
-				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\CI"), c1->getPort("\\CI"), act, ci));
-				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\BI"), c1->getPort("\\BI"), act, bi));
-				supercell->setPort("\\CI", ci);
-				supercell->setPort("\\BI", bi);
-				supercell->setPort("\\CO", co);
-				supercell->setPort("\\X", x);
+				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci));
+				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(BI)), c1->getPort(ID(BI)), act, bi));
+				supercell->setPort(ID(CI), ci);
+				supercell->setPort(ID(BI), bi);
+				supercell->setPort(ID(CO), co);
+				supercell->setPort(ID(X), x);
 			}
 			supercell->check();
 
 			supercell_aux.insert(module->addPos(NEW_ID, y, y1));
 			supercell_aux.insert(module->addPos(NEW_ID, y, y2));
-			if (c1->type == "$alu") {
-				supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort("\\CO")));
-				supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort("\\CO")));
-				supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort("\\X")));
-				supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort("\\X")));
+			if (c1->type == ID($alu)) {
+				supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort(ID(CO))));
+				supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort(ID(CO))));
+				supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort(ID(X))));
+				supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort(ID(X))));
 			}
 
 			supercell_aux.insert(supercell);
 			return supercell;
 		}
 
-		if (c1->type == "$macc")
+		if (c1->type == ID($macc))
 		{
 			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 			supercell_aux.insert(supercell);
@@ -705,18 +705,18 @@ struct ShareWorker
 			return supercell;
 		}
 
-		if (c1->type == "$memrd")
+		if (c1->type == ID($memrd))
 		{
 			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
-			RTLIL::SigSpec addr1 = c1->getPort("\\ADDR");
-			RTLIL::SigSpec addr2 = c2->getPort("\\ADDR");
+			RTLIL::SigSpec addr1 = c1->getPort(ID(ADDR));
+			RTLIL::SigSpec addr2 = c2->getPort(ID(ADDR));
 			if (GetSize(addr1) < GetSize(addr2))
 				addr1.extend_u0(GetSize(addr2));
 			else
 				addr2.extend_u0(GetSize(addr1));
-			supercell->setPort("\\ADDR", addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
-			supercell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr1));
-			supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA")));
+			supercell->setPort(ID(ADDR), addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
+			supercell->parameters[ID(ABITS)] = RTLIL::Const(GetSize(addr1));
+			supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort(ID(DATA)), c2->getPort(ID(DATA))));
 			supercell_aux.insert(supercell);
 			return supercell;
 		}
@@ -747,8 +747,8 @@ struct ShareWorker
 		modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]);
 
 		for (auto &bit : pbits) {
-			if ((bit.cell->type == "$mux" || bit.cell->type == "$pmux") && bit.port == "\\S")
-				forbidden_controls_cache[cell].insert(bit.cell->getPort("\\S").extract(bit.offset, 1));
+			if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == ID(S))
+				forbidden_controls_cache[cell].insert(bit.cell->getPort(ID(S)).extract(bit.offset, 1));
 			consumer_cells.insert(bit.cell);
 		}
 
@@ -874,7 +874,7 @@ struct ShareWorker
 			}
 			for (auto &pbit : modwalker.signal_consumers[bit]) {
 				log_assert(fwd_ct.cell_known(pbit.cell->type));
-				if ((pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") && (pbit.port == "\\A" || pbit.port == "\\B"))
+				if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID(A) || pbit.port == ID(B)))
 					driven_data_muxes.insert(pbit.cell);
 				else
 					driven_cells.insert(pbit.cell);
@@ -890,10 +890,10 @@ struct ShareWorker
 			bool used_in_a = false;
 			std::set<int> used_in_b_parts;
 
-			int width = c->parameters.at("\\WIDTH").as_int();
-			std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort("\\A"));
-			std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort("\\B"));
-			std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort("\\S"));
+			int width = c->parameters.at(ID(WIDTH)).as_int();
+			std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort(ID(A)));
+			std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort(ID(B)));
+			std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort(ID(S)));
 
 			for (auto &bit : sig_a)
 				if (cell_out_bits.count(bit))
@@ -1132,14 +1132,14 @@ struct ShareWorker
 		fwd_ct.setup_internals();
 
 		cone_ct.setup_internals();
-		cone_ct.cell_types.erase("$mul");
-		cone_ct.cell_types.erase("$mod");
-		cone_ct.cell_types.erase("$div");
-		cone_ct.cell_types.erase("$pow");
-		cone_ct.cell_types.erase("$shl");
-		cone_ct.cell_types.erase("$shr");
-		cone_ct.cell_types.erase("$sshl");
-		cone_ct.cell_types.erase("$sshr");
+		cone_ct.cell_types.erase(ID($mul));
+		cone_ct.cell_types.erase(ID($mod));
+		cone_ct.cell_types.erase(ID($div));
+		cone_ct.cell_types.erase(ID($pow));
+		cone_ct.cell_types.erase(ID($shl));
+		cone_ct.cell_types.erase(ID($shr));
+		cone_ct.cell_types.erase(ID($sshl));
+		cone_ct.cell_types.erase(ID($sshr));
 
 		modwalker.setup(design, module);
 
@@ -1153,9 +1153,9 @@ struct ShareWorker
 				GetSize(shareable_cells), log_id(module));
 
 		for (auto cell : module->cells())
-			if (cell->type == "$pmux")
-				for (auto bit : cell->getPort("\\S"))
-				for (auto other_bit : cell->getPort("\\S"))
+			if (cell->type == ID($pmux))
+				for (auto bit : cell->getPort(ID(S)))
+				for (auto other_bit : cell->getPort(ID(S)))
 					if (bit < other_bit)
 						exclusive_ctrls.push_back(std::pair<RTLIL::SigBit, RTLIL::SigBit>(bit, other_bit));
 
@@ -1466,43 +1466,43 @@ struct SharePass : public Pass {
 		config.opt_aggressive = false;
 		config.opt_fast = false;
 
-		config.generic_uni_ops.insert("$not");
-		// config.generic_uni_ops.insert("$pos");
-		config.generic_uni_ops.insert("$neg");
+		config.generic_uni_ops.insert(ID($not));
+		// config.generic_uni_ops.insert(ID($pos));
+		config.generic_uni_ops.insert(ID($neg));
 
-		config.generic_cbin_ops.insert("$and");
-		config.generic_cbin_ops.insert("$or");
-		config.generic_cbin_ops.insert("$xor");
-		config.generic_cbin_ops.insert("$xnor");
+		config.generic_cbin_ops.insert(ID($and));
+		config.generic_cbin_ops.insert(ID($or));
+		config.generic_cbin_ops.insert(ID($xor));
+		config.generic_cbin_ops.insert(ID($xnor));
 
-		config.generic_bin_ops.insert("$shl");
-		config.generic_bin_ops.insert("$shr");
-		config.generic_bin_ops.insert("$sshl");
-		config.generic_bin_ops.insert("$sshr");
+		config.generic_bin_ops.insert(ID($shl));
+		config.generic_bin_ops.insert(ID($shr));
+		config.generic_bin_ops.insert(ID($sshl));
+		config.generic_bin_ops.insert(ID($sshr));
 
-		config.generic_bin_ops.insert("$lt");
-		config.generic_bin_ops.insert("$le");
-		config.generic_bin_ops.insert("$eq");
-		config.generic_bin_ops.insert("$ne");
-		config.generic_bin_ops.insert("$eqx");
-		config.generic_bin_ops.insert("$nex");
-		config.generic_bin_ops.insert("$ge");
-		config.generic_bin_ops.insert("$gt");
+		config.generic_bin_ops.insert(ID($lt));
+		config.generic_bin_ops.insert(ID($le));
+		config.generic_bin_ops.insert(ID($eq));
+		config.generic_bin_ops.insert(ID($ne));
+		config.generic_bin_ops.insert(ID($eqx));
+		config.generic_bin_ops.insert(ID($nex));
+		config.generic_bin_ops.insert(ID($ge));
+		config.generic_bin_ops.insert(ID($gt));
 
-		config.generic_cbin_ops.insert("$add");
-		config.generic_cbin_ops.insert("$mul");
+		config.generic_cbin_ops.insert(ID($add));
+		config.generic_cbin_ops.insert(ID($mul));
 
-		config.generic_bin_ops.insert("$sub");
-		config.generic_bin_ops.insert("$div");
-		config.generic_bin_ops.insert("$mod");
-		// config.generic_bin_ops.insert("$pow");
+		config.generic_bin_ops.insert(ID($sub));
+		config.generic_bin_ops.insert(ID($div));
+		config.generic_bin_ops.insert(ID($mod));
+		// config.generic_bin_ops.insert(ID($pow));
 
-		config.generic_uni_ops.insert("$logic_not");
-		config.generic_cbin_ops.insert("$logic_and");
-		config.generic_cbin_ops.insert("$logic_or");
+		config.generic_uni_ops.insert(ID($logic_not));
+		config.generic_cbin_ops.insert(ID($logic_and));
+		config.generic_cbin_ops.insert(ID($logic_or));
 
-		config.generic_other_ops.insert("$alu");
-		config.generic_other_ops.insert("$macc");
+		config.generic_other_ops.insert(ID($alu));
+		config.generic_other_ops.insert(ID($macc));
 
 		log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n");
 
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index 1eeca2748..ca0be54d2 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -34,13 +34,13 @@ struct WreduceConfig
 	WreduceConfig()
 	{
 		supported_cell_types = pool<IdString>({
-			"$not", "$pos", "$neg",
-			"$and", "$or", "$xor", "$xnor",
-			"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
-			"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
-			"$add", "$sub", "$mul", // "$div", "$mod", "$pow",
-			"$mux", "$pmux",
-			"$dff", "$adff"
+			ID($not), ID($pos), ID($neg),
+			ID($and), ID($or), ID($xor), ID($xnor),
+			ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
+			ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
+			ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($pow),
+			ID($mux), ID($pmux),
+			ID($dff), ID($adff)
 		});
 	}
 };
@@ -64,10 +64,10 @@ struct WreduceWorker
 	{
 		// Reduce size of MUX if inputs agree on a value for a bit or a output bit is unused
 
-		SigSpec sig_a = mi.sigmap(cell->getPort("\\A"));
-		SigSpec sig_b = mi.sigmap(cell->getPort("\\B"));
-		SigSpec sig_s = mi.sigmap(cell->getPort("\\S"));
-		SigSpec sig_y = mi.sigmap(cell->getPort("\\Y"));
+		SigSpec sig_a = mi.sigmap(cell->getPort(ID(A)));
+		SigSpec sig_b = mi.sigmap(cell->getPort(ID(B)));
+		SigSpec sig_s = mi.sigmap(cell->getPort(ID(S)));
+		SigSpec sig_y = mi.sigmap(cell->getPort(ID(Y)));
 		std::vector<SigBit> bits_removed;
 
 		if (sig_y.has_const())
@@ -130,9 +130,9 @@ struct WreduceWorker
 		for (auto bit : new_work_queue_bits)
 			work_queue_bits.insert(bit);
 
-		cell->setPort("\\A", new_sig_a);
-		cell->setPort("\\B", new_sig_b);
-		cell->setPort("\\Y", new_sig_y);
+		cell->setPort(ID(A), new_sig_a);
+		cell->setPort(ID(B), new_sig_b);
+		cell->setPort(ID(Y), new_sig_y);
 		cell->fixup_parameters();
 
 		module->connect(sig_y.extract(n_kept, n_removed), sig_removed);
@@ -142,8 +142,8 @@ struct WreduceWorker
 	{
 		// Reduce size of FF if inputs are just sign/zero extended or output bit is not used
 
-		SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
-		SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
+		SigSpec sig_d = mi.sigmap(cell->getPort(ID(D)));
+		SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q)));
 		Const initval;
 
 		int width_before = GetSize(sig_q);
@@ -214,14 +214,14 @@ struct WreduceWorker
 			work_queue_bits.insert(bit);
 
 		// Narrow ARST_VALUE parameter to new size.
-		if (cell->parameters.count("\\ARST_VALUE")) {
-			Const arst_value = cell->getParam("\\ARST_VALUE");
+		if (cell->parameters.count(ID(ARST_VALUE))) {
+			Const arst_value = cell->getParam(ID(ARST_VALUE));
 			arst_value.bits.resize(GetSize(sig_q));
-			cell->setParam("\\ARST_VALUE", arst_value);
+			cell->setParam(ID(ARST_VALUE), arst_value);
 		}
 
-		cell->setPort("\\D", sig_d);
-		cell->setPort("\\Q", sig_q);
+		cell->setPort(ID(D), sig_d);
+		cell->setPort(ID(Q), sig_q);
 		cell->fixup_parameters();
 	}
 
@@ -230,7 +230,7 @@ struct WreduceWorker
 		port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool();
 		SigSpec sig = mi.sigmap(cell->getPort(stringf("\\%c", port)));
 
-		if (port == 'B' && cell->type.in("$shl", "$shr", "$sshl", "$sshr"))
+		if (port == 'B' && cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr)))
 			port_signed = false;
 
 		int bits_removed = 0;
@@ -264,13 +264,13 @@ struct WreduceWorker
 		if (!cell->type.in(config->supported_cell_types))
 			return;
 
-		if (cell->type.in("$mux", "$pmux"))
+		if (cell->type.in(ID($mux), ID($pmux)))
 			return run_cell_mux(cell);
 
-		if (cell->type.in("$dff", "$adff"))
+		if (cell->type.in(ID($dff), ID($adff)))
 			return run_cell_dff(cell);
 
-		SigSpec sig = mi.sigmap(cell->getPort("\\Y"));
+		SigSpec sig = mi.sigmap(cell->getPort(ID(Y)));
 
 		if (sig.has_const())
 			return;
@@ -278,10 +278,10 @@ struct WreduceWorker
 
 		// Reduce size of ports A and B based on constant input bits and size of output port
 
-		int max_port_a_size = cell->hasPort("\\A") ? GetSize(cell->getPort("\\A")) : -1;
-		int max_port_b_size = cell->hasPort("\\B") ? GetSize(cell->getPort("\\B")) : -1;
+		int max_port_a_size = cell->hasPort(ID(A)) ? GetSize(cell->getPort(ID(A))) : -1;
+		int max_port_b_size = cell->hasPort(ID(B)) ? GetSize(cell->getPort(ID(B))) : -1;
 
-		if (cell->type.in("$not", "$pos", "$neg", "$and", "$or", "$xor", "$add", "$sub")) {
+		if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) {
 			max_port_a_size = min(max_port_a_size, GetSize(sig));
 			max_port_b_size = min(max_port_b_size, GetSize(sig));
 		}
@@ -289,32 +289,32 @@ struct WreduceWorker
 		bool port_a_signed = false;
 		bool port_b_signed = false;
 
-		if (max_port_a_size >= 0 && cell->type != "$shiftx")
+		if (max_port_a_size >= 0 && cell->type != ID($shiftx))
 			run_reduce_inport(cell, 'A', max_port_a_size, port_a_signed, did_something);
 
 		if (max_port_b_size >= 0)
 			run_reduce_inport(cell, 'B', max_port_b_size, port_b_signed, did_something);
 
-		if (cell->hasPort("\\A") && cell->hasPort("\\B") && port_a_signed && port_b_signed) {
-			SigSpec sig_a = mi.sigmap(cell->getPort("\\A")), sig_b = mi.sigmap(cell->getPort("\\B"));
+		if (cell->hasPort(ID(A)) && cell->hasPort(ID(B)) && port_a_signed && port_b_signed) {
+			SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))), sig_b = mi.sigmap(cell->getPort(ID(B)));
 			if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 &&
 					GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) {
 				log("Converting cell %s.%s (%s) from signed to unsigned.\n",
 						log_id(module), log_id(cell), log_id(cell->type));
-				cell->setParam("\\A_SIGNED", 0);
-				cell->setParam("\\B_SIGNED", 0);
+				cell->setParam(ID(A_SIGNED), 0);
+				cell->setParam(ID(B_SIGNED), 0);
 				port_a_signed = false;
 				port_b_signed = false;
 				did_something = true;
 			}
 		}
 
-		if (cell->hasPort("\\A") && !cell->hasPort("\\B") && port_a_signed) {
-			SigSpec sig_a = mi.sigmap(cell->getPort("\\A"));
+		if (cell->hasPort(ID(A)) && !cell->hasPort(ID(B)) && port_a_signed) {
+			SigSpec sig_a = mi.sigmap(cell->getPort(ID(A)));
 			if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) {
 				log("Converting cell %s.%s (%s) from signed to unsigned.\n",
 						log_id(module), log_id(cell), log_id(cell->type));
-				cell->setParam("\\A_SIGNED", 0);
+				cell->setParam(ID(A_SIGNED), 0);
 				port_a_signed = false;
 				did_something = true;
 			}
@@ -324,7 +324,7 @@ struct WreduceWorker
 		// Reduce size of port Y based on sizes for A and B and unused bits in Y
 
 		int bits_removed = 0;
-		if (port_a_signed && cell->type == "$shr") {
+		if (port_a_signed && cell->type == ID($shr)) {
 			// do not reduce size of output on $shr cells with signed A inputs
 		} else {
 			while (GetSize(sig) > 0)
@@ -342,20 +342,20 @@ struct WreduceWorker
 			}
 		}
 
-		if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub"))
+		if (cell->type.in(ID($pos), ID($add), ID($mul), ID($and), ID($or), ID($xor), ID($sub)))
 		{
-			bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$sub";
+			bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub);
 
 			int a_size = 0, b_size = 0;
-			if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A"));
-			if (cell->hasPort("\\B")) b_size = GetSize(cell->getPort("\\B"));
+			if (cell->hasPort(ID(A))) a_size = GetSize(cell->getPort(ID(A)));
+			if (cell->hasPort(ID(B))) b_size = GetSize(cell->getPort(ID(B)));
 
 			int max_y_size = max(a_size, b_size);
 
-			if (cell->type.in("$add", "$sub"))
+			if (cell->type.in(ID($add), ID($sub)))
 				max_y_size++;
 
-			if (cell->type == "$mul")
+			if (cell->type == ID($mul))
 				max_y_size = a_size + b_size;
 
 			while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) {
@@ -374,7 +374,7 @@ struct WreduceWorker
 		if (bits_removed) {
 			log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n",
 					bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type));
-			cell->setPort("\\Y", sig);
+			cell->setPort(ID(Y), sig);
 			did_something = true;
 		}
 
@@ -387,8 +387,8 @@ struct WreduceWorker
 	static int count_nontrivial_wire_attrs(RTLIL::Wire *w)
 	{
 		int count = w->attributes.size();
-		count -= w->attributes.count("\\src");
-		count -= w->attributes.count("\\unused_bits");
+		count -= w->attributes.count(ID(src));
+		count -= w->attributes.count(ID(unused_bits));
 		return count;
 	}
 
@@ -398,11 +398,11 @@ struct WreduceWorker
 		SigMap init_attr_sigmap = mi.sigmap;
 
 		for (auto w : module->wires()) {
-			if (w->get_bool_attribute("\\keep"))
+			if (w->get_bool_attribute(ID(keep)))
 				for (auto bit : mi.sigmap(w))
 					keep_bits.insert(bit);
-			if (w->attributes.count("\\init")) {
-				Const initval = w->attributes.at("\\init");
+			if (w->attributes.count(ID(init))) {
+				Const initval = w->attributes.at(ID(init));
 				SigSpec initsig = init_attr_sigmap(w);
 				int width = std::min(GetSize(initval), GetSize(initsig));
 				for (int i = 0; i < width; i++)
@@ -459,8 +459,8 @@ struct WreduceWorker
 
 		if (!remove_init_bits.empty()) {
 			for (auto w : module->wires()) {
-				if (w->attributes.count("\\init")) {
-					Const initval = w->attributes.at("\\init");
+				if (w->attributes.count(ID(init))) {
+					Const initval = w->attributes.at(ID(init));
 					Const new_initval(State::Sx, GetSize(w));
 					SigSpec initsig = init_attr_sigmap(w);
 					int width = std::min(GetSize(initval), GetSize(initsig));
@@ -468,7 +468,7 @@ struct WreduceWorker
 						if (!remove_init_bits.count(initsig[i]))
 							new_initval[i] = initval[i];
 					}
-					w->attributes.at("\\init") = new_initval;
+					w->attributes.at(ID(init)) = new_initval;
 				}
 			}
 		}
@@ -528,23 +528,23 @@ struct WreducePass : public Pass {
 
 			for (auto c : module->selected_cells())
 			{
-				if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
-						"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
-						"$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) {
-					SigSpec sig = c->getPort("\\Y");
+				if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
+						ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
+						ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID(Y))) > 1) {
+					SigSpec sig = c->getPort(ID(Y));
 					if (!sig.has_const()) {
-						c->setPort("\\Y", sig[0]);
-						c->setParam("\\Y_WIDTH", 1);
+						c->setPort(ID(Y), sig[0]);
+						c->setParam(ID(Y_WIDTH), 1);
 						sig.remove(0);
 						module->connect(sig, Const(0, GetSize(sig)));
 					}
 				}
 
-				if (c->type.in("$div", "$mod", "$pow"))
+				if (c->type.in(ID($div), ID($mod), ID($pow)))
 				{
-					SigSpec A = c->getPort("\\A");
+					SigSpec A = c->getPort(ID(A));
 					int original_a_width = GetSize(A);
-					if (c->getParam("\\A_SIGNED").as_bool()) {
+					if (c->getParam(ID(A_SIGNED)).as_bool()) {
 						while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0)
 							A.remove(GetSize(A)-1, 1);
 					} else {
@@ -554,13 +554,13 @@ struct WreducePass : public Pass {
 					if (original_a_width != GetSize(A)) {
 						log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
 								original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type));
-						c->setPort("\\A", A);
-						c->setParam("\\A_WIDTH", GetSize(A));
+						c->setPort(ID(A), A);
+						c->setParam(ID(A_WIDTH), GetSize(A));
 					}
 
-					SigSpec B = c->getPort("\\B");
+					SigSpec B = c->getPort(ID(B));
 					int original_b_width = GetSize(B);
-					if (c->getParam("\\B_SIGNED").as_bool()) {
+					if (c->getParam(ID(B_SIGNED)).as_bool()) {
 						while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0)
 							B.remove(GetSize(B)-1, 1);
 					} else {
@@ -570,24 +570,24 @@ struct WreducePass : public Pass {
 					if (original_b_width != GetSize(B)) {
 						log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
 								original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type));
-						c->setPort("\\B", B);
-						c->setParam("\\B_WIDTH", GetSize(B));
+						c->setPort(ID(B), B);
+						c->setParam(ID(B_WIDTH), GetSize(B));
 					}
 				}
 
-				if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) {
-					IdString memid = c->getParam("\\MEMID").decode_string();
+				if (!opt_memx && c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
+					IdString memid = c->getParam(ID(MEMID)).decode_string();
 					RTLIL::Memory *mem = module->memories.at(memid);
 					if (mem->start_offset >= 0) {
-						int cur_addrbits = c->getParam("\\ABITS").as_int();
+						int cur_addrbits = c->getParam(ID(ABITS)).as_int();
 						int max_addrbits = ceil_log2(mem->start_offset + mem->size);
 						if (cur_addrbits > max_addrbits) {
 							log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n",
 									cur_addrbits-max_addrbits, cur_addrbits,
-									c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init",
+									c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init",
 									log_id(module), log_id(c), log_id(memid));
-							c->setParam("\\ABITS", max_addrbits);
-							c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits));
+							c->setParam(ID(ABITS), max_addrbits);
+							c->setPort(ID(ADDR), c->getPort(ID(ADDR)).extract(0, max_addrbits));
 						}
 					}
 				}
diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc
index b541ceb6b..8f195a90a 100644
--- a/passes/techmap/extract_fa.cc
+++ b/passes/techmap/extract_fa.cc
@@ -513,13 +513,13 @@ struct ExtractFaWorker
 				}
 
 				if (func2.at(key).count(xor2_func)) {
-					SigBit YY = invert_xy ? module->NotGate(NEW_ID, Y) : Y;
+					SigBit YY = invert_xy || (f2i.inv_a && !f2i.inv_b) || (!f2i.inv_a && f2i.inv_b) ? module->NotGate(NEW_ID, Y) : Y;
 					for (auto bit : func2.at(key).at(xor2_func))
 						assign_new_driver(bit, YY);
 				}
 
 				if (func2.at(key).count(xnor2_func)) {
-					SigBit YY = invert_xy ? Y : module->NotGate(NEW_ID, Y);
+					SigBit YY = invert_xy || (f2i.inv_a && !f2i.inv_b) || (!f2i.inv_a && f2i.inv_b) ? Y : module->NotGate(NEW_ID, Y);
 					for (auto bit : func2.at(key).at(xnor2_func))
 						assign_new_driver(bit, YY);
 				}
diff --git a/tests/various/opt_expr.ys b/tests/various/opt_expr.ys
index 0c61ac881..f0306efa1 100644
--- a/tests/various/opt_expr.ys
+++ b/tests/various/opt_expr.ys
@@ -5,144 +5,219 @@ module opt_expr_add_test(input [3:0] i, input [7:0] j, output [8:0] o);
 endmodule
 EOT
 
-hierarchy -auto-top
-proc
-design -save gold
+equiv_opt -assert opt_expr -fine
+design -load postopt
 
-opt_expr -fine
-wreduce
-
-select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
-
-design -stash gate
-
-design -import gold -as gold
-design -import gate -as gate
-
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -show-ports miter
+select -assert-count 1 t:$add r:A_WIDTH=5 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
 
 ##########
 
+# alumacc version of above
+design -reset
+read_verilog <<EOT
+module opt_expr_add_test(input [3:0] i, input [7:0] j, output [8:0] o);
+    assign o = (i << 4) + j;
+endmodule
+EOT
+
+alumacc
+equiv_opt -assert opt_expr -fine
+design -load postopt
+
+select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i
+
+##########
+
+design -reset
 read_verilog <<EOT
 module opt_expr_add_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
     assign o = (i << 4) + j;
 endmodule
 EOT
 
-hierarchy -auto-top
-proc
-design -save gold
+equiv_opt -assert opt_expr -fine
+design -load postopt
 
-opt_expr -fine
-wreduce
-
-select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
-
-design -stash gate
-
-design -import gold -as gold
-design -import gate -as gate
-
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -show-ports miter
+select -assert-count 1 t:$add r:A_WIDTH=5 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
 
 ##########
 
+# alumacc version of above
+design -reset
+read_verilog <<EOT
+module opt_expr_add_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
+    assign o = (i << 4) + j;
+endmodule
+EOT
+
+alumacc
+equiv_opt -assert opt_expr -fine
+design -load postopt
+
+select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i
+
+##########
+
+design -reset
 read_verilog <<EOT
 module opt_expr_sub_test1(input [3:0] i, input [7:0] j, output [8:0] o);
     assign o = j - (i << 4);
 endmodule
 EOT
 
-hierarchy -auto-top
-proc
-design -save gold
+equiv_opt -assert opt_expr -fine
+design -load postopt
 
-opt_expr -fine
-wreduce
-
-select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
-
-design -stash gate
-
-design -import gold -as gold
-design -import gate -as gate
-
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -show-ports miter
+select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i
 
 ##########
 
+# alumacc version of above
+design -reset
+read_verilog <<EOT
+module opt_expr_sub_test1(input [3:0] i, input [7:0] j, output [8:0] o);
+    assign o = j - (i << 4);
+endmodule
+EOT
+
+alumacc
+equiv_opt -assert opt_expr -fine
+design -load postopt
+
+dump
+select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i
+
+##########
+
+design -reset
 read_verilog <<EOT
 module opt_expr_sub_signed_test1(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
     assign o = j - (i << 4);
 endmodule
 EOT
 
-hierarchy -auto-top
-proc
-design -save gold
+equiv_opt -assert opt_expr -fine
+design -load postopt
 
-opt_expr -fine
-wreduce
-
-select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
-
-design -stash gate
-
-design -import gold -as gold
-design -import gate -as gate
-
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -show-ports miter
+select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i
 
 ##########
 
+# alumacc version of above
+design -reset
+read_verilog <<EOT
+module opt_expr_sub_signed_test1(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
+    assign o = j - (i << 4);
+endmodule
+EOT
+
+alumacc
+equiv_opt -assert opt_expr -fine
+design -load postopt
+
+select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=5 r:Y_WIDTH=5 %i %i %i
+
+##########
+
+design -reset
 read_verilog <<EOT
 module opt_expr_sub_test2(input [3:0] i, input [7:0] j, output [8:0] o);
     assign o = (i << 4) - j;
 endmodule
 EOT
 
-hierarchy -auto-top
-proc
-design -save gold
+equiv_opt -assert opt_expr -fine
+design -load postopt
 
-opt_expr -fine
-wreduce
-
-select -assert-count 1 t:$sub r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
-
-design -stash gate
-
-design -import gold -as gold
-design -import gate -as gate
-
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -show-ports miter
+select -assert-count 1 t:$sub r:A_WIDTH=9 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
 
 ##########
 
+# alumacc version of above
+design -reset
+read_verilog <<EOT
+module opt_expr_sub_test2(input [3:0] i, input [7:0] j, output [8:0] o);
+    assign o = (i << 4) - j;
+endmodule
+EOT
+
+alumacc
+opt_expr -fine
+equiv_opt -assert opt_expr -fine
+design -load postopt
+
+select -assert-count 1 t:$alu r:A_WIDTH=9 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
+
+##########
+
+design -reset
 read_verilog <<EOT
 module opt_expr_sub_test4(input [3:0] i, output [8:0] o);
     assign o = 5'b00010 - i;
 endmodule
 EOT
 
-hierarchy -auto-top
-proc
-design -save gold
-
-opt_expr -fine
 wreduce
+equiv_opt -assert opt_expr -fine
+design -load postopt
 
 select -assert-count 1 t:$sub r:A_WIDTH=2 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
 
-design -stash gate
+##########
 
-design -import gold -as gold
-design -import gate -as gate
+# alumacc version of above
+design -reset
+read_verilog <<EOT
+module opt_expr_sub_test4(input [3:0] i, output [8:0] o);
+    assign o = 5'b00010 - i;
+endmodule
+EOT
 
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -show-ports miter
+wreduce
+alumacc
+equiv_opt -assert opt_expr -fine
+design -load postopt
+
+select -assert-count 1 t:$alu r:A_WIDTH=2 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_alu_test_ci0_bi0(input [7:0] a, input [3:0] b, output [8:0] x, y, co);
+    \$alu #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(8), .Y_WIDTH(9)) alu (.A(a), .B({b, 4'b0000}), .CI(1'b0), .BI(1'b0), .X(x), .Y(y), .CO(co));
+endmodule
+EOT
+check
+
+equiv_opt -assert opt_expr -fine
+design -load postopt
+select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_alu_test_ci1_bi1(input [7:0] a, input [3:0] b, output [8:0] x, y, co);
+    \$alu #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(8), .Y_WIDTH(9)) alu (.A(a), .B({b, 4'b0000}), .CI(1'b1), .BI(1'b1), .X(x), .Y(y), .CO(co));
+endmodule
+EOT
+check
+
+equiv_opt opt_expr -fine
+design -load postopt
+select -assert-count 1 t:$alu r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
+
+###########
+
+design -reset
+read_verilog -icells <<EOT
+module opt_expr_alu_test_ci0_bi1(input [7:0] a, input [3:0] b, output [8:0] x, y, co);
+    \$alu #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(8), .Y_WIDTH(9)) alu (.A(a), .B({b, 4'b0000}), .CI(1'b0), .BI(1'b1), .X(x), .Y(y), .CO(co));
+endmodule
+EOT
+check
+
+equiv_opt opt_expr -fine
+design -load postopt
+select -assert-count 1 t:$alu r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i