Explorar o código

C generation done?

Maybe there are some bugs wrt self-loops, but I was not able to find them.
Randy Paredis %!s(int64=4) %!d(string=hai) anos
pai
achega
0b7df833fd

+ 106 - 31
src/CBD/converters/CBD2C/__init__.py

@@ -3,17 +3,22 @@ A module that allows the creation of a C file, in which the block's computations
 """
 from CBD.scheduling import TopologicalScheduler
 from CBD.solver import GaussianJordanLinearSolver
-from CBD.depGraph import DepGraph, createDepGraph
-from CBD.converters.latexify import CBD2Latex
+from CBD.depGraph import DepGraph, createDepGraph, gvDepGraph
+from CBD.converters.latexify import CBD2Latex, _BLOCK_MAP
+import CBD.naivelog as naivelog
 
 from jinja2 import Template
 
 class CBD2C:
-	def __init__(self, model, itcnt):
+	def __init__(self, model, itcnt, delta=1.0):
 		self.itcnt = itcnt
+		self.delta = 1.0
 		self.model = model.clone()
 		self.model.flatten(psep='_')
+		for block in self.model.getBlocks():
+			block.setBlockName(block.getBlockName().replace("-", "_"))
 		self.scheduler = TopologicalScheduler()
+		self.solver = GaussianJordanLinearSolver(naivelog.getLogger("CBD"))
 
 	def get_blocks(self):
 		return self.model.getBlocks()
@@ -22,13 +27,97 @@ class CBD2C:
 		depGraph = createDepGraph(self.model, curIt)
 		return self.scheduler.schedule(depGraph, curIt, 0.0)
 
+	@staticmethod
+	def flatten(t):
+		return [item for sublist in t for item in sublist]
+
+	def obtain_data_from_order(self, order, curIt):
+		i = "0" if curIt == 0 else "i"
+		conf = {"path_sep": '_', "ignore_path": False, "escape_nonlatex": False, "time_variable": "time"}
+		norder = []
+		for c in order:
+			nc = []
+			if len(c) == 1 and c[0] not in [c[0].getBlockConnectedToInput(x).block for x in c[0].getInputPortNames()]:
+				n = c[0]
+				bd = CBD2Latex.get_block_data(n, self.model, conf)
+				if bd is None:
+					if n.getBlockType() == "WireBlock":
+						bl = n.getBlockConnectedToInput("IN1")
+						nc = ([n.getPath('_')], bl.block.getPath('_') + '_' + bl.output_port + '[' + i + ']')
+				else:
+					kv = {x: n.getBlockConnectedToInput(x) for x in n.getInputPortNames()}
+					for k, v in kv.items():
+						bd[1].apply(n.getPath('_') + '_' + k, v.block.getPath('_') + '_' + v.output_port)
+					if n.getBlockType() == "DelayBlock":
+						if curIt == 0:
+							bd[1].apply_time(time=-1, t=i, fmt="[{time}]")
+							bd = bd[0], bd[1].args[1]
+						else:
+							bd[1].apply_time(t=i, fmt="[{time}]")
+							bd = bd[0], bd[1].args[0]
+					try:
+						bd[1].apply_time(t=i, fmt="[{time}]")
+					except: pass
+					nc = ([bd[0]], str(bd[1]))
+				if n.getBlockType() != "WireBlock":
+					n.compute(curIt)
+			else:
+				self.solver.checkValidity(self.model.getPath("."), c)
+
+				# Get matrix representation
+				m1, m2 = self.solver.constructInput(c, curIt)
+				mat = []
+				for r in range(m1.rows):
+					row = []
+					for col in range(m1.cols):
+						row.append(float(m1[r, col]))
+					row.append(float(m2[r]))
+					mat.append(row)
+
+				deps = {}
+				for b in c:
+					D = [b.getBlockConnectedToInput(x) for x in b.getInputPortNames()]
+					deps[b] = [b.block.getPath('_') + '_' + b.output_port for b in D if b.block in c]
+
+				if len(mat) == 1:
+					nc = ([deps[c[mat[0].index(1)]]], mat[0][-1])
+				else:
+					dlist = []
+					for b in c:
+						for d in deps[b]:
+							if d not in dlist:
+								dlist.append(d)
+
+					nc = (dlist, str(mat).replace("[", "{").replace("]", "}"))
+			norder.append(nc)
+		print(norder)
+		return norder
+
 	def generate(self, fname):
 		with open("template.c", 'r') as file:
 			template = Template(file.read(), trim_blocks=True, lstrip_blocks=True)
+		variables = []
+		for block in self.get_blocks():
+			if block.getBlockType() == "WireBlock":
+				variables.append(block.getPath('_'))
+				continue
+			for port in block.getSignals().keys():
+				variables.append(block.getPath('_') + '_' + port)
+
+		# Obtain the data
+		comp0 = self.get_order(0)
+		comp = self.get_order(1)
+		self.model.addFixedRateClock()
+		comp0 = self.obtain_data_from_order(comp0, 0)
+		comp = self.obtain_data_from_order(comp, 1)
+
+		# print(comp0)
+
 		contents = template.render(itcnt = self.itcnt,
-		                           blocks = self.get_blocks(),
-		                           components0 = self.get_order(0),
-		                           components = self.get_order(1) )
+		                           delta = self.delta,
+		                           variables = variables,
+		                           components0 = comp0,
+		                           components = comp )
 		with open(fname, 'w') as file:
 			file.write(contents)
 
@@ -39,35 +128,21 @@ if __name__ == '__main__':
 		def __init__(self, name):
 			super().__init__(name, [], ["x"])
 			self.addBlock(AdderBlock("A"))
-			self.addBlock(ProductBlock("B"))
+			# self.addBlock(ProductBlock("B"))
+			# self.addConnection("A", "A")
+			# self.addConnection("A", "B")
+			# self.addConnection("B", "A")
+			# self.addConnection("B", "B")
+			# self.addBlock(ProductBlock("B"))
 			self.addBlock(ConstantBlock("C", 3.0))
 			self.addBlock(ConstantBlock("D", 6.0))
 			self.addConnection("C", "A")
-			self.addConnection("B", "A")
-			self.addConnection("A", "B")
-			self.addConnection("D", "B")
-			self.addConnection("B", "x")
+			# self.addConnection("B", "A")
+			# self.addConnection("A", "B")
+			self.addConnection("D", "A")
+			self.addConnection("A", "x")
 
 	test = Test("test")
-	ltx = CBD2Latex(test, render_latex=False, escape_nonlatex=False, path_sep='_', ignore_path=False)
-	ltx.simplify_links()
-	print(ltx.equations)
 	gen = CBD2C(test, 3000)
 	gen.generate("example.c")
-	for block in gen.get_blocks():
-		try:
-			print(block.getBlockConnectedToInput("IN1"))
-		except: pass
-	# sol = GaussianJordanLinearSolver(None)
-	# # block = gen.get_blocks()
-	# for comp in gen.get_order(0):
-	# 	print("--------------")
-	# 	if len(comp) == 1:
-	# 		print(comp[0])
-	# 		comp[0].compute(0)
-	# 	else:
-	# 		m1, m2 = sol.constructInput(comp, 0)
-	# 		print(m1)
-	# 		print(m2)
-	#
-	# # TODO: Generate header file with all #defines
+

BIN=BIN
src/CBD/converters/CBD2C/a.out


+ 62 - 0
src/CBD/converters/CBD2C/code.c

@@ -0,0 +1,62 @@
+#include <math.h>
+#include <stdio.h>
+#include <time.h>
+#include "lsolve.h"
+
+#define M 8    /* No of Blocks */
+#define N 100    /* No of Iterations */
+
+/* BLOCK VARIABLE NAMES */
+#define Factorial_GSTB9gRuDpQ50gPdog42_3_OUT1 RESULT[0]
+#define Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1 RESULT[1]
+#define Factorial_GSTB9gRuDpQ50gPdog42_12_OUT1 RESULT[2]
+#define Factorial_GSTB9gRuDpQ50gPdog42_12_relative RESULT[3]
+#define Factorial_one_OUT1 RESULT[4]
+#define Factorial_GSTB9gRuDpQ50gPdog42_24_OUT1 RESULT[5]
+#define Factorial_GSTB9gRuDpQ50gPdog42_31_OUT1 RESULT[6]
+#define Factorial_y RESULT[7]
+
+double RESULT[M][N];
+
+/* EQUATIONS */
+void _eq_init(const double time, const double delta) {
+    Factorial_one_OUT1[0] = 1;
+    Factorial_GSTB9gRuDpQ50gPdog42_3_OUT1[0] = Factorial_one_OUT1[0];
+    Factorial_GSTB9gRuDpQ50gPdog42_24_OUT1[0] = Factorial_one_OUT1[0];
+    Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1[0] = (Factorial_GSTB9gRuDpQ50gPdog42_3_OUT1[0]) * (Factorial_GSTB9gRuDpQ50gPdog42_24_OUT1[0]);
+    Factorial_GSTB9gRuDpQ50gPdog42_12_OUT1[0] = time;
+    Factorial_GSTB9gRuDpQ50gPdog42_31_OUT1[0] = (Factorial_one_OUT1[0]) + (Factorial_GSTB9gRuDpQ50gPdog42_12_OUT1[0]);
+    Factorial_y[0] = Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1[0];
+}
+
+void _eq_iter(const unsigned int i, const double time, const double delta) {
+    Factorial_GSTB9gRuDpQ50gPdog42_3_OUT1[i] = Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1[i-1];
+    Factorial_GSTB9gRuDpQ50gPdog42_24_OUT1[i] = Factorial_GSTB9gRuDpQ50gPdog42_31_OUT1[i-1];
+    Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1[i] = (Factorial_GSTB9gRuDpQ50gPdog42_3_OUT1[i]) * (Factorial_GSTB9gRuDpQ50gPdog42_24_OUT1[i]);
+    Factorial_GSTB9gRuDpQ50gPdog42_12_OUT1[i] = time;
+    Factorial_one_OUT1[i] = 1;
+    Factorial_GSTB9gRuDpQ50gPdog42_31_OUT1[i] = (Factorial_one_OUT1[i]) + (Factorial_GSTB9gRuDpQ50gPdog42_12_OUT1[i]);
+    Factorial_y[i] = Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1[i];
+}
+
+/* SIMULATOR */
+int main(int argc, char *args[]) {
+    double delta = 1.0;
+    double time = 0.0;
+
+    _eq_init(0.0, delta);
+    for(int i = 1; i < N; ++i) {
+        time += delta;
+        _eq_iter(i, time, delta);
+    }
+
+    printf("\t%-20s = %12.4f\n", "TIME", time);
+    printf("\t%-20s = %12.4f\n", "Factorial_GSTB9gRuDpQ50gPdog42_3_OUT1", Factorial_GSTB9gRuDpQ50gPdog42_3_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1", Factorial_GSTB9gRuDpQ50gPdog42_7_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "Factorial_GSTB9gRuDpQ50gPdog42_12_OUT1", Factorial_GSTB9gRuDpQ50gPdog42_12_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "Factorial_GSTB9gRuDpQ50gPdog42_12_relative", Factorial_GSTB9gRuDpQ50gPdog42_12_relative[N - 1]);
+    printf("\t%-20s = %12.4f\n", "Factorial_one_OUT1", Factorial_one_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "Factorial_GSTB9gRuDpQ50gPdog42_24_OUT1", Factorial_GSTB9gRuDpQ50gPdog42_24_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "Factorial_GSTB9gRuDpQ50gPdog42_31_OUT1", Factorial_GSTB9gRuDpQ50gPdog42_31_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "Factorial_y", Factorial_y[N - 1]);
+}

+ 20 - 27
src/CBD/converters/CBD2C/example.c

@@ -1,42 +1,32 @@
 #include <math.h>
 #include <stdio.h>
 #include <time.h>
-#include <stdlib.h>
 #include "lsolve.h"
 
-#define M 5    /* No of Blocks */
+#define M 4    /* No of Blocks */
 #define N 3000    /* No of Iterations */
 
 /* BLOCK VARIABLE NAMES */
-#define test_A RESULT[0]
-#define test_B RESULT[1]
-#define test_C RESULT[2]
-#define test_D RESULT[3]
-#define test_x RESULT[4]
+#define test_A_OUT1 RESULT[0]
+#define test_C_OUT1 RESULT[1]
+#define test_D_OUT1 RESULT[2]
+#define test_x RESULT[3]
 
 double RESULT[M][N];
 
 /* EQUATIONS */
-void _eq_init(const double delta) {
-    test_C = ??;
-    test_D = ??;
-
-    /* Algebraic Loop */
-    double _C2[2][3] = {{ -1.0, 6.0, 0.0}, {1.0, -1.0, -3.0 }};
-    agloop(&_C2, 2, &bla_B[0], &bla_A[0]);
-
-    test_x = ??;
+void _eq_init(const double time, const double delta) {
+    test_C_OUT1[0] = 3.0;
+    test_D_OUT1[0] = 6.0;
+    test_A_OUT1[0] = (test_C_OUT1[0]) + (test_D_OUT1[0]);
+    test_x[0] = test_A_OUT1[0];
 }
 
 void _eq_iter(const unsigned int i, const double time, const double delta) {
-    bla_C[i] = 3.0;
-    bla_D[i] = 6.0;
-
-    /* Algebraic Loop */
-    double _C3[2][3] = {{ -1.0, 6.0, 0.0}, {1.0, -1.0, -3.0 }};
-    agloop(&_C3, 2, &bla_B[i], &bla_A[i]);
-
-    bla_x[i] = bla_B[i];
+    test_C_OUT1[i] = 3.0;
+    test_D_OUT1[i] = 6.0;
+    test_A_OUT1[i] = (test_C_OUT1[i]) + (test_D_OUT1[i]);
+    test_x[i] = test_A_OUT1[i];
 }
 
 /* SIMULATOR */
@@ -44,12 +34,15 @@ int main(int argc, char *args[]) {
     double delta = 0.1;
     double time = 0.0;
 
-    _eq_init(delta);
+    _eq_init(0.0, delta);
     for(int i = 1; i < N; ++i) {
         time += delta;
         _eq_iter(i, time, delta);
     }
 
-    printf("\tTIME = %12.4f s\n", time);
-    printf("\tX    = %12.4f\n", bla_x[N - 1]);
+    printf("\t%-20s = %12.4f\n", "TIME", time);
+    printf("\t%-20s = %12.4f\n", "test_A_OUT1", test_A_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "test_C_OUT1", test_C_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "test_D_OUT1", test_D_OUT1[N - 1]);
+    printf("\t%-20s = %12.4f\n", "test_x", test_x[N - 1]);
 }

+ 32 - 0
src/CBD/converters/CBD2C/factorial.py

@@ -0,0 +1,32 @@
+#!/usr/bin/python3
+# This file was automatically generated from drawio2cbd with the command:
+#   C:\Users\randy\Documents\MoSIS\assignments\2021\A3-CBD\DrawioConvert.exe -F CBD -e Factorial -sSrgv factorial.drawio
+
+from CBD.Core import *
+from CBD.lib.std import *
+
+
+class Factorial(CBD):
+    def __init__(self, block_name):
+        super().__init__(block_name, input_ports=[], output_ports=['y'])
+
+        # Create the Blocks
+        self.addBlock(DelayBlock("GSTB9gRuDpQ50gPdog42-3"))
+        self.addBlock(ProductBlock("GSTB9gRuDpQ50gPdog42-7"))
+        self.addBlock(TimeBlock("GSTB9gRuDpQ50gPdog42-12"))
+        self.addBlock(ConstantBlock("one", value=(1)))
+        self.addBlock(DelayBlock("GSTB9gRuDpQ50gPdog42-24"))
+        self.addBlock(AdderBlock("GSTB9gRuDpQ50gPdog42-31"))
+
+        # Create the Connections
+        self.addConnection("GSTB9gRuDpQ50gPdog42-3", "GSTB9gRuDpQ50gPdog42-7", output_port_name='OUT1', input_port_name='IN1')
+        self.addConnection("GSTB9gRuDpQ50gPdog42-7", "GSTB9gRuDpQ50gPdog42-3", output_port_name='OUT1', input_port_name='IN1')
+        self.addConnection("GSTB9gRuDpQ50gPdog42-7", "y", output_port_name='OUT1')
+        self.addConnection("one", "GSTB9gRuDpQ50gPdog42-3", output_port_name='OUT1', input_port_name='IC')
+        self.addConnection("one", "GSTB9gRuDpQ50gPdog42-24", output_port_name='OUT1', input_port_name='IC')
+        self.addConnection("one", "GSTB9gRuDpQ50gPdog42-31", output_port_name='OUT1', input_port_name='IN1')
+        self.addConnection("GSTB9gRuDpQ50gPdog42-24", "GSTB9gRuDpQ50gPdog42-7", output_port_name='OUT1', input_port_name='IN2')
+        self.addConnection("GSTB9gRuDpQ50gPdog42-31", "GSTB9gRuDpQ50gPdog42-24", output_port_name='OUT1', input_port_name='IN1')
+        self.addConnection("GSTB9gRuDpQ50gPdog42-12", "GSTB9gRuDpQ50gPdog42-31", output_port_name='OUT1', input_port_name='IN2')
+
+

+ 23 - 0
src/CBD/converters/CBD2C/factorial_experiment.py

@@ -0,0 +1,23 @@
+#!/usr/bin/python3
+# This file was automatically generated from drawio2cbd with the command:
+#   C:\Users\randy\Documents\MoSIS\assignments\2021\A3-CBD\DrawioConvert.exe -F CBD -e Factorial -sSrgv factorial.drawio
+
+from factorial import *
+from CBD.simulator import Simulator
+
+
+cbd = Factorial("Factorial")
+
+# Run the Simulation
+# sim = Simulator(cbd)
+# sim.run(10)
+#
+# for s in cbd.getSignal("y"):
+#    print(s)
+
+# TODO: Process Your Simulation Results
+from CBD.converters.eq2CBD import eq2CBD
+from CBD.converters.CBD2C import CBD2C
+
+gen = CBD2C(cbd, 100, 1.0)
+gen.generate("code.c")

+ 1 - 1
src/CBD/converters/CBD2C/generated.c

@@ -17,7 +17,7 @@
 double RESULT[M][N];
 
 /* EQUATIONS */
-void _eq_init(const double delta) {
+void _eq_init(const double time, const double delta) {
     bla_C[0] = 3.0;
     bla_D[0] = 6.0;
 

+ 5 - 4
src/CBD/converters/CBD2C/lsolve.c

@@ -1,6 +1,7 @@
 #include <math.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include "lsolve.h"
 
 double getelm(double* matrix, const unsigned int i, const unsigned int j, const unsigned int m) {
@@ -82,10 +83,10 @@ double det(double* matrix, const unsigned int size) {
     unsigned int height = size - 1;
 
     if(size == 2) {
-        double a00 = getelm(matrix, 0, 0, height);
-        double a01 = getelm(matrix, 0, 1, height);
-        double a10 = getelm(matrix, 1, 0, height);
-        double a11 = getelm(matrix, 1, 1, height);
+        double a00 = getelm(matrix, 0, 0, size);
+        double a01 = getelm(matrix, 0, 1, size);
+        double a10 = getelm(matrix, 1, 0, size);
+        double a11 = getelm(matrix, 1, 1, size);
         return (a00 * a11) - (a01 * a10);
     }
 

+ 22 - 18
src/CBD/converters/CBD2C/template.c

@@ -1,56 +1,60 @@
 #include <math.h>
 #include <stdio.h>
 #include <time.h>
-#include <stdlib.h>
 #include "lsolve.h"
 
-#define M {{ blocks|length }}    /* No of Blocks */
+#define M {{ variables|length }}    /* No of Blocks */
 #define N {{ itcnt }}    /* No of Iterations */
 
 /* BLOCK VARIABLE NAMES */
-{% for block in blocks %}
-#define {{ block.getPath('_') }} RESULT[{{ loop.index0 }}]
+{% for var in variables %}
+#define {{ var }} RESULT[{{ loop.index0 }}]
 {% endfor %}
 
 double RESULT[M][N];
 
 /* EQUATIONS */
-void _eq_init(const double delta) {
+void _eq_init(const double time, const double delta) {
     {% for comp in components0 %}
-        {% if comp|length == 1 %}
-    {{ comp[0].getPath('_') }} = ??;
+        {% if comp[0]|length == 1 %}
+    {{ comp[0][0] }}[0] = {{ comp[1] }};
         {% else %}
 
     /* Algebraic Loop */
-    double _C{{ loop.index0 }}[{{comp|length}}][{{comp|length + 1}}] = {{ '{{' }} -1.0, 6.0, 0.0}, {1.0, -1.0, -3.0 {{ '}}' }};
-    agloop(&_C{{ loop.index0 }}, {{comp|length}}, &bla_B[0], &bla_A[0]);
+    double _C{{ loop.index0 }}[{{comp[0]|length}}][{{comp[0]|length + 1}}] = {{ comp[1] }};
+    agloop(&_C{{ loop.index0 }}, {{comp|length}}{% for block in comp[0] %}, &{{ block }}[0]{% endfor %});
 
         {% endif %}
     {% endfor %}
 }
 
 void _eq_iter(const unsigned int i, const double time, const double delta) {
-    bla_C[i] = 3.0;
-    bla_D[i] = 6.0;
+    {% for comp in components %}
+        {% if comp[0]|length == 1 %}
+    {{ comp[0][0] }}[i] = {{ comp[1] }};
+        {% else %}
 
     /* Algebraic Loop */
-    double _C3[2][3] = {{ '{{' }} -1.0, 6.0, 0.0}, {1.0, -1.0, -3.0 {{ '}}' }};
-    agloop(&_C3, 2, &bla_B[i], &bla_A[i]);
+    double _C{{ loop.index0 }}[{{comp[0]|length}}][{{comp[0]|length + 1}}] = {{ comp[1] }};
+    agloop(&_C{{ loop.index0 }}, {{comp|length}}{% for block in comp[0] %}, &{{ block }}[i]{% endfor %});
 
-    bla_x[i] = bla_B[i];
+        {% endif %}
+    {% endfor %}
 }
 
 /* SIMULATOR */
 int main(int argc, char *args[]) {
-    double delta = 0.1;
+    double delta = {{ delta }};
     double time = 0.0;
 
-    _eq_init(delta);
+    _eq_init(0.0, delta);
     for(int i = 1; i < N; ++i) {
         time += delta;
         _eq_iter(i, time, delta);
     }
 
-    printf("\tTIME = %12.4f s\n", time);
-    printf("\tX    = %12.4f\n", bla_x[N - 1]);
+    printf("\t%-20s = %12.4f\n", "TIME", time);
+    {% for var in variables %}
+    printf("\t%-20s = %12.4f\n", "{{ var }}", {{ var }}[N - 1]);
+    {% endfor %}
 }

+ 64 - 41
src/CBD/converters/latexify.py

@@ -51,25 +51,29 @@ class CBD2Latex:
 		merge_negs (bool):      Whether or not all negations in a product should be merged into a
 								single negation. Defaults to :code:`True`.
 	"""
+
+	DEFAULT_CONFIG = {
+		"show_steps": False,
+		"ignore_path": True,
+		"escape_nonlatex": True,
+		"time_variable": 'i',
+		"render_latex": True,
+		"time_format": "({time})",
+		"delta_t": "",
+		"replace_par": True,
+		"type_formats": {},
+		"path_sep": '.',
+
+		# Fnc settings
+		"merge_sums": True,
+		"merge_prods": True,
+		"merge_negs": True
+	}
+	"""Default configuration setup."""
+
 	def __init__(self, model, **kwargs):
 		self.model = model
-		self.config = {
-			"show_steps": False,
-			"ignore_path": True,
-			"escape_nonlatex": True,
-			"time_variable": 'i',
-			"render_latex": True,
-			"time_format": "({time})",
-			"delta_t": "",
-			"replace_par": True,
-			"type_formats": {},
-			"path_sep": '.',
-
-			# Fnc settings
-			"merge_sums": True,
-			"merge_prods": True,
-			"merge_negs": True
-		}
+		self.config = self.DEFAULT_CONFIG
 
 		for k in kwargs:
 			if k in self.config:
@@ -81,19 +85,55 @@ class CBD2Latex:
 		self._step = 0
 
 	def _rename(self, name):
+		return CBD2Latex.rename(name, self.config, self.model)
+
+	@staticmethod
+	def rename(name, config, model):
 		"""Makes the name of a path accurate.
 
 		Args:
 			name (str):     The name to convert.
+			config (dict):  Configuration dictionary (see above).
+			model (CBD):    The parent CBD model.
 		"""
-		if self.config["ignore_path"]:
-			mname = self.model.getPath(self.config['path_sep']) + self.config['path_sep']
+		if config["ignore_path"]:
+			mname = model.getPath(config['path_sep']) + config['path_sep']
 			if name.startswith(mname):
 				name = name[len(mname):]
-		if self.config["escape_nonlatex"]:
+		if config["escape_nonlatex"]:
 			name = name.replace("_", r"\_")
 		return name
 
+	@staticmethod
+	def get_block_data(block, model, conf=None):
+		config = CBD2Latex.DEFAULT_CONFIG
+		if conf is not None:
+			for k, v in conf.items():
+				config[k] = v
+
+		TF = config["type_formats"]
+		func = _BLOCK_MAP.get(block.getBlockType(), None)
+		if func is None:
+			func = block.getBlockType()
+			if func in ["OutputPortBlock", "InputPortBlock", "WireBlock"]:
+				return None
+		if isinstance(func, str):
+			func = lambda b, p, f=func: (p("OUT1"), Fnc(f, [CBD2Latex.rename(p("%s") % x, config, model) for x in block.getInputPortNames()]))
+		res = func(block, lambda x: CBD2Latex.rename(block.getPath(config['path_sep']) + config['path_sep'] + x, config, model))
+		if isinstance(res, tuple):
+			f = res[1]
+			if isinstance(f, Fnc):
+				f.fmt = TF
+			elif isinstance(f, str):
+				f = f.format(time=config['time_variable'])
+			return res[0], f
+		elif isinstance(res, list):
+			for r in res:
+				f = r[1]
+				if isinstance(f, Fnc):
+					f.fmt = TF
+				return res[0], f
+
 	def _collect_equations(self):
 		"""
 		Loads the equations from the model in.
@@ -103,27 +143,10 @@ class CBD2Latex:
 			Technical Report <https://repository.uantwerpen.be/docman/irua/d28eb1/151279.pdf>`_
 		"""
 		# Add all blocks
-		TF = self.config["type_formats"]
 		for block in self.model.getBlocks():
-			func = _BLOCK_MAP.get(block.getBlockType(), None)
-			if func is None:
-				func = block.getBlockType()
-				if func in ["OutputPortBlock", "InputPortBlock", "WireBlock"]:
-					continue
-			if isinstance(func, str):
-				func = lambda b, p, f=func: (p("OUT1"), Fnc(f, [self._rename(p("%s") % x) for x in block.getInputPortNames()]))
-			res = func(block, lambda x: self._rename(block.getPath(self.config['path_sep']) + self.config['path_sep'] + x))
-			if isinstance(res, tuple):
-				f = res[1]
-				if isinstance(f, Fnc):
-					f.fmt = TF
-				self.equations[res[0]] = f
-			elif isinstance(res, list):
-				for r in res:
-					f = r[1]
-					if isinstance(f, Fnc):
-						f.fmt = TF
-					self.equations[r[0]] = f
+			f = self.get_block_data(block, self.model, self.config)
+			if f is not None:
+				self.equations[f[0]] = f[1]
 
 		# Add all connections
 		for block in self.model.getBlocks():
@@ -804,7 +827,7 @@ _BLOCK_MAP = {
 	"OrBlock": 'or',
 	"AndBlock": 'and',
 	"DelayBlock": 'D',
-	"TimeBlock": lambda block, p: (p("OUT1"), 't'),
+	"TimeBlock": lambda block, p: (p("OUT1"), '{time}'),
 	"DerivatorBlock": 'der',
 	"IntegratorBlock": 'integral',
 }

+ 1 - 1
src/CBD/simulator.py

@@ -3,7 +3,7 @@ import time
 import threading
 from . import naivelog
 from .depGraph import createDepGraph
-from .solver import GaussianJordanLinearSolver, SympySolver
+from .solver import GaussianJordanLinearSolver
 from .realtime.threadingBackend import ThreadingBackend, Platform
 from .util import PYTHON_VERSION, hash64
 from .scheduling import TopologicalScheduler