├── .gitignore
├── README.md
├── coolname
├── __init__.py
├── __main__.py
├── config.py
├── control.py
├── coolname.py
├── fonts
│ └── JetBrainsMono-Regular.ttf
├── fsm.py
├── gui.py
├── logger.py
├── memory.py
├── nodes.py
├── operator_.py
└── sample_ir.py
├── data
├── divergence_atomic.dot
├── divergence_speculative.dot
├── prefix_sum_parallel.dot
├── prefix_sum_work_effective.dot
├── trmm_MEM.json
├── trmm_atomic_IR.dot
└── trmm_speculative_IR.dot
├── header.png
├── requirements.txt
└── run.py
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | /venv
3 | /.vscode
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
5 | # \: a dataflow simulator.
6 |
7 | Abstract from thesis:
8 | > In recent developments, dataflow graphs are used to design highly parallel application-specific hardware (ASH). However, prototyping and optimizing these graphs - and the techniques used to construct them - is difficult as constructing and testing hardware circuits directly is expensive, both in time as cost. Currently, no model or tool exists to compare these graphs in terms of latency, energy and utilization.
9 |
10 | > In this thesis, we present \, a cycle-accurate, application-level static dataflow simulator, which can be used for analyzing high-level synthesis for application-specific hardware. Furthermore, we present and analyze several techniques and strategies to convert control dataflow graphs to pure dataflow graphs, and outline the possible challenges and limitations of this process. We validate the simulator - in terms of correctness and compliance to the static dataflow model - using controlled experiments in which we compare the execution of a dataflow graph using \, the execution of a conventional reference program and a manual simulation of the dataflow graph.
11 |
12 | > \ can be used as a tool to compare and optimize dataflow graphs for application-specific hardware by reporting performance metrics such as latency, energy and utilization. For ease of use, we also provide a GUI for the simulator, where the user can set input parameters, control the execution and gather performance results.
13 |
14 |
15 | ### Installation
16 |
17 | ---
18 |
19 | Tested for Python 3.8.
20 | ```
21 | pip3 install -r requirements.txt
22 | ```
23 |
24 | ### Usage
25 |
26 | ---
27 |
28 | From the GUI:
29 | ```
30 | python3 run.py
31 | ```
32 |
33 | Directly:
34 | ```
35 | from coolname.gui import GUI
36 | from coolname.control import Simulation
37 | from coolname.logger import Logger
38 | from coolname.memory import DefaultMemorySimulator
39 | from coolname.nodes import IR
40 |
41 | # Load graph
42 | graph = IR.from_DOT('mygraph.dot')
43 |
44 | # Setup
45 | mem = DefaultMemorySimulator()
46 | logger = Logger()
47 | sim = Simulation(mem=mem, logger=logger)
48 |
49 | # Interact with memory:
50 | mem.store(2, 'a')
51 | mem.store(True, 'b', [0,0])
52 |
53 | # Start
54 | sim.run()
55 | # or
56 | # sim.step()
57 | # or
58 | # sim.reset()
59 |
60 | # Statistics:
61 | sim.get_ipc_series()
62 | sim.get_end_statistics()
63 | ```
64 |
--------------------------------------------------------------------------------
/coolname/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffreyspaan/coolname/367db6afcab933d9dd494a49dbe51c75007fbd9f/coolname/__init__.py
--------------------------------------------------------------------------------
/coolname/__main__.py:
--------------------------------------------------------------------------------
1 |
2 | from .coolname import main
3 |
4 | main()
--------------------------------------------------------------------------------
/coolname/config.py:
--------------------------------------------------------------------------------
1 | from .operator_ import *
2 | import math
3 |
4 | class Config:
5 | class Latency:
6 | computation = {
7 | Operator.ADD: 1,
8 | Operator.SUB: 1,
9 | Operator.MUL: 3,
10 | Operator.DIV: 24,
11 | Operator.MOD: 24,
12 | Operator.LT: 1,
13 | Operator.LE: 1,
14 | Operator.GT: 1,
15 | Operator.GE: 1,
16 | Operator.EQ: 1,
17 | Operator.NE: 1,
18 | Operator.NEG: 0,
19 | Operator.NOT: 1
20 | }
21 |
22 | eta = 0
23 |
24 | mu_str = 'lambda n: math.log(n)'
25 | mu = eval(mu_str)
26 |
27 | mux_str = 'lambda n: math.log(n/4)'
28 | mux = eval(mux_str)
29 |
30 | combine_str = 'lambda n: math.log(n)/2'
31 | combine = eval(combine_str)
32 |
33 | xor_str = 'lambda n: math.log(n)/2'
34 | xor = eval(xor_str)
35 |
36 | mem_load = 8
37 | mem_store = 8
38 | communication = 1
39 |
40 | class Energy:
41 | computation = {
42 | Operator.ADD: 100,
43 | Operator.SUB: 100,
44 | Operator.MUL: 100,
45 | Operator.DIV: 100,
46 | Operator.MOD: 100,
47 | Operator.LT: 100,
48 | Operator.LE: 100,
49 | Operator.GT: 100,
50 | Operator.GE: 100,
51 | Operator.EQ: 100,
52 | Operator.NE: 100,
53 | Operator.NEG: 100,
54 | Operator.NOT: 100
55 | }
56 |
57 | eta = 100
58 |
59 | mu_str = 'lambda n: n*100'
60 | mu = eval(mu_str)
61 |
62 | mux_str = 'lambda n: n*100'
63 | mux = eval(mux_str)
64 |
65 | combine_str = 'lambda n: n*100'
66 | combine = eval(combine_str)
67 |
68 | xor_str = 'lambda n: n*100'
69 | xor = eval(xor_str)
70 |
71 | mem_load = 100
72 | mem_store = 100
73 | communication = 0
--------------------------------------------------------------------------------
/coolname/control.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from .config import *
4 | from .logger import *
5 |
6 | class Simulation:
7 | mem = None
8 | logger = None
9 |
10 | cycle = 0
11 |
12 | def __init__(self, graph=None, mem=None, logger=None):
13 | self.graph = graph
14 |
15 | Simulation.mem = mem
16 | Simulation.logger = logger
17 |
18 | self.stop_after = None
19 | self.halt_now = False
20 |
21 | self.busy_counter = 0
22 | self.start_time = 0
23 | self.end_time = 0
24 |
25 | self.ipc = []
26 |
27 | def run(self):
28 | self.start_time = time.time()
29 |
30 | while not (self.soft_stop() or self.hard_stop()):
31 | self.step()
32 |
33 | if self.soft_stop():
34 | # Account for soft stop extra unnecessary cycles.
35 | Simulation.cycle -= Config.Latency.communication
36 | self.ipc = self.ipc[:-Config.Latency.communication]
37 |
38 | self.end_time = time.time()
39 |
40 | def step(self):
41 | Simulation.cycle += 1
42 |
43 | for node in self.graph.nodes:
44 | node.step()
45 |
46 | self.was_busy()
47 | self.calc_ipc()
48 |
49 | def was_busy(self):
50 | if any([n.is_busy() for n in self.graph.nodes]):
51 | self.busy_counter = 0
52 | else:
53 | self.busy_counter += 1
54 |
55 | def hard_stop(self):
56 | if self.halt_now:
57 | return True
58 |
59 | if self.stop_after:
60 | if Simulation.cycle == self.stop_after:
61 | return True
62 |
63 | return False
64 |
65 | def soft_stop(self):
66 | return self.busy_counter == Config.Latency.communication
67 |
68 | def reset(self):
69 | Simulation.cycle = 0
70 | self.halt_now = False
71 | self.busy_counter = 0
72 | self.start_time = 0
73 | self.end_time = 0
74 | self.ipc = []
75 |
76 | for node in self.graph.nodes:
77 | node.reset()
78 |
79 | for wire in self.graph.wires:
80 | wire.reset()
81 |
82 | def calc_ipc(self):
83 | self.ipc.append(sum([n.in_computation for n in self.graph.nodes]))
84 |
85 | def get_ipc_series(self):
86 | return self.ipc
87 |
88 | def get_end_statistics(self):
89 | # Total cycle count:
90 | total_cycle_count = Simulation.cycle
91 |
92 | # Total energy consumption:
93 | total_energy = sum([n.energy for n in self.graph.nodes])
94 |
95 | # Average utilization percentage:
96 | utilizations = [n.utilization/total_cycle_count for n in self.graph.nodes if n.utilization > 0]
97 | avg_utilization = (sum(utilizations)/len(self.graph.nodes))*100 if len(self.graph.nodes) > 0 else 0
98 |
99 | # Simulator run-time:
100 | runtime = self.end_time - self.start_time
101 |
102 | return (total_cycle_count, total_energy, avg_utilization, runtime)
--------------------------------------------------------------------------------
/coolname/coolname.py:
--------------------------------------------------------------------------------
1 | from coolname.gui import GUI
2 | from coolname.control import Simulation
3 | from coolname.logger import Logger
4 | from coolname.memory import DefaultMemorySimulator
5 |
6 | def main():
7 | my_mem = DefaultMemorySimulator()
8 | my_gui = GUI()
9 | my_logger = Logger(my_gui)
10 | my_sim = Simulation(mem=my_mem, logger=my_logger)
11 |
12 | my_gui.simulation = my_sim
13 | my_gui.build()
14 | my_gui.start()
--------------------------------------------------------------------------------
/coolname/fonts/JetBrainsMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffreyspaan/coolname/367db6afcab933d9dd494a49dbe51c75007fbd9f/coolname/fonts/JetBrainsMono-Regular.ttf
--------------------------------------------------------------------------------
/coolname/fsm.py:
--------------------------------------------------------------------------------
1 | from enum import Enum, IntEnum
2 |
3 | class FSM(Enum):
4 | def next(self):
5 | states = list(self.__class__)
6 | return states[(states.index(self) + 1) % len(states)]
7 |
8 |
9 | class InputFSM(FSM):
10 | NONE = 1
11 | SOME = 2
12 | ALL = 3
13 |
14 |
15 | class OutputFSM(FSM):
16 | FREE = 1
17 | BUSY = 2
18 |
19 |
20 | class DataFSM(FSM):
21 | NONE = 1
22 | INITIATED = 2
23 | COMPLETED = 3
24 | TRANSMITTED = 4
--------------------------------------------------------------------------------
/coolname/gui.py:
--------------------------------------------------------------------------------
1 | from dearpygui.core import *
2 | from dearpygui.simple import *
3 | import os
4 | import json
5 |
6 | from .config import *
7 | from .operator_ import *
8 | from .control import *
9 | from .nodes import *
10 |
11 | class GUI:
12 | def __init__(self):
13 | self.simulation = None
14 | self.animation_ctr = 1
15 |
16 | self.mem_table_rows = 0
17 | self.mem_table_data = []
18 |
19 | def build(self):
20 | set_main_window_size(1650, 915)
21 | set_main_window_title(' simulator')
22 | add_additional_font("coolname/fonts/JetBrainsMono-Regular.ttf", 15)
23 | set_exit_callback(self.stop)
24 |
25 | set_theme('Dark 2')
26 | set_theme_item(mvGuiCol_Text, 235, 235, 235, 230)
27 | set_theme_item(mvGuiCol_Tab, 0, 121, 0, 255)
28 | set_theme_item(mvGuiCol_TabHovered, 0, 175, 0, 255)
29 | set_theme_item(mvGuiCol_TabActive, 0, 175, 0, 255)
30 | set_theme_item(mvGuiCol_ButtonActive, 45, 105, 200, 173)
31 | set_theme_item(mvGuiCol_WindowBg, 23, 23, 38, 240)
32 |
33 |
34 | self.create_config_window()
35 | self.create_memory_window()
36 | self.create_graph_window()
37 | self.create_editor_window()
38 | self.create_control_window()
39 | self.create_logger_window()
40 | self.create_performance_window()
41 |
42 | def start(self):
43 | start_dearpygui(primary_window='graph_window')
44 |
45 | def stop(self, sender, data):
46 | if self.animation_ctr > 1:
47 | os.remove(f'IR{self.animation_ctr-1}.png')
48 |
49 | def reset(self):
50 | # Reset results and log:
51 | clear_log(logger='logger_window##logger')
52 | set_table_item('performance_window##table', 0, 1, '...')
53 | set_table_item('performance_window##table', 1, 1, '...')
54 | set_table_item('performance_window##table', 2, 1, '...')
55 | set_table_item('performance_window##table', 3, 1, '...')
56 | add_stem_series('performance_window##plot', 'IPC', [0.0], [0.0])
57 | set_value('performance_window##ipc_data', '...')
58 |
59 | def create_config_window(self):
60 | with window('config_window', label='Config', x_pos=0, y_pos=0, width=400, height=640):
61 | add_text('Graph')
62 | add_button("config_window##load_ir_button", label='Select IR file', callback=(lambda s, d: open_file_dialog(self.cb_config_load_dot, ".dot,.DOT")))
63 |
64 | add_same_line(spacing=20)
65 | add_text('config_window##count1', default_value='0', color=[0,255,0])
66 | add_same_line(spacing=5)
67 | add_text('blocks')
68 | add_same_line(spacing=20)
69 | add_text('config_window##count2', default_value='0', color=[0,255,0])
70 | add_same_line(spacing=5)
71 | add_text('nodes')
72 | add_same_line(spacing=20)
73 | add_text('config_window##count3', default_value='0', color=[0,255,0])
74 | add_same_line(spacing=5)
75 | add_text('wires')
76 |
77 | add_spacing(count=2)
78 | add_separator()
79 | add_spacing(count=2)
80 |
81 | add_text('Parameters')
82 |
83 | with tab_bar('parameter_tabs'):
84 | with tab('parameter_tab_latency', label='Latency'):
85 | add_text('parameter_tab_latency##group1', default_value='Communication')
86 | with child('parameter_tab_latency##child1', border=True, autosize_x=True, height=90):
87 | add_input_int('parameter_l_com', width=200, min_value=0, default_value=Config.Latency.communication, callback=self.cb_parameter_latency, callback_data='communication', label='wire')
88 | add_input_int('parameter_l_meml', width=200, min_value=0, default_value=Config.Latency.mem_load, callback=self.cb_parameter_latency, callback_data='mem_load', label='Memory load')
89 | add_input_int('parameter_l_mems', width=200, min_value=0, default_value=Config.Latency.mem_store, callback=self.cb_parameter_latency, callback_data='mem_store', label='Memory store')
90 |
91 | add_spacing(count=3)
92 | add_text('parameter_tab_latency##group2', default_value='Operations')
93 | with child('parameter_tab_latency##child2', border=True, autosize_x=True, height=155):
94 |
95 | add_text('parameter_tab_latency##text3', default_value='Latency')
96 | add_same_line(xoffset=210)
97 | add_text('parameter_tab_latency##text4', default_value='Operator')
98 |
99 | add_input_int('parameter_l_plus', width=200, min_value=0, default_value=Config.Latency.computation[Operator.ADD], callback=self.cb_parameter_latency_comp, callback_data=Operator.ADD, label='+ (add)')
100 | add_input_int('parameter_l_sub', width=200, min_value=0, default_value=Config.Latency.computation[Operator.SUB], callback=self.cb_parameter_latency_comp, callback_data=Operator.SUB, label='- (subtract)')
101 | add_input_int('parameter_l_mul', width=200, min_value=0, default_value=Config.Latency.computation[Operator.MUL], callback=self.cb_parameter_latency_comp, callback_data=Operator.MUL, label='* (multiply)')
102 | add_input_int('parameter_l_div', width=200, min_value=0, default_value=Config.Latency.computation[Operator.DIV], callback=self.cb_parameter_latency_comp, callback_data=Operator.DIV, label='/ (divide)')
103 | add_input_int('parameter_l_mod', width=200, min_value=0, default_value=Config.Latency.computation[Operator.MOD], callback=self.cb_parameter_latency_comp, callback_data=Operator.MOD, label='% (modulo)')
104 | add_input_int('parameter_l_lt', width=200, min_value=0, default_value=Config.Latency.computation[Operator.LT], callback=self.cb_parameter_latency_comp, callback_data=Operator.LT, label='< (less than)')
105 | add_input_int('parameter_l_le', width=200, min_value=0, default_value=Config.Latency.computation[Operator.LE], callback=self.cb_parameter_latency_comp, callback_data=Operator.LE, label='<= (less or equal)')
106 | add_input_int('parameter_l_gt', width=200, min_value=0, default_value=Config.Latency.computation[Operator.GT], callback=self.cb_parameter_latency_comp, callback_data=Operator.GT, label='> (greater than)')
107 | add_input_int('parameter_l_ge', width=200, min_value=0, default_value=Config.Latency.computation[Operator.GE], callback=self.cb_parameter_latency_comp, callback_data=Operator.GE, label='>= (greater or equal)')
108 | add_input_int('parameter_l_eq', width=200, min_value=0, default_value=Config.Latency.computation[Operator.EQ], callback=self.cb_parameter_latency_comp, callback_data=Operator.EQ, label='== (equal to)')
109 | add_input_int('parameter_l_ne', width=200, min_value=0, default_value=Config.Latency.computation[Operator.NE], callback=self.cb_parameter_latency_comp, callback_data=Operator.NE, label='!= (not equal to)')
110 | add_input_int('parameter_l_neg', width=200, min_value=0, default_value=Config.Latency.computation[Operator.NEG], callback=self.cb_parameter_latency_comp, callback_data=Operator.NEG, label='- (negation)')
111 | add_input_int('parameter_l_not', width=200, min_value=0, default_value=Config.Latency.computation[Operator.NOT], callback=self.cb_parameter_latency_comp, callback_data=Operator.NOT, label='! (not)')
112 |
113 | add_spacing(count=3)
114 | add_text('parameter_tab_latency##group3', default_value='Nodes')
115 | with child('parameter_tab_latency##child3', border=True, autosize_x=True, height=160):
116 |
117 | add_text('parameter_tab_latency##text5', default_value='Latency')
118 | add_same_line(xoffset=210)
119 | add_text('parameter_tab_latency##text6', default_value='Node')
120 |
121 | add_input_int('parameter_l_eta', width=200, default_value=Config.Latency.eta, callback=self.cb_parameter_latency, callback_data='eta', label='ETA', min_value=0)
122 | add_input_text('parameter_l_mu', width=200, default_value=Config.Latency.mu_str, callback=self.cb_parameter_latency_f, callback_data='mu', label='Mu', tip='n: amount of inputs')
123 | add_input_text('parameter_l_mux', width=200, default_value=Config.Latency.mux_str, callback=self.cb_parameter_latency_f, callback_data='mux', label='Mux', tip='n: amount of inputs')
124 | add_input_text('parameter_l_combine', width=200, default_value=Config.Latency.combine_str, callback=self.cb_parameter_latency_f, callback_data='combine', label='Combine', tip='n: amount of inputs')
125 | add_input_text('parameter_l_xor', width=200, default_value=Config.Latency.xor_str, callback=self.cb_parameter_latency_f, callback_data='xor', label='XOR', tip='n: amount of inputs')
126 |
127 |
128 | with tab('parameter_tab_energy', label='Energy'):
129 | add_text('parameter_tab_energy##group1', default_value='Communication')
130 | with child('parameter_tab_energy##child1', border=True, autosize_x=True, height=90):
131 | add_input_int('parameter_e_com', width=200, min_value=0, default_value=Config.Energy.communication, callback=self.cb_parameter_energy, callback_data='communication', label='wire')
132 | add_input_int('parameter_e_meml', width=200, min_value=0, default_value=Config.Energy.mem_load, callback=self.cb_parameter_energy, callback_data='mem_load', label='Memory load')
133 | add_input_int('parameter_e_mems', width=200, min_value=0, default_value=Config.Energy.mem_store, callback=self.cb_parameter_energy, callback_data='mem_store', label='Memory store')
134 |
135 | add_spacing(count=3)
136 | add_text('parameter_tab_energy##group2', default_value='Operations')
137 | with child('parameter_tab_energy##child2', border=True, autosize_x=True, height=155):
138 |
139 | add_text('parameter_tab_energy##text3', default_value='Energy (pJ)')
140 | add_same_line(xoffset=210)
141 | add_text('parameter_tab_energy##text4', default_value='Operator')
142 |
143 | add_input_int('parameter_e_plus', width=200, min_value=0, default_value=Config.Energy.computation[Operator.ADD], callback=self.cb_parameter_energy_comp, callback_data=Operator.ADD, label='+ (add)')
144 | add_input_int('parameter_e_sub', width=200, min_value=0, default_value=Config.Energy.computation[Operator.SUB], callback=self.cb_parameter_energy_comp, callback_data=Operator.SUB, label='- (subtract)')
145 | add_input_int('parameter_e_mul', width=200, min_value=0, default_value=Config.Energy.computation[Operator.MUL], callback=self.cb_parameter_energy_comp, callback_data=Operator.MUL, label='* (multiply)')
146 | add_input_int('parameter_e_div', width=200, min_value=0, default_value=Config.Energy.computation[Operator.DIV], callback=self.cb_parameter_energy_comp, callback_data=Operator.DIV, label='/ (divide)')
147 | add_input_int('parameter_e_mod', width=200, min_value=0, default_value=Config.Energy.computation[Operator.MOD], callback=self.cb_parameter_energy_comp, callback_data=Operator.MOD, label='% (modulo)')
148 | add_input_int('parameter_e_lt', width=200, min_value=0, default_value=Config.Energy.computation[Operator.LT], callback=self.cb_parameter_energy_comp, callback_data=Operator.LT, label='< (less than)')
149 | add_input_int('parameter_e_le', width=200, min_value=0, default_value=Config.Energy.computation[Operator.LE], callback=self.cb_parameter_energy_comp, callback_data=Operator.LE, label='<= (less or equal)')
150 | add_input_int('parameter_e_gt', width=200, min_value=0, default_value=Config.Energy.computation[Operator.GT], callback=self.cb_parameter_energy_comp, callback_data=Operator.GT, label='> (greater than)')
151 | add_input_int('parameter_e_ge', width=200, min_value=0, default_value=Config.Energy.computation[Operator.GE], callback=self.cb_parameter_energy_comp, callback_data=Operator.GE, label='>= (greater or equal)')
152 | add_input_int('parameter_e_eq', width=200, min_value=0, default_value=Config.Energy.computation[Operator.EQ], callback=self.cb_parameter_energy_comp, callback_data=Operator.EQ, label='== (equal to)')
153 | add_input_int('parameter_e_ne', width=200, min_value=0, default_value=Config.Energy.computation[Operator.NE], callback=self.cb_parameter_energy_comp, callback_data=Operator.NE, label='!= (not equal to)')
154 | add_input_int('parameter_e_neg', width=200, min_value=0, default_value=Config.Energy.computation[Operator.NEG], callback=self.cb_parameter_energy_comp, callback_data=Operator.NEG, label='- (negation)')
155 | add_input_int('parameter_e_not', width=200, min_value=0, default_value=Config.Energy.computation[Operator.NOT], callback=self.cb_parameter_energy_comp, callback_data=Operator.NOT, label='! (not)')
156 |
157 | add_spacing(count=3)
158 | add_text('parameter_tab_energy##group3', default_value='Nodes')
159 | with child('parameter_tab_energy##child3', border=True, autosize_x=True, height=160):
160 |
161 | add_text('parameter_tab_energy##text5', default_value='Energy (pJ)')
162 | add_same_line(xoffset=210)
163 | add_text('parameter_tab_energy##text6', default_value='Node')
164 |
165 | add_input_int('parameter_e_eta', width=200, default_value=Config.Energy.communication, callback=self.cb_parameter_energy, callback_data='eta', label='ETA', min_value=0,)
166 | add_input_text('parameter_e_mu', width=200, default_value=Config.Energy.mu_str, callback=self.cb_parameter_energy_f, callback_data='mu', label='Mu', tip='n: amount of inputs')
167 | add_input_text('parameter_e_mux', width=200, default_value=Config.Energy.mux_str, callback=self.cb_parameter_energy_f, callback_data='mux', label='Mux', tip='n: amount of inputs')
168 | add_input_text('parameter_e_combine', width=200, default_value=Config.Energy.combine_str, callback=self.cb_parameter_energy_f, callback_data='combine', label='Combine', tip='n: amount of inputs')
169 | add_input_text('parameter_e_xor', width=200, default_value=Config.Energy.xor_str, callback=self.cb_parameter_energy_f, callback_data='xor', label='XOR', tip='n: amount of inputs')
170 |
171 | def create_memory_window(self):
172 | with window('memory_window', label='Memory', x_pos=0, y_pos=650, width=400, height=265):
173 | add_button('memory_window##load', label='Load JSON', callback=(lambda s,d: open_file_dialog(self.cb_memory_table_load, ".json,.*")))
174 |
175 | add_same_line(xoffset=200)
176 | add_button('memory_window##save', callback=self.cb_memory_table_save, label='Save state')
177 | add_same_line()
178 | add_button('memory_window##revert', callback=self.cb_memory_table_revert, label='Revert state')
179 |
180 | add_spacing(count=3)
181 |
182 | with child('memory_window##table', border=False, autosize_x=True, height=165):
183 | with managed_columns('memory_window##table_head', 3):
184 | add_text('Identifier')
185 | add_text('Indices')
186 | add_text('Value')
187 |
188 | add_dummy()
189 | add_same_line(spacing=8)
190 | add_button('memory_window##add_row', small=True, callback=self.cb_memory_table_add_row, label='Add row')
191 |
192 | def memory_table_add_row(self, identifier='', indices='', value=''):
193 | configure_item('memory_window', label='Memory (not saved)')
194 |
195 |
196 | self.mem_table_data.append([identifier, indices, value])
197 | row_str = str(self.mem_table_rows)
198 |
199 | with managed_columns(f'memory_window##table_row{row_str}', 3, parent='memory_window##table'):
200 | add_input_text(f"##memory_window##table_row{row_str}_0", callback=self.cb_memory_table_update, default_value=identifier, width=-1)
201 | add_input_text(f"##memory_window##table_row{row_str}_1", callback=self.cb_memory_table_update, default_value=indices, width=-1)
202 | add_input_text(f"##memory_window##table_row{row_str}_2", callback=self.cb_memory_table_update, default_value=value, width=-1)
203 |
204 | self.mem_table_rows += 1
205 |
206 | def cb_memory_table_update(self, sender, data):
207 | configure_item('memory_window', label='Memory (not saved)')
208 |
209 | def cb_memory_table_add_row(self, sender, data):
210 | self.memory_table_add_row()
211 |
212 | def cb_memory_table_load(self, sender, data):
213 | configure_item('memory_window', label='Memory (not saved)')
214 | dir_, file_ = data
215 |
216 | with open(f'{dir_}/{file_}') as f:
217 | # We expect a json array with each memory item an array consisting of
218 | # an identifier, indices (can be []) and a value. For example:
219 | # [a, [], 123]
220 | # [b, [1,2], true]
221 | json_mem = json.load(f)
222 |
223 | for identifier, indices, value in json_mem:
224 | self.log_mem(value, identifier, indices)
225 |
226 | self.cb_memory_table_save(None, None)
227 |
228 |
229 | def cb_memory_table_save(self, sender, data):
230 | try:
231 | for r in range(self.mem_table_rows):
232 | identifier = get_value(f"##memory_window##table_row{r}_0")
233 | indices = get_value(f"##memory_window##table_row{r}_1")
234 | value = get_value(f"##memory_window##table_row{r}_2")
235 |
236 | self.mem_table_data[r][0] = identifier
237 | self.mem_table_data[r][1] = indices
238 | self.mem_table_data[r][2] = value
239 |
240 | # print('save', identifier)
241 | self.simulation.mem.store(eval(value), identifier, eval(indices) if indices else None)
242 |
243 | # print('DUMP')
244 | # print(self.mem_table_data)
245 | # self.simulation.mem.dump()
246 |
247 | configure_item('memory_window', label='Memory (saved)')
248 | except SyntaxError:
249 | log_error('Memory could not be saved (SyntaxError)', logger='logger_window##logger')
250 |
251 | def cb_memory_table_revert(self, sender, data):
252 | configure_item('memory_window', label='Memory (not saved)')
253 |
254 | for r in range(self.mem_table_rows):
255 | set_value(f"##memory_window##table_row{r}_0", self.mem_table_data[r][0])
256 | set_value(f"##memory_window##table_row{r}_1", self.mem_table_data[r][1])
257 | set_value(f"##memory_window##table_row{r}_2", self.mem_table_data[r][2])
258 |
259 |
260 | def log_mem(self, value, identifier, indices=None):
261 | for i,r in enumerate(self.mem_table_data):
262 | if r[0] == identifier:
263 | if indices:
264 | if indices == eval(r[1]):
265 | set_value(f"##memory_window##table_row{i}_2", str(value))
266 | return
267 | else:
268 | set_value(f"##memory_window##table_row{i}_2", str(value))
269 | return
270 |
271 | # Memory table was not updated, so a new entry must be inserted.
272 | self.memory_table_add_row(str(identifier), str(indices) if indices else '', str(value))
273 |
274 | def create_graph_window(self):
275 | with window('graph_window', label='Intermediate Representation'):
276 | add_plot("graph_window##plot", no_legend=True, equal_aspects=True, anti_aliased=True, no_mouse_pos=True, yaxis_no_tick_labels=True, yaxis_no_tick_marks=True, xaxis_no_tick_labels=True, xaxis_no_tick_marks=True, label='Intermediate representation (green=busy, red=computing)')
277 | self.update_graph()
278 |
279 |
280 | def create_editor_window(self):
281 | pass
282 |
283 | def create_control_window(self):
284 | with window('control_window', label='Control', x_pos=1150, y_pos=0, width=500, height=145):
285 |
286 | add_text('Exit condition')
287 |
288 | add_checkbox('control_window##stop_after_check', default_value=False, callback=self.cb_control_stop_after, label='stop after')
289 | add_same_line()
290 | add_input_int('control_window##stop_after_cycles', width=100, min_value=1, default_value=100, callback=self.cb_control_stop_after_cycles, enabled=False, label='cycles')
291 |
292 | add_same_line(spacing=20)
293 | add_checkbox('control_window##animation_check', default_value=True, label='Animate graph')
294 |
295 | add_spacing(count=2)
296 | add_separator()
297 | add_spacing(count=2)
298 |
299 | add_text('Control')
300 |
301 | add_button('control_window_button##run', callback=self.cb_control_run, label='Run')
302 | add_same_line()
303 | add_button('control_window_button##step', callback=self.cb_control_step, label='Step')
304 | add_same_line()
305 | add_button('control_window_button##halt', callback=self.cb_control_halt, label='Halt')
306 | set_item_color('control_window_button##halt', mvGuiCol_Button, [150,0,0])
307 | set_item_color('control_window_button##halt', mvGuiCol_ButtonHovered, [200,0,0])
308 | set_item_color('control_window_button##halt', mvGuiCol_ButtonActive, [255,0,0])
309 | add_same_line()
310 | add_button('control_window_button##reset', callback=self.cb_control_reset, label='Reset')
311 | set_item_color('control_window_button##reset', mvGuiCol_Button, [0,150,0])
312 | set_item_color('control_window_button##reset', mvGuiCol_ButtonHovered, [0,200,0])
313 | set_item_color('control_window_button##reset', mvGuiCol_ButtonActive, [0,255,0])
314 |
315 |
316 | def create_logger_window(self):
317 | with window('logger_window', label='Logging', x_pos=1150, y_pos=155, width=500, height=385):
318 | with group('logger_window##group2'):
319 | add_text('Only show log type ...')
320 | add_same_line()
321 |
322 | logger_help_msg = 'and logs of higher importance'
323 | add_text('(?)'+logger_help_msg, color=[150, 150, 150], default_value='(?)')
324 | add_tooltip('(?)'+logger_help_msg, logger_help_msg + 'tip')
325 | add_text(logger_help_msg)
326 | end()
327 |
328 | add_radio_button('logger_window##log_type', horizontal=True, items=('Trace', 'Debug', 'Info', 'Warning', 'Error', 'Off'), callback=self.cb_logger_type)
329 |
330 | add_spacing(count=2)
331 | add_separator()
332 | add_spacing(count=2)
333 |
334 | add_logger('logger_window##logger', log_level=0, autosize_x=True, height=230, auto_scroll=True)
335 | clear_log(logger='logger_window##logger')
336 |
337 | def create_performance_window(self):
338 | with window('performance_window', label='Performance', x_pos=1150, y_pos=550, width=500, height=365):
339 | add_table('performance_window##table', ['Metric', 'Result'], height=105)
340 | add_row('performance_window##table', ['Total cycle count', '...'])
341 | add_row('performance_window##table', ['Total enery consumption (pJ)', '...'])
342 | add_row('performance_window##table', ['Average utilization (%)', '...'])
343 | add_row('performance_window##table', ['Simulator run-time (s)', '...'])
344 |
345 | add_plot('performance_window##plot', height=190, label='Instructions Per Cycle (IPC)', no_legend=True)
346 |
347 | add_text('Raw:')
348 | add_same_line()
349 | add_input_text('performance_window##ipc_data', width=-2, readonly=True, default_value='...', label='')
350 |
351 | # add_button('performance_window##button', label='Raw IPC data')
352 | # with popup('performance_window##button', 'IPC data##modal', modal=True, mousebutton=0, width=500):
353 | # add_input_text('performance_window##ipc_data', multiline=True, readonly=True, height=20, default_value='...')
354 | # add_button("performance_window##close_button", callback=self.cb_performance_close_modal, label='Close')
355 |
356 | def cb_config_load_dot(self, sender, data):
357 | dir_, file_ = data
358 | self.simulation.graph = IR.from_DOT(f'{dir_}/{file_}')
359 | set_value('config_window##count1', str(len(self.simulation.graph.blocks)-1))
360 | set_value('config_window##count2', str(len(self.simulation.graph.nodes)))
361 | set_value('config_window##count3', str(len(self.simulation.graph.wires)))
362 |
363 | self.reset()
364 | self.update_graph()
365 |
366 | def cb_parameter_latency(self, sender, data):
367 | setattr(Config.Latency, data, int(get_value(sender)))
368 |
369 | def cb_parameter_latency_comp(self, sender, data):
370 | Config.Latency.computation[data] = int(get_value(sender))
371 |
372 | def cb_parameter_latency_f(self, sender, data):
373 | try:
374 | setattr(Config.Latency, data, eval(get_value(sender)))
375 | except SyntaxError:
376 | pass
377 |
378 |
379 | def cb_parameter_energy(self, sender, data):
380 | setattr(Config.Energy, data, int(get_value(sender)))
381 |
382 | def cb_parameter_energy_comp(self, sender, data):
383 | Config.Energy.computation[data] = int(get_value(sender))
384 |
385 | def cb_parameter_energy_f(self, sender, data):
386 | setattr(Config.Energy, data, eval(get_value(sender)))
387 |
388 |
389 |
390 | def cb_control_stop_after(self, sender, data):
391 | if not get_value(sender):
392 | self.simulation.stop_after = None
393 |
394 | configure_item('control_window##stop_after_cycles', enabled=get_value(sender))
395 |
396 | def cb_control_stop_after_cycles(self, sender, data):
397 | self.simulation.stop_after = get_value(sender)
398 |
399 | def cb_control_run(self, sender, data):
400 | if self.simulation.graph is not None:
401 | self.simulation.run()
402 | self.show_statistics()
403 | self.show_IPC()
404 |
405 | def cb_control_step(self, sender, data):
406 | if self.simulation.graph is not None:
407 | self.simulation.step()
408 | self.show_statistics()
409 | self.show_IPC()
410 | self.update_graph()
411 |
412 | def cb_control_halt(self, sender, data):
413 | self.simulation.halt_now = True
414 |
415 | def cb_control_reset(self, sender, data):
416 | if self.simulation.graph is not None:
417 | # Reset GUI (except graph, which depends on the simulator reset)
418 | self.reset()
419 |
420 | # Reset sim:
421 | self.simulation.reset()
422 |
423 | # Reset graph explorer:
424 | self.update_graph()
425 |
426 | def cb_logger_type(self, sender, data):
427 | set_log_level(get_value(sender), logger='logger_window##logger')
428 |
429 | def log(self, cycle, level, msg):
430 | msg = f'[{cycle}] {msg}'
431 |
432 | if level == 'trace':
433 | log(msg, logger='logger_window##logger')
434 | elif level == 'debug':
435 | log_debug(msg, logger='logger_window##logger')
436 | elif level == 'info':
437 | log_info(msg, logger='logger_window##logger')
438 | elif level == 'warning':
439 | log_warning(msg, logger='logger_window##logger')
440 | elif level == 'error':
441 | log_error(msg, logger='logger_window##logger')
442 |
443 |
444 | def cb_performance_close_modal(self, sender, data):
445 | close_popup("IPC data##modal")
446 |
447 | def show_IPC(self):
448 | ipc_series = self.simulation.get_ipc_series()
449 | plot_x = [float(x) for x in range(1,len(ipc_series)+1)]
450 | plot_y = [float(y) for y in ipc_series]
451 |
452 | add_stem_series('performance_window##plot', 'IPC', plot_x, plot_y, update_bounds=True)
453 |
454 | set_value('performance_window##ipc_data', str(ipc_series))
455 |
456 | def show_statistics(self):
457 | (total_cycle_count, total_energy, avg_utilization, runtime) = self.simulation.get_end_statistics()
458 |
459 | set_table_item('performance_window##table', 0, 1, str(total_cycle_count))
460 | set_table_item('performance_window##table', 1, 1, str(total_energy))
461 | set_table_item('performance_window##table', 2, 1, str(avg_utilization))
462 | set_table_item('performance_window##table', 3, 1, str(runtime))
463 |
464 | def update_graph(self):
465 | if get_value('control_window##animation_check'):
466 | filename = self.simulation.graph.to_stylizedPNGfile(f'IR{self.animation_ctr}.png')
467 | series_name = 'graph_window##plot_graph' + str(self.animation_ctr)
468 |
469 | if self.animation_ctr == 1:
470 | add_image_series('graph_window##plot', series_name, filename, bounds_min=[0,0], bounds_max=get_main_window_size())
471 | else:
472 | add_image_series('graph_window##plot', series_name, filename, bounds_min=[0,0], bounds_max=get_main_window_size(), update_bounds=False)
473 | os.remove(f'IR{self.animation_ctr-1}.png')
474 |
475 | self.animation_ctr += 1
476 |
477 |
--------------------------------------------------------------------------------
/coolname/logger.py:
--------------------------------------------------------------------------------
1 | class Logger:
2 |
3 | def __init__(self, gui=None):
4 | self.gui = gui
5 |
6 | def log_inputFSM_transition(self, cycle, node, specific=None):
7 | if specific:
8 | msg = f'[{node.name}] input: {node.input_state.name} -> {specific.name}'
9 | else:
10 | msg = f'[{node.name}] input: {node.input_state.name} -> {node.input_state.next().name}'
11 |
12 | self._report(cycle, 'trace', msg)
13 |
14 | def log_outputFSM_transition(self, cycle, node, specific=None):
15 | if specific:
16 | msg = f'[{node.name}] output: {node.output_state.name} -> {specific.name}'
17 | else:
18 | msg = f'[{node.name}] output: {node.output_state.name} -> {node.output_state.next().name}'
19 |
20 | self._report(cycle, 'trace', msg)
21 |
22 | def log_dataFSM_transition(self, cycle, node, specific=None):
23 | if specific:
24 | msg = f'[{node.name}] data: {node.data_state.name} -> {specific.name}'
25 | else:
26 | msg = f'[{node.name}] data: {node.data_state.name} -> {node.data_state.next().name}'
27 |
28 | self._report(cycle, 'trace', msg)
29 |
30 | def log_send(self, cycle, wire, data):
31 | msg = f'[{wire.input_.name}] sending [{data}] to [{wire.output_.name}] on wire [{wire.name}]'
32 | self._report(cycle, 'debug', msg)
33 |
34 | def log_error(self, cycle, node, error):
35 | msg = f'[{node.name}]: {error}'
36 | self._report(cycle, 'error', msg)
37 |
38 | def _report(self, cycle, level, msg):
39 | if self.gui:
40 | self.gui.log(cycle, level, msg)
41 | else:
42 | print(f'{cycle}| {msg}')
43 |
44 | def log_mem_store(self, value, identifier, indices=None):
45 | if self.gui:
46 | self.gui.log_mem(value, identifier, indices)
47 | else:
48 | print(f'Memory store: {identifier}{indices if indices else ""} = {value}')
--------------------------------------------------------------------------------
/coolname/memory.py:
--------------------------------------------------------------------------------
1 | from .config import *
2 |
3 | class MemorySimulator():
4 | def load(self, addr, indices=None):
5 | """
6 | Must return (value, latency, error) pair.
7 | """
8 | raise NotImplementedError
9 |
10 | def store(self, val, addr, indices=None):
11 | """
12 | Must return (latency, error) pair.
13 | """
14 | raise NotImplementedError
15 |
16 | def dump(self):
17 | """
18 | Outputs all values currently in memory.
19 | """
20 | raise NotImplementedError
21 |
22 |
23 | class DefaultMemorySimulator(MemorySimulator):
24 | def __init__(self):
25 | self.load_latency = Config.Latency.mem_load
26 | self.store_latency = Config.Latency.mem_store
27 | self.load_energy = Config.Energy.mem_load
28 | self.store_energy = Config.Energy.mem_store
29 |
30 | self.memory = dict()
31 |
32 | def load(self, addr, indices=None):
33 | mem_val = self.memory.get(addr)
34 |
35 | if mem_val is None:
36 | return None, None, None, True, 'No value is stored on this address'
37 | elif isinstance(mem_val, dict):
38 | if indices is None:
39 | return None, None, None, True, 'Attempted to get primtive from array, forgot indices?'
40 |
41 | array_val = mem_val.get(tuple(indices))
42 |
43 | if array_val is None:
44 | return None, None, None, True, 'No value is stored on this array element address'
45 |
46 | return array_val, self.load_latency, self.load_energy, False, None
47 | else: # primitive value
48 | if indices:
49 | return None, None, None, True, 'Attempted to get array element from primitive, why indices?'
50 |
51 | return mem_val, self.load_latency, self.load_energy, False, None
52 |
53 | def store(self, val, addr, indices=None):
54 | mem_val = self.memory.get(addr)
55 |
56 | if mem_val is None:
57 | if indices:
58 | self.memory[addr] = dict()
59 | self.memory[addr][tuple(indices)] = val
60 | else:
61 | self.memory[addr] = val
62 |
63 | return self.store_latency, self.store_energy, False, None
64 | elif isinstance(mem_val, dict):
65 | if indices is None:
66 | return None, None, True, 'Attempted to store primtive as array, forgot indices?'
67 |
68 | self.memory[addr][tuple(indices)] = val
69 | return self.store_latency, self.store_energy, False, None
70 | else:
71 | if indices:
72 | return None, None, True, 'Attempted to store array element as primitive, why indices?'
73 |
74 | self.memory[addr] = val
75 | return self.store_latency, self.store_energy, False, None
76 |
77 | print('UNCHARTED WATERS: abort')
78 | exit()
79 |
80 | def dump(self):
81 | print('MEMORY DUMP:')
82 | print()
83 |
84 | for addr, val in self.memory.items():
85 | if isinstance(val, dict):
86 | print(f'\'{addr}\'')
87 | print('type=array')
88 | for arr_indices, arr_val in val.items():
89 | print(f'value{list(arr_indices)}={arr_val}')
90 | else:
91 | print(f'\'{addr}\'')
92 | print('type=primitive')
93 | print(f'value={val}')
94 |
95 | print()
--------------------------------------------------------------------------------
/coolname/nodes.py:
--------------------------------------------------------------------------------
1 | from enum import Enum, IntEnum
2 | import re
3 | import math
4 | import pydot
5 |
6 | from .operator_ import *
7 | from .config import *
8 | from .control import *
9 | from .fsm import *
10 |
11 | class Input:
12 | value_types = IntEnum('Types', 'DATA PREDICATE TOKEN')
13 |
14 | def read(self, consume=True):
15 | raise NotImplementedError
16 |
17 | def send(self, data, latency=None):
18 | raise NotImplementedError
19 |
20 | def acknowledge(self, latency=None):
21 | raise NotImplementedError
22 |
23 | def is_ready(self):
24 | raise NotImplementedError
25 |
26 | def is_acknowledged(self):
27 | raise NotImplementedError
28 |
29 |
30 | class IntegratedConstant(Input):
31 | def __init__(self, data, value_type, name='ICONST'):
32 | self.data = data
33 | self.name = name
34 | self.value_type = value_type
35 |
36 | def read(self, consume=True):
37 | return self.data
38 |
39 | def acknowledge(self, latency=None):
40 | return
41 |
42 | def is_ready(self):
43 | return True
44 |
45 |
46 | class Wire(Input):
47 | def __init__(self, input_, output_, value_type, name='WIRE'):
48 | assert isinstance(input_, Node), 'Input node class is unknown'
49 | self.input_ = input_
50 |
51 | assert isinstance(output_, Node), 'Output node class is unknown'
52 | self.output_ = output_
53 |
54 | input_.add_output(self)
55 | output_.add_input(self)
56 |
57 | self.name = name
58 |
59 | assert isinstance(value_type, Input.value_types), 'Wire value type is unknown'
60 | self.value_type = value_type
61 |
62 | self.data = None
63 | self.data_ready = -1
64 | self.acknowledged = -1
65 |
66 | def reset(self):
67 | self.data = None
68 | self.data_ready = -1
69 | self.acknowledged = -1
70 |
71 | def read(self, consume=True):
72 | data = self.data
73 |
74 | if consume:
75 | self.data = None
76 | self.data_ready = -1
77 |
78 | return data
79 |
80 | def send(self, data, latency=None):
81 | if self.is_ready():
82 | Simulation.logger.log_error(Simulation.cycle, self,
83 | f'cannot send, [{self.data}] already in wire {self.name}: [{self.input_.name}] -> [{self.output_.name}]')
84 | else:
85 | Simulation.logger.log_send(Simulation.cycle, self, data)
86 |
87 | if not latency:
88 | latency = Config.Latency.communication
89 |
90 | self.acknowledged = -1
91 | self.data = data
92 | self.data_ready = Simulation.cycle + latency
93 |
94 | def acknowledge(self, latency=None):
95 | if not latency:
96 | latency = Config.Latency.communication
97 |
98 | self.acknowledged = Simulation.cycle + latency
99 |
100 | def is_ready(self):
101 | return self.data_ready >= 0 and \
102 | self.data_ready <= Simulation.cycle
103 |
104 | def is_acknowledged(self):
105 | return self.acknowledged >= 0 and \
106 | self.acknowledged <= Simulation.cycle
107 |
108 |
109 | class Node:
110 | name = "UNNAMED"
111 |
112 | def __init__(self):
113 | self.inputs = []
114 | self.outputs = []
115 |
116 | # Default FSM states.
117 | self.input_state = InputFSM.NONE
118 | self.output_state = OutputFSM.FREE
119 | self.data_state = DataFSM.NONE
120 |
121 | self.default_data_ready = -1
122 | self.data_ready = self.default_data_ready
123 |
124 | self.energy = 0
125 | self.utilization = 0
126 |
127 | self.busy = False
128 | self.in_computation = False
129 |
130 | @staticmethod
131 | def generate_dummy_data(type_):
132 | if type_ is int:
133 | return 1
134 | if type_ is float:
135 | return 1.0
136 | if type_ is bool:
137 | return True
138 | else:
139 | Simulation.logger.log_error(Simulation.cycle, self,
140 | f'cannot generate dummy value, type [{type_}] is unknown')
141 |
142 | def add_input(self, i):
143 | self.inputs.append(i)
144 |
145 | def add_output(self, o):
146 | self.outputs.append(o)
147 |
148 | def get_data_inputs(self):
149 | return [i for i in self.inputs if i.value_type == Input.value_types.DATA]
150 |
151 | def get_predicate_inputs(self):
152 | return [i for i in self.inputs if i.value_type == Input.value_types.PREDICATE]
153 |
154 | def get_token_input(self):
155 | return [i for i in self.inputs if i.value_type == Input.value_types.TOKEN]
156 |
157 | def get_matching_inputs(self):
158 | matches = []
159 | names = set([i.name for i in self.inputs])
160 |
161 | for name in names:
162 | matches.append(sorted([i for i in self.inputs if i.name == name],
163 | key=lambda i: i.value_type))
164 |
165 | return matches
166 |
167 | def step(self):
168 | self.busy = False
169 | self.in_computation = False
170 |
171 | self.process_inputs()
172 | self.process_outputs()
173 | self.process_data()
174 |
175 | def reset(self):
176 | self.input_state = InputFSM.NONE
177 | self.output_state = OutputFSM.FREE
178 | self.data_state = DataFSM.NONE
179 |
180 | self.busy = False
181 | self.in_computation = False
182 |
183 | self.data_ready = self.default_data_ready
184 |
185 | self.energy = 0
186 | self.utilization = 0
187 |
188 | ################
189 | ## Input FSM ##
190 | ################
191 |
192 | def process_inputs(self):
193 | if self.input_state == InputFSM.NONE:
194 | self.process_inputs_NONE()
195 |
196 | if self.input_state == InputFSM.SOME:
197 | self.process_inputs_SOME()
198 |
199 | def process_inputs_NONE(self):
200 | inputs_ready = [i.is_ready() for i in self.inputs]
201 |
202 | if sum(inputs_ready) > 0:
203 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self)
204 | self.input_state = InputFSM.SOME
205 |
206 | def process_inputs_SOME(self):
207 | inputs_ready = [i.is_ready() for i in self.inputs]
208 |
209 | if all(inputs_ready):
210 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self)
211 | self.input_state = InputFSM.ALL
212 |
213 |
214 | ################
215 | ## Output FSM ##
216 | ################
217 |
218 | def process_outputs(self):
219 | if self.output_state == OutputFSM.BUSY:
220 | self.process_outputs_BUSY()
221 |
222 | def process_outputs_BUSY(self):
223 | if all([o.is_acknowledged() for o in self.outputs]):
224 | Simulation.logger.log_outputFSM_transition(Simulation.cycle, self)
225 | self.output_state = OutputFSM.FREE
226 |
227 | ################
228 | ## Data FSM ##
229 | ################
230 |
231 | def is_busy(self):
232 | return self.busy or self.in_computation
233 |
234 | def data_is_ready(self):
235 | return self.data_ready >= 0 and \
236 | self.data_ready <= Simulation.cycle
237 |
238 | def reset_data_ready(self):
239 | self.data_ready = self.default_data_ready
240 |
241 | def process_data(self):
242 | if self.data_state == DataFSM.NONE:
243 | self.process_data_NONE()
244 |
245 | if self.data_state == DataFSM.INITIATED:
246 | self.process_data_INITIATED()
247 |
248 | if self.data_state == DataFSM.COMPLETED:
249 | self.process_data_COMPLETED()
250 |
251 | if self.data_state == DataFSM.TRANSMITTED:
252 | self.process_data_TRANSMITTED()
253 |
254 | def process_data_NONE(self):
255 | raise NotImplementedError
256 |
257 | def process_data_INITIATED(self):
258 | self.in_computation = True
259 |
260 | if self.data_is_ready():
261 | self.in_computation = False
262 | self.busy = True
263 |
264 | self.reset_data_ready()
265 |
266 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
267 | self.data_state = DataFSM.COMPLETED
268 |
269 | def process_data_COMPLETED(self):
270 | if self.output_state == OutputFSM.FREE:
271 | self.busy = True
272 |
273 | # Transmit the data on all output wires.
274 | for o in self.outputs:
275 | o.send(self.data)
276 |
277 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
278 | self.data_state = DataFSM.TRANSMITTED
279 |
280 | Simulation.logger.log_outputFSM_transition(Simulation.cycle, self)
281 | self.output_state = OutputFSM.BUSY
282 |
283 | def process_data_TRANSMITTED(self):
284 | self.busy = True
285 |
286 | if self.inputs:
287 | # Send acknowledgements to all inputs.
288 | for i in self.inputs:
289 | i.acknowledge()
290 |
291 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self)
292 | self.input_state = InputFSM.NONE
293 |
294 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
295 | self.data_state = DataFSM.NONE
296 |
297 |
298 | class Computation(Node):
299 | ctr = 1
300 |
301 | def __init__(self, operator, type_=None, name=None):
302 | super().__init__()
303 |
304 | if name is None:
305 | self.name = 'COMP' + str(Computation.ctr)
306 | Computation.ctr += 1
307 | else:
308 | self.name = name
309 |
310 | self.operator = operator
311 | self.type_ = type_
312 |
313 | def process_data_NONE(self):
314 | if self.input_state == InputFSM.ALL:
315 | self.busy = True
316 |
317 | pred = self.get_predicate_inputs()[0].read()
318 | data_inputs = {i.name:i.read() for i in self.get_data_inputs()}
319 |
320 | if pred:
321 | self.data = self.operator.compute(data_inputs)
322 | self.data_ready = Simulation.cycle \
323 | + Config.Latency.computation[self.operator]
324 |
325 | self.energy += Config.Energy.computation[self.operator]
326 | self.utilization += Config.Latency.computation[self.operator]
327 | else:
328 | self.data = self.generate_dummy_data(self.type_)
329 | self.data_ready = Simulation.cycle
330 |
331 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
332 | self.data_state = DataFSM.INITIATED
333 |
334 |
335 | class ContinualConstant(Node):
336 | ctr = 1
337 |
338 | def __init__(self, data, name=None):
339 | super().__init__()
340 |
341 | if name is None:
342 | self.name = 'CC' + str(ContinualConstant.ctr)
343 | ContinualConstant.ctr += 1
344 | else:
345 | self.name = name
346 |
347 | self.data = data
348 |
349 | def process_data_NONE(self):
350 | self.busy = True
351 |
352 | # Constants always have zero latency.
353 | self.data_ready = Simulation.cycle
354 |
355 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
356 | self.data_state = DataFSM.INITIATED
357 |
358 |
359 | class OnetimeConstant(Node):
360 | ctr = 1
361 |
362 | def __init__(self, data, name=None):
363 | super().__init__()
364 |
365 | if name is None:
366 | self.name = 'OTC' + str(OnetimeConstant.ctr)
367 | OnetimeConstant.ctr += 1
368 | else:
369 | self.name = name
370 |
371 | self.data = data
372 | self.has_fired = False
373 |
374 | def reset(self):
375 | super().reset()
376 | self.has_fired = False
377 |
378 | def process_data_NONE(self):
379 | if not self.has_fired:
380 | self.has_fired = True
381 | self.busy = True
382 |
383 | # Constants always have zero latency.
384 | self.data_ready = Simulation.cycle
385 |
386 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
387 | self.data_state = DataFSM.INITIATED
388 |
389 |
390 | class Mu(Node):
391 | ctr = 1
392 |
393 | def __init__(self, name=None):
394 | super().__init__()
395 |
396 | if name is None:
397 | self.name = 'MU' + str(Mu.ctr)
398 | Mu.ctr += 1
399 | else:
400 | self.name = name
401 |
402 | self.data = None
403 | self.data_carrying_input = None
404 |
405 | def reset(self):
406 | super().reset()
407 | self.data_carrying_input = None
408 |
409 | def check(self):
410 | inputs_ready = [i.is_ready() for i in self.inputs]
411 | assert sum(inputs_ready) <= 1, 'Mu node "{}" has multiple inputs to choose from'.format(self.name)
412 |
413 | def process_data_NONE(self):
414 | if self.input_state == InputFSM.SOME or \
415 | (self.input_state == InputFSM.ALL and len(self.inputs) == 1):
416 | self.busy = True
417 |
418 | # Determine which input has sent something and read the data.
419 | self.data_carrying_input = None
420 | self.data = None
421 |
422 | for i in self.inputs:
423 | if i.is_ready():
424 | self.data_carrying_input = i
425 | self.data = i.read()
426 |
427 | self.data_ready = Simulation.cycle \
428 | + math.ceil(Config.Latency.mu(len(self.inputs)))
429 |
430 | self.energy += Config.Energy.mu(len(self.inputs))
431 | self.utilization += math.ceil(Config.Latency.mu(len(self.inputs)))
432 |
433 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
434 | self.data_state = DataFSM.INITIATED
435 |
436 | elif self.input_state == InputFSM.ALL and len(self.inputs) > 1:
437 | Simulation.logger.log_error(Simulation.cycle, self,
438 | f'mu [{self.name}] has multiple input values to choose from')
439 |
440 | def process_data_TRANSMITTED(self):
441 | self.busy = True
442 |
443 | # Send acknowledgements to the input which has sent something.
444 | self.data_carrying_input.acknowledge()
445 |
446 | # Note that the input FSM advances to NONE from SOME,
447 | # skipping ALL because if more than one input is ready,
448 | # the graph is incorrect.
449 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self, specific=InputFSM.NONE)
450 | self.input_state = InputFSM.NONE
451 |
452 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
453 | self.data_state = DataFSM.NONE
454 |
455 |
456 | class ETA(Node):
457 | ctr = 1
458 |
459 | def __init__(self, name=None):
460 | super().__init__()
461 |
462 | if name is None:
463 | self.name = 'ETA' + str(ETA.ctr)
464 | ETA.ctr += 1
465 | else:
466 | self.name = name
467 |
468 | self.data = None
469 |
470 | def check(self):
471 | assert len(self.inputs) == 2
472 |
473 | def data_is_ready(self):
474 | return self.data_ready >= 0 and \
475 | self.data_ready <= Simulation.cycle
476 |
477 | def process_data_NONE(self):
478 | if self.input_state == InputFSM.ALL:
479 | self.busy = True
480 |
481 | data = self.get_data_inputs()[0].read()
482 | pred = self.get_predicate_inputs()[0].read()
483 |
484 | if pred:
485 | self.data = data
486 | self.data_ready = Simulation.cycle \
487 | + Config.Latency.eta
488 |
489 | self.energy += Config.Energy.eta
490 | self.utilization += Config.Latency.eta
491 |
492 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
493 | self.data_state = DataFSM.INITIATED
494 | else:
495 | # The predicate is false, so the data must be discarded
496 | # and the inputs acknowledged.
497 | for i in self.inputs:
498 | i.acknowledge()
499 |
500 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self)
501 | self.input_state = InputFSM.NONE
502 |
503 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self, specific=DataFSM.NONE)
504 | self.data_state = DataFSM.NONE
505 |
506 |
507 | class Mux(Node):
508 | ctr = 1
509 |
510 | def __init__(self, name=None):
511 | super().__init__()
512 |
513 | if name is None:
514 | self.name = 'MUX' + str(Mux.ctr)
515 | Mux.ctr += 1
516 | else:
517 | self.name = name
518 |
519 | self.data = None
520 |
521 | def process_data_NONE(self):
522 | if self.input_state != InputFSM.NONE:
523 | for i_data, i_pred in self.get_matching_inputs():
524 | if i_data.is_ready() and i_pred.is_ready():
525 | if i_pred.read(consume=False):
526 | self.busy = True
527 |
528 | self.data = i_data.read(consume=False)
529 | self.data_ready = Simulation.cycle \
530 | + math.ceil(Config.Latency.mux(len(self.inputs)))
531 |
532 | self.energy += Config.Energy.mux(len(self.inputs))
533 | self.utilization += math.ceil(Config.Latency.mux(len(self.inputs)))
534 |
535 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
536 | self.data_state = DataFSM.INITIATED
537 | elif self.input_state == InputFSM.ALL:
538 | pass
539 | # TODO: what to do if all predicates are False: send dummy output? send nothing?
540 |
541 | def process_data_TRANSMITTED(self):
542 | if self.input_state == InputFSM.ALL:
543 | self.busy = True
544 |
545 | # Send acknowledgements to all inputs, which is only done after
546 | # inputs are ready (but might be done x cycles after data is sent).
547 | for i in self.inputs:
548 | # Consume unneeded data.
549 | if i.is_ready():
550 | i.read()
551 |
552 | i.acknowledge()
553 |
554 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self)
555 | self.input_state = InputFSM.NONE
556 |
557 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
558 | self.data_state = DataFSM.NONE
559 |
560 |
561 | class MemoryLoad(Node):
562 | ctr = 1
563 |
564 | def __init__(self, addr, type_, name=None):
565 | super().__init__()
566 |
567 | if name is None:
568 | self.name = 'MEML' + str(MemoryLoad.ctr)
569 | MemoryLoad.ctr += 1
570 | else:
571 | self.name = name
572 |
573 | self.addr = addr
574 | self.type_ = type_
575 | self.data = None
576 |
577 | def process_data_NONE(self):
578 | if self.input_state == InputFSM.ALL:
579 | self.busy = True
580 | indices = []
581 |
582 | if len(self.get_data_inputs()) > 0:
583 | indices_pairs = [(i.name, i.read()) for i in self.get_data_inputs()]
584 | indices = sorted(indices_pairs, key=(lambda a: int(a[0][1:-1:])))
585 | indices = [value for _,value in indices]
586 |
587 | pred = self.get_predicate_inputs()[0].read()
588 |
589 | if pred:
590 | self.data, load_latency, load_energy, error, error_msg = Simulation.mem.load(self.addr, indices=indices)
591 |
592 | if error:
593 | mem_str = self.addr + '[' + ']['.join(map(str,indices)) + ']' if indices else self.addr
594 | Simulation.logger.log_error(Simulation.cycle, self, f'memory load {mem_str} failed: {error_msg}')
595 |
596 | self.data_ready = Simulation.cycle \
597 | + load_latency
598 |
599 | self.energy += load_energy
600 | self.utilization += load_latency
601 | else:
602 | # The predicate is false, so no memory value is retrieved
603 | # and dummy data is used. The data is set to be ready
604 | # this cycle (to immediatly be transmitted).
605 | self.data = self.generate_dummy_data(self.type_)
606 | self.data_ready = Simulation.cycle
607 |
608 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
609 | self.data_state = DataFSM.INITIATED
610 |
611 | def process_data_COMPLETED(self):
612 | if self.output_state == OutputFSM.FREE:
613 | self.busy = True
614 |
615 | # Transmit the data on all output wires.
616 | for o in self.outputs:
617 | if o.value_type == Input.value_types.DATA:
618 | o.send(self.data)
619 | elif o.value_type == Input.value_types.PREDICATE:
620 | o.send(True)
621 |
622 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
623 | self.data_state = DataFSM.TRANSMITTED
624 |
625 | Simulation.logger.log_outputFSM_transition(Simulation.cycle, self)
626 | self.output_state = OutputFSM.BUSY
627 |
628 |
629 | class MemoryStore(Node):
630 | ctr = 1
631 |
632 | def __init__(self, addr, type_=None, name=None):
633 | super().__init__()
634 |
635 | if name is None:
636 | self.name = 'MEMS' + str(MemoryStore.ctr)
637 | MemoryStore.ctr += 1
638 | else:
639 | self.name = name
640 |
641 | self.addr = addr
642 | self.data = None
643 |
644 | def process_data_NONE(self):
645 | if self.input_state == InputFSM.ALL:
646 | self.busy = True
647 | indices_pairs = []
648 | val = None
649 |
650 | for i in self.get_data_inputs():
651 | indice_re = re.findall('\[.*\]', i.name)
652 |
653 | if indice_re:
654 | indices_pairs.append((indice_re[0], i.read()))
655 | else:
656 | val = i.read()
657 |
658 | indices = sorted(indices_pairs, key=(lambda a: a[0]))
659 | indices = [value for _,value in indices]
660 |
661 | pred = self.get_predicate_inputs()[0].read()
662 |
663 | if pred:
664 | Simulation.logger.log_mem_store(val, self.addr, indices)
665 | store_latency, store_energy, error, error_msg = Simulation.mem.store(val, self.addr, indices=indices)
666 |
667 | if error:
668 | mem_str = self.addr + '[' + ']['.join(map(str,indices)) + ']' if indices else self.addr
669 | Simulation.logger.log_error(Simulation.cycle, self, f'memory store {mem_str} failed: {error_msg}')
670 |
671 | self.data = True
672 | self.data_ready = Simulation.cycle \
673 | + store_latency
674 |
675 | self.energy += store_energy
676 | self.utilization += store_latency
677 | else:
678 | self.data = False
679 | self.data_ready = Simulation.cycle
680 |
681 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
682 | self.data_state = DataFSM.INITIATED
683 |
684 |
685 | class Combine(Node):
686 | ctr = 1
687 |
688 | def __init__(self, name=None):
689 | super().__init__()
690 |
691 | if name is None:
692 | self.name = 'COMBINE' + str(Combine.ctr)
693 | Combine.ctr += 1
694 | else:
695 | self.name = name
696 |
697 | self.data = None
698 |
699 | def process_data_NONE(self):
700 | if self.input_state != InputFSM.NONE:
701 | self.busy = True
702 |
703 | ready_input_values = [i.read(consume=False) for i in self.inputs if i.is_ready()]
704 |
705 | if False in ready_input_values:
706 | # If some or all inputs are ready and one or more is False,
707 | # the combine will send a False signal.
708 | self.data = False
709 | elif len(ready_input_values) == len(self.inputs):
710 | # No input has sent a False signal and all inputs are ready,
711 | # so the combine will send a True signal.
712 | self.data = True
713 | else:
714 | # If all inputs are True but not all inputs have arrived, a
715 | # False input might still arrive in the future, thus, we do not
716 | # send a value yet.
717 | return
718 |
719 | self.data_ready = Simulation.cycle \
720 | + math.ceil(Config.Latency.combine(len(self.inputs)))
721 |
722 | self.energy += Config.Energy.combine(len(self.inputs))
723 | self.utilization += math.ceil(Config.Latency.combine(len(self.inputs)))
724 |
725 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
726 | self.data_state = DataFSM.INITIATED
727 |
728 | def process_data_TRANSMITTED(self):
729 | if self.input_state == InputFSM.ALL:
730 | self.busy = True
731 |
732 | # Send acknowledgements to all inputs, which is only done after
733 | # inputs are ready (but might be done x cycles after data is sent).
734 | for i in self.inputs:
735 | # Consume unneeded data.
736 | if i.is_ready():
737 | i.read()
738 |
739 | i.acknowledge()
740 |
741 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self)
742 | self.input_state = InputFSM.NONE
743 |
744 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
745 | self.data_state = DataFSM.NONE
746 |
747 |
748 | class XOR(Node):
749 | ctr = 1
750 |
751 | def __init__(self, name=None):
752 | super().__init__()
753 |
754 | if name is None:
755 | self.name = 'XOR' + str(XOR.ctr)
756 | XOR.ctr += 1
757 | else:
758 | self.name = name
759 |
760 | self.data = None
761 |
762 | def process_data_NONE(self):
763 | if self.input_state != InputFSM.NONE:
764 | self.busy = True
765 |
766 | ready_input_values = [i.read(consume=False) for i in self.inputs if i.is_ready()]
767 |
768 | if True in ready_input_values:
769 | # If some or all inputs are ready and one or more is True, the xor
770 | # will send a True signal.
771 | self.data = True
772 | elif len(ready_input_values) == len(self.inputs):
773 | # No input has sent a True signal and all inputs are ready,
774 | # so the xor will send a False signal.
775 | self.data = False
776 | else:
777 | # If all inputs are False but not all inputs have arrived, a
778 | # False input might still arrive in the future, thus, we do not
779 | # send a value yet.
780 | return
781 |
782 | self.data_ready = Simulation.cycle \
783 | + math.ceil(Config.Latency.xor(len(self.inputs)))
784 |
785 | self.energy += Config.Energy.xor(len(self.inputs))
786 | self.utilization += math.ceil(Config.Latency.xor(len(self.inputs)))
787 |
788 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
789 | self.data_state = DataFSM.INITIATED
790 |
791 | def process_data_TRANSMITTED(self):
792 | if self.input_state == InputFSM.ALL:
793 | self.busy = True
794 |
795 | # Send acknowledgements to all inputs, which is only done after
796 | # inputs are ready (but might be done x cycles after data is sent).
797 | for i in self.inputs:
798 | # Consume unneeded data.
799 | if i.is_ready():
800 | i.read()
801 |
802 | i.acknowledge()
803 |
804 | Simulation.logger.log_inputFSM_transition(Simulation.cycle, self)
805 | self.input_state = InputFSM.NONE
806 |
807 | Simulation.logger.log_dataFSM_transition(Simulation.cycle, self)
808 | self.data_state = DataFSM.NONE
809 |
810 |
811 | class Drain(Node):
812 | def __init__(self, name='DRAIN'):
813 | super().__init__()
814 |
815 | self.name = name
816 |
817 | def process_data(self):
818 | for i in self.inputs:
819 | if i.is_ready():
820 |
821 | print('{} RESULT: {}'.format(self.name, i.read()))
822 | i.acknowledge()
823 |
824 |
825 | class IR:
826 | node_mapping = {
827 | # DOT shape : IR Node
828 | 'box': Computation,
829 | 'doublecircle': OnetimeConstant,
830 | 'circle': ContinualConstant,
831 | 'diamond': Mu,
832 | 'parallelogram': ETA,
833 | 'invtrapezium': Mux,
834 | 'invtriangle': MemoryLoad,
835 | 'triangle': MemoryStore,
836 | 'house': Combine,
837 | 'hexagon': XOR,
838 | 'star': Drain
839 | }
840 |
841 | sign_mapping = {
842 | # IR operator: DOT label
843 | Operator.ADD: '+',
844 | Operator.SUB: '-',
845 | Operator.MUL: '*',
846 | Operator.DIV: '/',
847 | Operator.MOD: '%',
848 | Operator.LT: '\<',
849 | Operator.LE: '\<=',
850 | Operator.GT: '\>',
851 | Operator.GE: '\>=',
852 | Operator.EQ: '==',
853 | Operator.NE: '!=',
854 | Operator.NEG: '-',
855 | Operator.NOT: '!'
856 | }
857 |
858 | operator_mapping = {
859 | # DOT operator: IR operator
860 | 'ADD': Operator.ADD,
861 | 'SUB': Operator.SUB,
862 | 'MUL': Operator.MUL,
863 | 'DIV': Operator.DIV,
864 | 'MOD': Operator.MOD,
865 | 'LT': Operator.LT,
866 | 'LE': Operator.LE,
867 | 'GT': Operator.GT,
868 | 'GE': Operator.GE,
869 | 'EQ': Operator.EQ,
870 | 'NE': Operator.NE,
871 | 'NEG': Operator.NEG,
872 | 'NOT': Operator.NOT
873 | }
874 |
875 | # Removes the need for a pointless eval().
876 | type_mapping = {
877 | # DOT type: IR type
878 | 'int': int,
879 | 'float': float,
880 | 'bool': bool
881 | }
882 |
883 | def __init__(self, blocks=None, wires=None):
884 | # The first block inside the blocks list is the global 'block'.
885 |
886 | self.blocks = blocks
887 | self.nodes = [n for b in blocks for n in b] if blocks else None
888 | self.wires = wires
889 |
890 | @classmethod
891 | def from_DOT(cls, filename):
892 | # Notes:
893 | # All edges must be 'global', in-block edges are not registered.
894 |
895 | a = pydot.graph_from_dot_file(filename)
896 |
897 | DOT_g = pydot.graph_from_dot_file(filename)[0]
898 | g = IR()
899 |
900 | all_nodes = dict()
901 | blocks = []
902 | wires = []
903 |
904 | def strip_quotation(s):
905 | if s:
906 | return s[1:-1] if (s[0] == '"' and s[-1] == '"') else s
907 |
908 | def create_IR_node(DOT_n):
909 | DOT_n_name = strip_quotation(DOT_n.get_name())
910 | DOT_n_label = strip_quotation(DOT_n.get('label'))
911 |
912 | if DOT_n_name == 'node' or DOT_n_name == 'edge' or DOT_n_name == 'graph':
913 | return
914 |
915 | node_kwargs = {}
916 |
917 | if DOT_n_label and \
918 | (cls.node_mapping[DOT_n.get('shape')] is OnetimeConstant or \
919 | cls.node_mapping[DOT_n.get('shape')] is ContinualConstant or \
920 | cls.node_mapping[DOT_n.get('shape')] is MemoryLoad or \
921 | cls.node_mapping[DOT_n.get('shape')] is MemoryStore):
922 |
923 | if DOT_n_label == 'T' or DOT_n_label == 'True' or DOT_n_label == 'true':
924 | # Constant with True value.
925 | node_kwargs['data'] = True
926 | elif DOT_n_label == 'F' or DOT_n_label == 'False' or DOT_n_label == 'false':
927 | # Constant with False value.
928 | node_kwargs['data'] = False
929 | elif DOT_n_label.isidentifier():
930 | # Memory node with address.
931 | node_kwargs['addr'] = DOT_n_label
932 | else:
933 | # Constant with int or float value.
934 | node_kwargs['data'] = eval(DOT_n_label)
935 |
936 | if DOT_n.get('operator'):
937 | node_kwargs['operator'] = cls.operator_mapping[strip_quotation(DOT_n.get('operator'))]
938 |
939 | if DOT_n.get('type'):
940 | node_kwargs['type_'] = cls.type_mapping[strip_quotation(DOT_n.get('type'))]
941 |
942 | n = cls.node_mapping[DOT_n.get('shape')](name=DOT_n_name, **node_kwargs)
943 | return n
944 |
945 | # Add global nodes.
946 | global_nodelist = []
947 |
948 | for DOT_n in DOT_g.get_nodes():
949 | n = create_IR_node(DOT_n)
950 | if n is not None:
951 | all_nodes[n.name] = n
952 | global_nodelist.append(n)
953 |
954 | blocks.append(global_nodelist)
955 |
956 | # Add in-block nodes.
957 | for sg in DOT_g.get_subgraphs():
958 | sg_nodelist = []
959 |
960 | for DOT_n in sg.get_nodes():
961 | n = create_IR_node(DOT_n)
962 | if n is not None:
963 | all_nodes[n.name] = n
964 | sg_nodelist.append(n)
965 |
966 | blocks.append(sg_nodelist)
967 |
968 | # Add wires.
969 | for DOT_w in DOT_g.get_edges():
970 | wire_kwargs = {}
971 |
972 | if DOT_w.get('style') and strip_quotation(DOT_w.get('style')) == 'dotted':
973 | wire_kwargs['value_type'] = Input.value_types.PREDICATE
974 | else:
975 | wire_kwargs['value_type'] = Input.value_types.DATA
976 |
977 | if DOT_w.get('label'):
978 | wire_kwargs['name'] = strip_quotation(DOT_w.get('label'))
979 |
980 | w = Wire(input_=all_nodes[DOT_w.get_source()], output_=all_nodes[DOT_w.get_destination()], **wire_kwargs)
981 | wires.append(w)
982 |
983 | g.nodes = list(all_nodes.values())
984 | g.blocks = blocks
985 | g.wires = wires
986 | return g
987 |
988 | def to_DOT(self, theme='Dark 2'):
989 | def add_node_to_DOT(g, n):
990 | node_kwargs = {}
991 |
992 | if n.is_busy():
993 | if theme == 'Light':
994 | node_kwargs['fillcolor'] = '#aaccf4'
995 | elif theme == 'Dark':
996 | node_kwargs['fillcolor'] = '#009600'
997 | elif theme == 'Dark 2':
998 | node_kwargs['fillcolor'] = '#009600'
999 |
1000 | if n.in_computation:
1001 | # Might override 'busy' color, but is accepted as all
1002 | # 'in computation' nodes are by definition also busy.
1003 | if theme == 'Light':
1004 | node_kwargs['fillcolor'] = '#960000'
1005 | elif theme == 'Dark':
1006 | node_kwargs['fillcolor'] = '#960000'
1007 | elif theme == 'Dark 2':
1008 | node_kwargs['fillcolor'] = '#960000'
1009 |
1010 | if hasattr(n, 'type_') and n.type_ is not None:
1011 | for DOT_type, type_ in self.type_mapping.items():
1012 | if type_ is n.type_:
1013 | node_kwargs['type'] = DOT_type
1014 |
1015 | if isinstance(n, Computation):
1016 | g.add_node(pydot.Node(n.name, label=f'"{n.operator.sign()}"', shape='box', operator=n.operator.name, **node_kwargs))
1017 | elif isinstance(n, OnetimeConstant):
1018 | g.add_node(pydot.Node(n.name, label=(('"T"' if n.data else '"F"') if isinstance(n.data, bool) else str(n.data)), shape='doublecircle', **node_kwargs))
1019 | elif isinstance(n, ContinualConstant):
1020 | g.add_node(pydot.Node(n.name, label=(('"T"' if n.data else '"F"') if isinstance(n.data, bool) else str(n.data)), shape='circle', **node_kwargs))
1021 | elif isinstance(n, Mu):
1022 | g.add_node(pydot.Node(n.name, label='"MU"', shape='diamond', **node_kwargs))
1023 | elif isinstance(n, ETA):
1024 | g.add_node(pydot.Node(n.name, label='"ETA"', shape='parallelogram', **node_kwargs))
1025 | elif isinstance(n, Mux):
1026 | g.add_node(pydot.Node(n.name, label='"MUX"', shape='invtrapezium', **node_kwargs))
1027 | elif isinstance(n, MemoryLoad):
1028 | g.add_node(pydot.Node(n.name, label=f'"{n.addr}"', shape='invtriangle', **node_kwargs))
1029 | elif isinstance(n, MemoryStore):
1030 | g.add_node(pydot.Node(n.name, label=f'"{n.addr}"', shape='triangle', **node_kwargs))
1031 | elif isinstance(n, Combine):
1032 | g.add_node(pydot.Node(n.name, label='"COMBINE"', shape='house', **node_kwargs))
1033 | elif isinstance(n, XOR):
1034 | g.add_node(pydot.Node(n.name, label='"XOR"', shape='hexagon', **node_kwargs))
1035 | else:
1036 | g.add_node(pydot.Node(n.name, label=f'"{n.name}"', shape='star', **node_kwargs))
1037 |
1038 | g = pydot.Dot('IR', graph_type='digraph')
1039 | g.set_graph_defaults(bgcolor='transparent', ratio='0.5545')
1040 |
1041 | if theme == 'Light':
1042 | g.set_node_defaults(fillcolor='#d4f3fd', style='filled', color='#aaccf4')
1043 | if theme == 'Dark':
1044 | g.set_node_defaults(fillcolor='#1d2f49', style='filled', fontcolor='white', color='#aaccf4')
1045 | g.set_edge_defaults(color='white', fontcolor='white')
1046 | if theme == 'Dark 2':
1047 | g.set_node_defaults(fillcolor='#1d2f49', style='filled', fontcolor='white', color='#aaccf4')
1048 | g.set_edge_defaults(color='white', fontcolor='white')
1049 |
1050 |
1051 | # Add global nodes.
1052 | for n in self.blocks[0]:
1053 | add_node_to_DOT(g, n)
1054 |
1055 | # Add in-block nodes.
1056 | cluster_ctr = 1
1057 |
1058 | for b in self.blocks[1:]:
1059 | cluster_ctr += 1
1060 |
1061 | sg = pydot.Subgraph(f'cluster_{str(cluster_ctr)}', color='#aaccf4', penwidth='2')
1062 | g.add_subgraph(sg)
1063 |
1064 | for n in b:
1065 | add_node_to_DOT(sg, n)
1066 |
1067 | # Add wires.
1068 | for w in self.wires:
1069 | wire_kwargs = {}
1070 |
1071 | if w.value_type == Input.value_types.PREDICATE:
1072 | wire_kwargs['style'] = 'dotted'
1073 |
1074 | if w.name != 'WIRE':
1075 | wire_kwargs['label'] = f'"{w.name}"'
1076 |
1077 | g.add_edge(pydot.Edge(w.input_.name, w.output_.name, **wire_kwargs))
1078 |
1079 | return g
1080 |
1081 | def to_DOTfile(self, filename):
1082 | g = self.to_DOT()
1083 | g.write_raw(filename)
1084 |
1085 | def to_stylizedPNGfile(self, filename):
1086 | g = self.to_DOT()
1087 | g.write_png(filename)
1088 |
1089 | return filename
--------------------------------------------------------------------------------
/coolname/operator_.py:
--------------------------------------------------------------------------------
1 | from enum import Enum, IntEnum
2 | import operator
3 |
4 | class Operator(Enum):
5 | # Binary operators:
6 | # Arithmetic operators:
7 | ADD = 1 # +
8 | SUB = 2 # -
9 | MUL = 3 # *
10 | DIV = 4 # /
11 | MOD = 5 # %
12 |
13 | # Relational operators ("and" and "or" ommited):
14 | LT = 6 # <
15 | LE = 7 # <=
16 | GT = 8 # >
17 | GE = 9 # >=
18 | EQ = 10 # ==
19 | NE = 11 # !=
20 |
21 | # Monary operators:
22 | # Arithmetic operators:
23 | NEG = 12 # -
24 |
25 | # Relational operators:
26 | NOT = 13 # !
27 |
28 | def is_binop(self):
29 | return self.value >= Operator.ADD.value and \
30 | self.value <= Operator.NE.value
31 |
32 | def is_monop(self):
33 | return self.value == Operator.NOT.value or \
34 | self.value == Operator.NEG.value
35 |
36 | def is_arithmetic(self):
37 | return (self.value >= Operator.ADD.value and \
38 | self.value <= Operator.MOD.value) or \
39 | (self.value == Operator.NEG.value)
40 |
41 | def is_relational(self):
42 | return (self.value >= Operator.LT.value and \
43 | self.value <= Operator.NE.value) or \
44 | (self.value == Operator.NOT.value)
45 |
46 | def sign(self):
47 | if self.value == Operator.ADD.value: return '+'
48 | elif self.value == Operator.SUB.value: return '-'
49 | elif self.value == Operator.MUL.value: return '*'
50 | elif self.value == Operator.DIV.value: return '/'
51 | elif self.value == Operator.MOD.value: return '%'
52 | elif self.value == Operator.LT.value: return '\<'
53 | elif self.value == Operator.LE.value: return '\<='
54 | elif self.value == Operator.GT.value: return '\>'
55 | elif self.value == Operator.GE.value: return '\>='
56 | elif self.value == Operator.EQ.value: return '=='
57 | elif self.value == Operator.NE.value: return '!='
58 | elif self.value == Operator.NEG.value: return '-'
59 | elif self.value == Operator.NOT.value: return '!'
60 |
61 | def fun(self):
62 | # TODO: differentiate between / and //
63 | if self.value == Operator.ADD.value: return operator.add
64 | elif self.value == Operator.SUB.value: return operator.sub
65 | elif self.value == Operator.MUL.value: return operator.mul
66 | elif self.value == Operator.DIV.value: return operator.truediv
67 | elif self.value == Operator.MOD.value: return operator.mod
68 | elif self.value == Operator.LT.value: return operator.lt
69 | elif self.value == Operator.LE.value: return operator.le
70 | elif self.value == Operator.GT.value: return operator.gt
71 | elif self.value == Operator.GE.value: return operator.ge
72 | elif self.value == Operator.EQ.value: return operator.eq
73 | elif self.value == Operator.NE.value: return operator.ne
74 | elif self.value == Operator.NEG.value: return operator.neg
75 | elif self.value == Operator.NOT.value: return operator.not_
76 |
77 | def compute(self, inputs):
78 | """
79 | Expects inputs in the form:
80 | {'LHS': 0, 'RHS':1}
81 | {''}
82 | """
83 |
84 | if self.is_monop():
85 | if len(inputs) == 1:
86 | return self.fun()(list(inputs.values())[0])
87 | else:
88 | pass
89 | # TODO: log error
90 |
91 | elif self.is_binop():
92 | if len(inputs) == 2 and 'LHS' in inputs and 'RHS' in inputs:
93 | LHS = inputs.get('LHS')
94 | RHS = inputs.get('RHS')
95 |
96 | if type(LHS) is not type(RHS):
97 | pass
98 | # TODO: log error
99 |
100 | return self.fun()(LHS, RHS)
101 | else:
102 | pass
103 | # TODO: log error
104 |
--------------------------------------------------------------------------------
/coolname/sample_ir.py:
--------------------------------------------------------------------------------
1 | from nodes import *
2 |
3 | # Triangular matrix multiplication IR graphs for atomic and speculative
4 | # mode of execution. Should be similar to the DOT representation in /data.
5 |
6 | def test_trmm_atomic():
7 | # entry
8 | e_oc1 = OnetimeConstant(True, name='E_OC1')
9 |
10 | e_oc2 = OnetimeConstant(1, name='E_OC2')
11 | e_oc3 = OnetimeConstant(0, name='E_OC3') # i
12 | e_oc4 = OnetimeConstant(0, name='E_OC4') # j
13 |
14 | e_comp1 = Computation(Operator.ADD, name='E_COMP1') # k
15 |
16 | e_w1 = Wire(e_oc2, e_comp1, Input.value_types.DATA, name='RHS')
17 | e_w2 = Wire(e_oc3, e_comp1, Input.value_types.DATA, name='LHS')
18 |
19 | # for_body
20 | fb_ml1 = MemoryLoad('n', int, name='FB_ML1')
21 | fb_comb1 = Combine(name='FB_COMB1')
22 | fb_comp1 = Computation(Operator.LT, type_=int, name='FB_COMP1')
23 | fb_comp2 = Computation(Operator.NOT, type_=bool, name='FB_COMP2')
24 | fb_eta1 = ETA(name='FB_ETA1')
25 | fb_eta2 = ETA(name='FB_ETA2')
26 |
27 | fb_w1 = Wire(fb_ml1, fb_comb1, Input.value_types.PREDICATE)
28 | fb_w2 = Wire(fb_ml1, fb_comp1, Input.value_types.DATA, name='RHS')
29 |
30 | fb_w3 = Wire(fb_comb1, fb_eta2, Input.value_types.DATA)
31 | fb_w4 = Wire(fb_comb1, fb_eta1, Input.value_types.DATA)
32 | fb_w5 = Wire(fb_comp1, fb_comp2, Input.value_types.DATA)
33 | fb_w6 = Wire(fb_comp1, fb_eta1, Input.value_types.PREDICATE)
34 | fb_w7 = Wire(fb_comp2, fb_eta2, Input.value_types.PREDICATE)
35 |
36 | # if_else_36
37 | ie36_cc1 = ContinualConstant(1, name='IE36_CC1')
38 | ie36_cc2 = ContinualConstant(1, name='IE36_CC2')
39 | ie36_cc3 = ContinualConstant(0, name='IE36_CC3')
40 | ie36_comp1 = Computation(Operator.ADD, type_=int, name='IE36_COMP1')
41 | ie36_comp2 = Computation(Operator.ADD, type_=int, name='IE36_COMP2')
42 | ie36_eta1 = ETA(name='IE36_ETA1')
43 |
44 | ie36_w1 = Wire(ie36_cc1, ie36_comp1, Input.value_types.DATA, name='RHS')
45 | ie36_w2 = Wire(ie36_comp2, ie36_comp1, Input.value_types.DATA, name='LHS')
46 |
47 | ie36_w3 = Wire(ie36_cc2, ie36_comp2, Input.value_types.DATA, name='RHS')
48 | ie36_w4 = Wire(ie36_cc3, ie36_eta1, Input.value_types.DATA)
49 |
50 | # if_then
51 | it_ml1 = MemoryLoad('m', int, name='IT_ML1')
52 | it_comb1 = Combine(name='IT_COMB1')
53 | it_comp1 = Computation(Operator.LT, type_=int, name='IT_COMP1')
54 | it_comp2 = Computation(Operator.NOT, type_=int, name='IT_COMP2')
55 | it_eta1 = ETA(name='IT_ETA1')
56 | it_eta2 = ETA(name='IT_ETA2')
57 |
58 | it_w1 = Wire(it_ml1, it_comb1, Input.value_types.PREDICATE)
59 | it_w2 = Wire(it_ml1, it_comp1, Input.value_types.DATA, name='RHS')
60 |
61 | it_w3 = Wire(it_comb1, it_eta1, Input.value_types.DATA)
62 | it_w4 = Wire(it_comb1, it_eta2, Input.value_types.DATA)
63 |
64 | it_w5 = Wire(it_comp1, it_eta1, Input.value_types.PREDICATE)
65 | it_w6 = Wire(it_comp1, it_comp2, Input.value_types.DATA)
66 |
67 | it_w7 = Wire(it_comp2, it_eta2, Input.value_types.PREDICATE)
68 |
69 | # if_then12
70 | it12_cc1 = ContinualConstant(1, name='IT12_CC1')
71 | it12_comp1 = Computation(Operator.ADD, type_=int, name='IT12_COMP1')
72 | it12_comp2 = Computation(Operator.MUL, type_=int, name='IT12_COMP2')
73 | it12_comp3 = Computation(Operator.ADD, type_=int, name='IT12_COMP3')
74 | it12_eta1 = ETA(name='IT12_ETA1')
75 | it12_eta2 = ETA(name='IT12_ETA2')
76 | it12_ml1 = MemoryLoad('A', type_=int, name='IT12_ML1')
77 | it12_ml2 = MemoryLoad('B', type_=int, name='IT12_ML2')
78 | it12_ml3 = MemoryLoad('B', type_=int, name='IT12_ML3')
79 | it12_ms1 = MemoryStore('B', type_=int, name='IT12_MS1')
80 | it12_comb1 = Combine(name='IT12_COMB1')
81 |
82 | it12_w1 = Wire(it12_cc1, it12_comp1, Input.value_types.DATA, name='RHS')
83 |
84 | it12_w2 = Wire(it12_ml1, it12_comp2, Input.value_types.DATA, name='LHS')
85 | it12_w3 = Wire(it12_ml1, it12_comb1, Input.value_types.PREDICATE)
86 |
87 | it12_w4 = Wire(it12_ml2, it12_comb1, Input.value_types.PREDICATE)
88 | it12_w5 = Wire(it12_ml2, it12_comp2, Input.value_types.DATA, name='RHS')
89 |
90 | it12_w6 = Wire(it12_comp2, it12_comp3, Input.value_types.DATA, name='RHS')
91 |
92 | it12_w7 = Wire(it12_ml3, it12_comp3, Input.value_types.DATA, name='LHS')
93 | it12_w8 = Wire(it12_ml3, it12_comb1, Input.value_types.PREDICATE)
94 |
95 | it12_w9 = Wire(it12_comp3, it12_ms1, Input.value_types.DATA)
96 |
97 | it12_w10 = Wire(it12_ms1, it12_comb1, Input.value_types.PREDICATE)
98 |
99 | # if_else
100 | ie_cc1 = ContinualConstant(1, name='IE_CC1')
101 | ie_cc2 = ContinualConstant(1, name='IE_CC2')
102 | ie_ml1 = MemoryLoad('alpha', type_=int, name='IE_ML1')
103 | ie_ml2 = MemoryLoad('B', type_=int, name='IE_ML2')
104 | ie_eta1 = ETA(name='IE_ETA1')
105 | ie_comp1 = Computation(Operator.ADD, type_=int, name='IE_COMP1')
106 | ie_comp2 = Computation(Operator.ADD, type_=int, name='IE_COMP2')
107 | ie_comp3 = Computation(Operator.MUL, type_=int, name='IE_COMP3')
108 | ie_ms1 = MemoryStore('B', type_=int, name='IE_MS1')
109 | ie_comb1 = Combine(name='IE_COMB1')
110 |
111 | ie_w1 = Wire(ie_cc1, ie_comp1, Input.value_types.DATA, name='RHS')
112 | ie_w2 = Wire(ie_cc2, ie_comp2, Input.value_types.DATA, name='RHS')
113 |
114 | ie_w3 = Wire(ie_ml1, ie_comp3, Input.value_types.DATA, name='LHS')
115 | ie_w4 = Wire(ie_ml1, ie_comb1, Input.value_types.PREDICATE)
116 |
117 | ie_w5 = Wire(ie_ml2, ie_comp3, Input.value_types.DATA, name='RHS')
118 | ie_w6 = Wire(ie_ml2, ie_comb1, Input.value_types.PREDICATE)
119 |
120 | ie_w7 = Wire(ie_comp3, ie_ms1, Input.value_types.DATA)
121 |
122 | ie_w8 = Wire(ie_ms1, ie_comb1, Input.value_types.PREDICATE)
123 |
124 | # final
125 | f_mu1 = Mu(name='F_MU1')
126 | f_mu2 = Mu(name='F_MU2')
127 | f_mu3 = Mu(name='F_MU3')
128 | f_mu4 = Mu(name='F_MU4')
129 | f_ms1 = MemoryStore('k', type_=int, name='F_MS1')
130 | f_ms2 = MemoryStore('i', type_=int, name='F_MS2')
131 | f_ms3 = MemoryStore('j', type_=int, name='F_MS3')
132 |
133 | f_w1 = Wire(f_mu1, f_ms1, Input.value_types.DATA) # k
134 | f_w2 = Wire(f_mu2, f_ms2, Input.value_types.DATA) # i
135 | f_w3 = Wire(f_mu4, f_ms3, Input.value_types.DATA) # j
136 |
137 | f_w4 = Wire(f_mu3, f_ms1, Input.value_types.PREDICATE)
138 | f_w5 = Wire(f_mu3, f_ms2, Input.value_types.PREDICATE)
139 | f_w6 = Wire(f_mu3, f_ms3, Input.value_types.PREDICATE)
140 |
141 | ################
142 | # Global wires #
143 | ################
144 |
145 | # g -> entry
146 | g_w1 = Wire(e_oc1, e_comp1, Input.value_types.PREDICATE)
147 |
148 | # g -> for_body
149 | g_w2 = Wire(e_oc1, fb_ml1, Input.value_types.PREDICATE)
150 | g_w3 = Wire(e_oc1, fb_comp1, Input.value_types.PREDICATE)
151 | g_w4 = Wire(e_oc1, fb_comp2, Input.value_types.PREDICATE)
152 |
153 | # entry -> for_body
154 | g_w5 = Wire(e_oc4, fb_comp1, Input.value_types.DATA, name='LHS')
155 |
156 | # entry -> if_else36
157 | g_w6 = Wire(e_oc3, ie36_comp2, Input.value_types.DATA, name='LHS')
158 |
159 | # for_body -> if_else36
160 | g_w7 = Wire(fb_eta2, ie36_comp1, Input.value_types.PREDICATE)
161 | g_w8 = Wire(fb_eta2, ie36_comp2, Input.value_types.PREDICATE)
162 | g_w9 = Wire(fb_eta2, ie36_eta1, Input.value_types.PREDICATE)
163 |
164 | # entry -> if_then
165 | g_w10 = Wire(e_comp1, it_comp1, Input.value_types.DATA, name='LHS')
166 |
167 | # for_body -> if_then
168 | g_w11 = Wire(fb_eta1, it_ml1, Input.value_types.PREDICATE)
169 | g_w12 = Wire(fb_eta1, it_comp1, Input.value_types.PREDICATE)
170 | g_w13 = Wire(fb_eta1, it_comp2, Input.value_types.PREDICATE)
171 |
172 | # entry -> if_then12
173 | g_w14 = Wire(e_oc3, it12_eta1, Input.value_types.DATA)
174 | g_w15 = Wire(e_oc3, it12_ml1, Input.value_types.DATA, name='[1]')
175 | g_w16 = Wire(e_oc3, it12_ml3, Input.value_types.DATA, name='[0]')
176 | g_w17 = Wire(e_oc3, it12_ms1, Input.value_types.DATA, name='[0]')
177 |
178 | g_w18 = Wire(e_oc4, it12_eta2, Input.value_types.DATA)
179 | g_w19 = Wire(e_oc4, it12_ml2, Input.value_types.DATA, name='[1]')
180 | g_w20 = Wire(e_oc4, it12_ml3, Input.value_types.DATA, name='[1]')
181 | g_w21 = Wire(e_oc4, it12_ms1, Input.value_types.DATA, name='[1]')
182 |
183 | g_w22 = Wire(e_comp1, it12_comp1, Input.value_types.DATA, name='LHS')
184 | g_w23 = Wire(e_comp1, it12_ml1, Input.value_types.DATA, name='[0]')
185 | g_w24 = Wire(e_comp1, it12_ml2, Input.value_types.DATA, name='[0]')
186 |
187 | # if_then -> if_then12
188 | g_w25 = Wire(it_eta1, it12_comp1, Input.value_types.PREDICATE)
189 | g_w26 = Wire(it_eta1, it12_eta1, Input.value_types.PREDICATE)
190 | g_w27 = Wire(it_eta1, it12_ml1, Input.value_types.PREDICATE)
191 | g_w28 = Wire(it_eta1, it12_eta2, Input.value_types.PREDICATE)
192 | g_w29 = Wire(it_eta1, it12_ml2, Input.value_types.PREDICATE)
193 | g_w30 = Wire(it_eta1, it12_comp2, Input.value_types.PREDICATE)
194 | g_w31 = Wire(it_eta1, it12_ml3, Input.value_types.PREDICATE)
195 | g_w32 = Wire(it_eta1, it12_comp3, Input.value_types.PREDICATE)
196 | g_w33 = Wire(it_eta1, it12_ms1, Input.value_types.PREDICATE)
197 |
198 | # entry -> if_else
199 | g_w34 = Wire(e_oc3, ie_ml2, Input.value_types.DATA, name='[0]')
200 | g_w35 = Wire(e_oc3, ie_eta1, Input.value_types.DATA)
201 | g_w36 = Wire(e_oc3, ie_comp1, Input.value_types.DATA, name='LHS')
202 | g_w37 = Wire(e_oc3, ie_ms1, Input.value_types.DATA, name='[0]')
203 |
204 | g_w38 = Wire(e_oc4, ie_ml2, Input.value_types.DATA, name='[1]')
205 | g_w39 = Wire(e_oc4, ie_comp2, Input.value_types.DATA, name='LHS')
206 | g_w40 = Wire(e_oc4, ie_ms1, Input.value_types.DATA, name='[1]')
207 |
208 | # if_then -> if_else
209 | g_w41 = Wire(it_eta2, ie_ml1, Input.value_types.PREDICATE)
210 | g_w42 = Wire(it_eta2, ie_ml2, Input.value_types.PREDICATE)
211 | g_w43 = Wire(it_eta2, ie_eta1, Input.value_types.PREDICATE)
212 | g_w44 = Wire(it_eta2, ie_comp1, Input.value_types.PREDICATE)
213 | g_w45 = Wire(it_eta2, ie_comp2, Input.value_types.PREDICATE)
214 | g_w46 = Wire(it_eta2, ie_comp3, Input.value_types.PREDICATE)
215 | g_w47 = Wire(it_eta2, ie_ms1, Input.value_types.PREDICATE)
216 |
217 | # for_body -> final
218 | g_w48 = Wire(fb_eta2, f_mu3, Input.value_types.PREDICATE)
219 |
220 | # if_else_36 -> final
221 | g_w49 = Wire(ie36_comp1, f_mu1, Input.value_types.DATA)
222 | g_w50 = Wire(ie36_comp2, f_mu2, Input.value_types.DATA)
223 | g_w51 = Wire(ie36_eta1, f_mu4, Input.value_types.DATA)
224 |
225 | # if_then12 -> final
226 | g_w52 = Wire(it12_comp1, f_mu1, Input.value_types.DATA)
227 | g_w53 = Wire(it12_eta1, f_mu2, Input.value_types.DATA)
228 | g_w54 = Wire(it12_comb1, f_mu3, Input.value_types.PREDICATE)
229 | g_w55 = Wire(it12_eta2, f_mu4, Input.value_types.DATA)
230 |
231 | # if_else -> final
232 | g_w56 = Wire(ie_comp1, f_mu1, Input.value_types.DATA)
233 | g_w57 = Wire(ie_eta1, f_mu2, Input.value_types.DATA)
234 | g_w58 = Wire(ie_comb1, f_mu3, Input.value_types.PREDICATE)
235 | g_w59 = Wire(ie_comp2, f_mu4, Input.value_types.DATA)
236 |
237 | return IR([[e_oc1],
238 | [e_oc2, e_oc3, e_oc4, e_comp1],
239 | [fb_ml1, fb_comb1, fb_comp1, fb_comp2, fb_eta1, fb_eta2],
240 | [ie36_cc1, ie36_cc2, ie36_cc3, ie36_comp1, ie36_comp2, ie36_eta1],
241 | [it_ml1, it_comb1, it_comp1, it_comp2, it_eta1, it_eta2],
242 | [it12_cc1, it12_comp1, it12_comp2, it12_comp3, it12_eta1, it12_eta2, it12_ml1, it12_ml2, it12_ml3, it12_ms1, it12_comb1],
243 | [ie_cc1, ie_cc2, ie_ml1, ie_ml2, ie_eta1, ie_comp1, ie_comp2, ie_comp3, ie_ms1, ie_comb1],
244 | [f_mu1, f_mu2, f_mu3, f_mu4, f_ms1, f_ms2, f_ms3]],
245 | [e_w1, e_w2,
246 | fb_w1, fb_w2, fb_w3, fb_w4, fb_w5, fb_w6, fb_w7,
247 | ie36_w1, ie36_w2, ie36_w3, ie36_w4,
248 | it_w1, it_w2, it_w3, it_w4, it_w5, it_w6, it_w7,
249 | it12_w1, it12_w2, it12_w3, it12_w4, it12_w5, it12_w6, it12_w7, it12_w8, it12_w9, it12_w10,
250 | ie_w1, ie_w2, ie_w3, ie_w4, ie_w5, ie_w6, ie_w7, ie_w8,
251 | f_w1, f_w2, f_w3, f_w4, f_w5, f_w6,
252 | g_w1, g_w2, g_w3, g_w4, g_w5, g_w6, g_w7, g_w8, g_w9, g_w10, g_w11, g_w12, g_w13, g_w14, g_w15, g_w16, g_w17, g_w18, g_w19, g_w20, g_w21, g_w22, g_w23, g_w24, g_w25, g_w26, g_w27, g_w28, g_w29, g_w30, g_w31, g_w32, g_w33, g_w34, g_w35, g_w36, g_w37, g_w38, g_w39, g_w40, g_w41, g_w42, g_w43, g_w44, g_w45, g_w46, g_w47, g_w48, g_w49, g_w50, g_w51, g_w52, g_w53,g_w54,g_w55,g_w56,g_w57,g_w58,g_w59])
253 |
254 | def test_trmm_speculated():
255 | # entry
256 | e_oc1 = OnetimeConstant(True, name='E_OC1')
257 | e_oc2 = OnetimeConstant(1, name='E_OC2')
258 | e_oc3 = OnetimeConstant(0, name='E_OC3') # i
259 | e_oc4 = OnetimeConstant(0, name='E_OC4') # j
260 | e_comp1 = Computation(Operator.ADD, name='E_COMP1') # k
261 |
262 | e_w1 = Wire(e_oc2, e_comp1, Input.value_types.DATA, name='RHS')
263 | e_w2 = Wire(e_oc3, e_comp1, Input.value_types.DATA, name='LHS')
264 |
265 | # for_body
266 | fb_cc1 = ContinualConstant(True, name='FB_CC1')
267 | fb_ml1 = MemoryLoad('n', int, name='FB_ML1')
268 | fb_comb1 = Combine(name='FB_COMB1')
269 | fb_comb2 = Combine(name='FB_COMB2')
270 | fb_comb3 = Combine(name='FB_COMB3')
271 | fb_comp1 = Computation(Operator.LT, type_=int, name='FB_COMP1')
272 | fb_comp2 = Computation(Operator.NOT, type_=bool, name='FB_COMP2')
273 |
274 | fb_w1 = Wire(fb_ml1, fb_comb1, Input.value_types.PREDICATE)
275 | fb_w2 = Wire(fb_ml1, fb_comp1, Input.value_types.DATA, name='RHS')
276 |
277 | fb_w3 = Wire(fb_comb1, fb_comb3, Input.value_types.DATA)
278 | fb_w4 = Wire(fb_comb1, fb_comb2, Input.value_types.DATA)
279 | fb_w5 = Wire(fb_comp1, fb_comp2, Input.value_types.DATA)
280 | fb_w6 = Wire(fb_comp1, fb_comb2, Input.value_types.DATA)
281 | fb_w7 = Wire(fb_comp2, fb_comb3, Input.value_types.DATA)
282 |
283 | fb_w8 = Wire(fb_cc1, fb_comp1, Input.value_types.PREDICATE)
284 | fb_w9 = Wire(fb_cc1, fb_comp2, Input.value_types.PREDICATE)
285 |
286 | # if_else_36
287 | ie36_cc1 = ContinualConstant(1, name='IE36_CC1')
288 | ie36_cc2 = ContinualConstant(1, name='IE36_CC2')
289 | ie36_cc3 = ContinualConstant(0, name='IE36_CC3')
290 | ie36_cc4 = ContinualConstant(True, name='IE36_CC4')
291 | ie36_comp1 = Computation(Operator.ADD, type_=int, name='IE36_COMP1')
292 | ie36_comp2 = Computation(Operator.ADD, type_=int, name='IE36_COMP2')
293 |
294 | ie36_w1 = Wire(ie36_cc1, ie36_comp1, Input.value_types.DATA, name='RHS')
295 | ie36_w2 = Wire(ie36_comp1, ie36_comp2, Input.value_types.DATA, name='LHS')
296 | ie36_w3 = Wire(ie36_cc2, ie36_comp2, Input.value_types.DATA, name='RHS')
297 |
298 | ie36_w4 = Wire(ie36_cc4, ie36_comp1, Input.value_types.PREDICATE)
299 | ie36_w5 = Wire(ie36_cc4, ie36_comp2, Input.value_types.PREDICATE)
300 |
301 | # if_then
302 | it_cc1 = ContinualConstant(True, name='IT_CC1')
303 | it_ml1 = MemoryLoad('m', int, name='IT_ML1')
304 | it_comb1 = Combine(name='IT_COMB1')
305 | it_comb2 = Combine(name='IT_COMB2')
306 | it_comb3 = Combine(name='IT_COMB3')
307 | it_comp1 = Computation(Operator.LT, type_=int, name='IT_COMP1')
308 | it_comp2 = Computation(Operator.NOT, type_=int, name='IT_COMP2')
309 |
310 | it_w1 = Wire(it_ml1, it_comb1, Input.value_types.PREDICATE)
311 | it_w2 = Wire(it_ml1, it_comp1, Input.value_types.DATA, name='RHS')
312 |
313 | it_w3 = Wire(it_comb1, it_comb2, Input.value_types.DATA)
314 | it_w4 = Wire(it_comb1, it_comb3, Input.value_types.DATA)
315 |
316 | it_w5 = Wire(it_comp1, it_comb2, Input.value_types.DATA)
317 | it_w6 = Wire(it_comp1, it_comp2, Input.value_types.DATA)
318 |
319 | it_w7 = Wire(it_comp2, it_comb3, Input.value_types.DATA)
320 |
321 | it_w8 = Wire(it_cc1, it_comp1, Input.value_types.PREDICATE)
322 | it_w9 = Wire(it_cc1, it_comp2, Input.value_types.PREDICATE)
323 |
324 | # if_then12
325 | it12_cc1 = ContinualConstant(1, name='IT12_CC1')
326 | it12_cc2 = ContinualConstant(True, name='IT12_CC2')
327 | it12_comp1 = Computation(Operator.ADD, type_=int, name='IT12_COMP1')
328 | it12_comp2 = Computation(Operator.MUL, type_=int, name='IT12_COMP2')
329 | it12_comp3 = Computation(Operator.ADD, type_=int, name='IT12_COMP3')
330 | it12_ml1 = MemoryLoad('A', type_=int, name='IT12_ML1')
331 | it12_ml2 = MemoryLoad('B', type_=int, name='IT12_ML2')
332 | it12_ml3 = MemoryLoad('B', type_=int, name='IT12_ML3')
333 | it12_ms1 = MemoryStore('B', type_=int, name='IT12_MS1')
334 | it12_comb1 = Combine(name='IT12_COMB1')
335 |
336 | it12_w1 = Wire(it12_cc1, it12_comp1, Input.value_types.DATA, name='RHS')
337 |
338 | it12_w2 = Wire(it12_ml1, it12_comp2, Input.value_types.DATA, name='LHS')
339 | it12_w3 = Wire(it12_ml1, it12_comb1, Input.value_types.PREDICATE)
340 |
341 | it12_w4 = Wire(it12_ml2, it12_comb1, Input.value_types.PREDICATE)
342 | it12_w5 = Wire(it12_ml2, it12_comp2, Input.value_types.DATA, name='RHS')
343 |
344 | it12_w6 = Wire(it12_comp2, it12_comp3, Input.value_types.DATA, name='RHS')
345 |
346 | it12_w7 = Wire(it12_ml3, it12_comp3, Input.value_types.DATA, name='LHS')
347 | it12_w8 = Wire(it12_ml3, it12_comb1, Input.value_types.PREDICATE)
348 |
349 | it12_w9 = Wire(it12_comp3, it12_ms1, Input.value_types.DATA)
350 |
351 | it12_w10 = Wire(it12_ms1, it12_comb1, Input.value_types.PREDICATE)
352 |
353 | it12_w11 = Wire(it12_cc2, it12_comp1, Input.value_types.PREDICATE)
354 | it12_w12 = Wire(it12_cc2, it12_comp2, Input.value_types.PREDICATE)
355 | it12_w13 = Wire(it12_cc2, it12_comp3, Input.value_types.PREDICATE)
356 |
357 | # if_else
358 | ie_cc1 = ContinualConstant(1, name='IE_CC1')
359 | ie_cc2 = ContinualConstant(1, name='IE_CC2')
360 | ie_cc3 = ContinualConstant(True, name='IE_CC3')
361 | ie_ml1 = MemoryLoad('alpha', type_=int, name='IE_ML1')
362 | ie_ml2 = MemoryLoad('B', type_=int, name='IE_ML2')
363 | ie_comp1 = Computation(Operator.ADD, type_=int, name='IE_COMP1')
364 | ie_comp2 = Computation(Operator.ADD, type_=int, name='IE_COMP2')
365 | ie_comp3 = Computation(Operator.MUL, type_=int, name='IE_COMP3')
366 | ie_ms1 = MemoryStore('B', type_=int, name='IE_MS1')
367 | ie_comb1 = Combine(name='IE_COMB1')
368 |
369 | ie_w1 = Wire(ie_cc1, ie_comp1, Input.value_types.DATA, name='RHS')
370 | ie_w2 = Wire(ie_cc2, ie_comp2, Input.value_types.DATA, name='RHS')
371 |
372 | ie_w3 = Wire(ie_ml1, ie_comp3, Input.value_types.DATA, name='LHS')
373 | ie_w4 = Wire(ie_ml1, ie_comb1, Input.value_types.PREDICATE)
374 |
375 | ie_w5 = Wire(ie_ml2, ie_comp3, Input.value_types.DATA, name='RHS')
376 | ie_w6 = Wire(ie_ml2, ie_comb1, Input.value_types.PREDICATE)
377 |
378 | ie_w7 = Wire(ie_comp3, ie_ms1, Input.value_types.DATA)
379 |
380 | ie_w8 = Wire(ie_ms1, ie_comb1, Input.value_types.PREDICATE)
381 |
382 | ie_w9 = Wire(ie_cc3, ie_comp1, Input.value_types.PREDICATE)
383 | ie_w10 = Wire(ie_cc3, ie_comp2, Input.value_types.PREDICATE)
384 | ie_w11 = Wire(ie_cc3, ie_comp3, Input.value_types.PREDICATE)
385 |
386 | # final
387 | f_mux1 = Mux(name='F_MUX1')
388 | f_mux2 = Mux(name='F_MUX2')
389 | f_mux3 = Mux(name='F_MUX3')
390 | f_xor1 = XOR(name='F_XOR1')
391 | f_ms1 = MemoryStore('k', type_=int, name='F_MS1')
392 | f_ms2 = MemoryStore('i', type_=int, name='F_MS2')
393 | f_ms3 = MemoryStore('j', type_=int, name='F_MS3')
394 |
395 | f_w1 = Wire(f_mux1, f_ms3, Input.value_types.DATA) # j
396 | f_w2 = Wire(f_mux2, f_ms2, Input.value_types.DATA) # i
397 | f_w3 = Wire(f_mux3, f_ms1, Input.value_types.DATA) # k
398 |
399 | f_w4 = Wire(f_xor1, f_ms1, Input.value_types.PREDICATE)
400 | f_w5 = Wire(f_xor1, f_ms2, Input.value_types.PREDICATE)
401 | f_w6 = Wire(f_xor1, f_ms3, Input.value_types.PREDICATE)
402 |
403 | ################
404 | # Global wires #
405 | ################
406 |
407 | # e_oc3 i
408 | # e_oc4 j
409 | # e_comp1 k
410 |
411 | # f_mux2 i
412 | # f_mux1 j
413 | # f_mux3 k
414 |
415 | # g -> entry
416 | g_w1 = Wire(e_oc1, e_comp1, Input.value_types.PREDICATE)
417 |
418 | # g -> for_body
419 | g_w2 = Wire(e_oc1, fb_ml1, Input.value_types.PREDICATE)
420 | g_w3 = Wire(e_oc1, fb_comb1, Input.value_types.PREDICATE)
421 |
422 | # entry -> for_body
423 | g_w4 = Wire(e_oc4, fb_comp1, Input.value_types.DATA, name='LHS')
424 |
425 | # entry -> if_else36
426 | g_w5 = Wire(e_oc3, ie36_comp1, Input.value_types.DATA, name='LHS')
427 |
428 | # entry -> if_then
429 | g_w6 = Wire(e_comp1, it_comp1, Input.value_types.DATA, name='LHS')
430 |
431 | # for_body -> if_then
432 | g_w7 = Wire(fb_comb2, it_ml1, Input.value_types.PREDICATE)
433 | g_w8 = Wire(fb_comb2, it_comb1, Input.value_types.PREDICATE)
434 |
435 | # entry -> if_then12
436 | g_w9 = Wire(e_oc3, it12_ml1, Input.value_types.DATA, name='[1]')
437 | g_w10 = Wire(e_oc3, it12_ml3, Input.value_types.DATA, name='[0]')
438 | g_w11 = Wire(e_oc3, it12_ms1, Input.value_types.DATA, name='[0]')
439 |
440 | g_w12 = Wire(e_oc4, it12_ml2, Input.value_types.DATA, name='[1]')
441 | g_w13 = Wire(e_oc4, it12_ml3, Input.value_types.DATA, name='[1]')
442 | g_w14 = Wire(e_oc4, it12_ms1, Input.value_types.DATA, name='[1]')
443 |
444 | g_w15 = Wire(e_comp1, it12_ml1, Input.value_types.DATA, name='[0]')
445 | g_w16 = Wire(e_comp1, it12_ml2, Input.value_types.DATA, name='[0]')
446 | g_w17 = Wire(e_comp1, it12_comp1, Input.value_types.DATA, name='LHS')
447 |
448 | # if_then -> if_then12
449 | g_w18 = Wire(it_comb2, it12_ml1, Input.value_types.PREDICATE)
450 | g_w19 = Wire(it_comb2, it12_ml2, Input.value_types.PREDICATE)
451 | g_w20 = Wire(it_comb2, it12_ml3, Input.value_types.PREDICATE)
452 | g_w21 = Wire(it_comb2, it12_ms1, Input.value_types.PREDICATE)
453 | g_w22 = Wire(it_comb2, it12_comb1, Input.value_types.PREDICATE)
454 |
455 | # entry -> if_else
456 | g_w23 = Wire(e_oc3, ie_ml2, Input.value_types.DATA, name='[0]')
457 | g_w24 = Wire(e_oc3, ie_comp1, Input.value_types.DATA, name='LHS')
458 | g_w25 = Wire(e_oc3, ie_ms1, Input.value_types.DATA, name='[0]')
459 |
460 | g_w26 = Wire(e_oc4, ie_ml2, Input.value_types.DATA, name='[1]')
461 | g_w27 = Wire(e_oc4, ie_comp2, Input.value_types.DATA, name='LHS')
462 | g_w28 = Wire(e_oc4, ie_ms1, Input.value_types.DATA, name='[1]')
463 |
464 | # if_then -> if_else
465 | g_w29 = Wire(it_comb3, ie_ml1, Input.value_types.PREDICATE)
466 | g_w30 = Wire(it_comb3, ie_ml2, Input.value_types.PREDICATE)
467 | g_w31 = Wire(it_comb3, ie_ms1, Input.value_types.PREDICATE)
468 | g_w32 = Wire(it_comb3, ie_comb1, Input.value_types.PREDICATE)
469 |
470 | # for_body -> final
471 | g_w33 = Wire(fb_comb3, f_xor1, Input.value_types.PREDICATE)
472 | g_w34 = Wire(fb_comb3, f_mux2, Input.value_types.PREDICATE, name='i1')
473 | g_w35 = Wire(fb_comb3, f_mux1, Input.value_types.PREDICATE, name='j1')
474 | g_w36 = Wire(fb_comb3, f_mux3, Input.value_types.PREDICATE, name='k1')
475 |
476 | # if_else_36 -> final
477 | g_w37 = Wire(ie36_comp1, f_mux2, Input.value_types.DATA, name='i1')
478 | g_w38 = Wire(ie36_cc3, f_mux1, Input.value_types.DATA, name='j1')
479 | g_w39 = Wire(ie36_comp2, f_mux3, Input.value_types.DATA, name='k1')
480 |
481 | # if_then12 -> final
482 | g_w40 = Wire(e_oc3, f_mux2, Input.value_types.DATA, name='i2')
483 | g_w41 = Wire(e_oc4, f_mux1, Input.value_types.DATA, name='j2')
484 | g_w42 = Wire(it12_comp1, f_mux3, Input.value_types.DATA, name='k2')
485 |
486 | g_w43 = Wire(it12_comb1, f_xor1, Input.value_types.PREDICATE)
487 | g_w44 = Wire(it12_comb1, f_mux2, Input.value_types.PREDICATE, name='i2')
488 | g_w45 = Wire(it12_comb1, f_mux1, Input.value_types.PREDICATE, name='j2')
489 | g_w46 = Wire(it12_comb1, f_mux3, Input.value_types.PREDICATE, name='k2')
490 |
491 | # if_else -> final
492 | g_w47 = Wire(e_oc3, f_mux2, Input.value_types.DATA, name='i3')
493 | g_w48 = Wire(ie_comp2, f_mux1, Input.value_types.DATA, name='j3')
494 | g_w49 = Wire(ie_comp1, f_mux3, Input.value_types.DATA, name='k3')
495 |
496 | g_w50 = Wire(ie_comb1, f_xor1, Input.value_types.PREDICATE)
497 | g_w51 = Wire(ie_comb1, f_mux2, Input.value_types.PREDICATE, name='i3')
498 | g_w52 = Wire(ie_comb1, f_mux1, Input.value_types.PREDICATE, name='j3')
499 | g_w53 = Wire(ie_comb1, f_mux3, Input.value_types.PREDICATE, name='k3')
500 |
501 | return IR([[e_oc1],
502 | [e_oc2, e_oc3, e_oc4, e_comp1],
503 | [fb_cc1, fb_ml1, fb_comb1, fb_comb2, fb_comb3, fb_comp1, fb_comp2],
504 | [ie36_cc1, ie36_cc2, ie36_cc3, ie36_cc4, ie36_comp1, ie36_comp2],
505 | [it_cc1, it_ml1, it_comb1, it_comb2, it_comb3, it_comp1, it_comp2],
506 | [it12_cc1, it12_cc2, it12_comp1, it12_comp2, it12_comp3, it12_ml1, it12_ml2, it12_ml3, it12_ms1, it12_comb1],
507 | [ie_cc1, ie_cc2, ie_cc3, ie_ml1, ie_ml2, ie_comp1, ie_comp2, ie_comp3, ie_ms1, ie_comb1],
508 | [f_mux1, f_mux2, f_mux3, f_xor1, f_ms1, f_ms2, f_ms3]],
509 | [e_w1, e_w2,
510 | fb_w1, fb_w2, fb_w3, fb_w4, fb_w5, fb_w6, fb_w7, fb_w8, fb_w9,
511 | ie36_w1, ie36_w2, ie36_w3, ie36_w4, ie36_w5,
512 | it_w1, it_w2, it_w3, it_w4, it_w5, it_w6, it_w7, it_w8, it_w9,
513 | it12_w1, it12_w2, it12_w3, it12_w4, it12_w5, it12_w6, it12_w7, it12_w8, it12_w9, it12_w10, it12_w11, it12_w12, it12_w13,
514 | ie_w1, ie_w2, ie_w3, ie_w4, ie_w5, ie_w6, ie_w7, ie_w8, ie_w9, ie_w10, ie_w11,
515 | f_w1, f_w2, f_w3, f_w4, f_w5, f_w6,
516 | g_w1, g_w2, g_w3, g_w4, g_w5, g_w6, g_w7, g_w8, g_w9, g_w10, g_w11, g_w12, g_w13, g_w14, g_w15, g_w16, g_w17, g_w18, g_w19, g_w20, g_w21, g_w22, g_w23, g_w24, g_w25, g_w26, g_w27, g_w28, g_w29, g_w30, g_w31, g_w32, g_w33, g_w34, g_w35, g_w36, g_w37, g_w38, g_w39, g_w40, g_w41, g_w42, g_w43, g_w44, g_w45, g_w46, g_w47, g_w48, g_w49, g_w50, g_w51, g_w52, g_w53])
--------------------------------------------------------------------------------
/data/divergence_atomic.dot:
--------------------------------------------------------------------------------
1 | digraph IR {
2 | subgraph cluster_1 {
3 | B1_OT1 [label=1, shape=doublecircle];
4 | B1_OT2 [label="T", shape=doublecircle];
5 |
6 | B1_CC1 [label=2, shape=circle];
7 |
8 | B1_ML1 [label="B", shape=invtriangle, type=int];
9 |
10 | B1_COMB1 [label="COMBINE", shape=house];
11 |
12 | B1_COMP1 [label="==", operator=EQ, shape=box, type=int];
13 | B1_COMP2 [label="!", operator=NOT, shape=box, type=bool];
14 |
15 | B1_ETA1 [label="ETA", shape=parallelogram];
16 | B1_ETA2 [label="ETA", shape=parallelogram];
17 | }
18 |
19 | subgraph cluster_2 {
20 | B2_CC1 [label=3, shape=circle];
21 | B2_COMP1 [label="+", operator=ADD, shape=box, type=int];
22 | B2_MS1 [label="B", shape=triangle];
23 | }
24 |
25 | subgraph cluster_3 {
26 | B3_CC1 [label=3, shape=circle];
27 | B3_COMP1 [label="*", operator=MUL, shape=box, type=int];
28 | B3_MS1 [label="B", shape=triangle];
29 | }
30 |
31 | # B1 wires
32 | B1_CC1 -> B1_COMP1 [label="RHS"];
33 | B1_ML1 -> B1_COMP1 [label="LHS"];
34 |
35 | B1_COMP1 -> B1_COMP2;
36 | B1_COMP1 -> B1_ETA1 [style=dotted];
37 |
38 | B1_ML1 -> B1_COMB1 [style=dotted];
39 |
40 | B1_COMB1 -> B1_ETA1;
41 | B1_COMB1 -> B1_ETA2;
42 |
43 | B1_COMP2 -> B1_ETA2 [style=dotted];
44 |
45 | B1_OT2 -> B1_COMP1 [style=dotted];
46 | B1_OT2 -> B1_COMP2 [style=dotted];
47 | B1_OT2 -> B1_ML1 [style=dotted];
48 |
49 | B1_OT1 -> B2_COMP1 [label="LHS"];
50 | B1_OT1 -> B3_COMP1 [label="LHS"];
51 |
52 | // B2 wires
53 | B2_CC1 -> B2_COMP1 [label="RHS"];
54 | B2_COMP1 -> B2_MS1;
55 |
56 | // B3 wires
57 | B3_CC1 -> B3_COMP1 [label="RHS"];
58 | B3_COMP1 -> B3_MS1;
59 |
60 | // Global wires
61 | B1_ETA1 -> B2_MS1 [style=dotted];
62 | B1_ETA1 -> B2_COMP1 [style=dotted];
63 |
64 | B1_ETA2 -> B3_MS1 [style=dotted];
65 | B1_ETA2 -> B3_COMP1 [style=dotted];
66 | }
67 |
--------------------------------------------------------------------------------
/data/divergence_speculative.dot:
--------------------------------------------------------------------------------
1 | digraph IR {
2 | subgraph cluster_1 {
3 | B1_OT1 [label=1, shape=doublecircle];
4 | B1_OT2 [label="T", shape=doublecircle];
5 |
6 | B1_CC1 [label=2, shape=circle];
7 |
8 | B1_ML1 [label="B", shape=invtriangle, type=int];
9 |
10 | B1_COMB1 [label="COMBINE", shape=house];
11 |
12 | B1_COMP1 [label="==", operator=EQ, shape=box, type=int];
13 | B1_COMP2 [label="!", operator=NOT, shape=box, type=bool];
14 |
15 | B1_COMB2 [label="COMBINE", shape=house];
16 | B1_COMB3 [label="COMBINE", shape=house];
17 | }
18 |
19 | subgraph cluster_2 {
20 | B2_CC1 [label=3, shape=circle];
21 | B2_CC2 [label="T", shape=circle];
22 |
23 | B2_COMP1 [label="+", operator=ADD, shape=box, type=int];
24 | B2_MS1 [label="B", shape=triangle];
25 | }
26 |
27 | subgraph cluster_3 {
28 | B3_CC1 [label=3, shape=circle];
29 | B3_CC2 [label="T", shape=circle];
30 |
31 | B3_COMP1 [label="*", operator=MUL, shape=box, type=int];
32 | B3_MS1 [label="B", shape=triangle];
33 | }
34 |
35 | # B1 wires
36 | B1_CC1 -> B1_COMP1 [label="RHS"];
37 | B1_ML1 -> B1_COMP1 [label="LHS"];
38 |
39 | B1_COMP1 -> B1_COMP2;
40 | B1_COMP1 -> B1_COMB2 [style=dotted];
41 |
42 | B1_ML1 -> B1_COMB1 [style=dotted];
43 |
44 | B1_COMB1 -> B1_COMB2;
45 | B1_COMB1 -> B1_COMB3;
46 |
47 | B1_COMP2 -> B1_COMB3 [style=dotted];
48 |
49 | B1_OT2 -> B1_COMP1 [style=dotted];
50 | B1_OT2 -> B1_COMP2 [style=dotted];
51 | B1_OT2 -> B1_ML1 [style=dotted];
52 | B1_OT2 -> B1_COMB1 [style=dotted];
53 |
54 | B1_OT1 -> B2_COMP1 [label="LHS"];
55 | B1_OT1 -> B3_COMP1 [label="LHS"];
56 |
57 | // B2 wires
58 | B2_CC2 -> B2_COMP1 [style=dotted];
59 | B2_CC1 -> B2_COMP1 [label="RHS"];
60 | B2_COMP1 -> B2_MS1;
61 |
62 | // B3 wires
63 | B3_CC2 -> B3_COMP1 [style=dotted];
64 | B3_CC1 -> B3_COMP1 [label="RHS"];
65 | B3_COMP1 -> B3_MS1;
66 |
67 | // Global wires
68 | B1_COMB2 -> B2_MS1 [style=dotted];
69 | B1_COMB3 -> B3_MS1 [style=dotted];
70 | }
71 |
--------------------------------------------------------------------------------
/data/prefix_sum_parallel.dot:
--------------------------------------------------------------------------------
1 | digraph IR {
2 | graph [bgcolor=transparent, ratio="0.5545"];
3 | node [color="#aaccf4", fillcolor="#1d2f49", fontcolor=white, style=filled];
4 | edge [color=white, fontcolor=white];
5 | PRED [label="T", shape=doublecircle];
6 | subgraph cluster_2 {
7 | color="#aaccf4";
8 | penwidth=2;
9 | R0_0 [label=7, shape=doublecircle];
10 | R0_1 [label=0, shape=doublecircle];
11 | R0_2 [label=2, shape=doublecircle];
12 | R0_3 [label=9, shape=doublecircle];
13 | R0_4 [label=5, shape=doublecircle];
14 | R0_5 [label=1, shape=doublecircle];
15 | R0_6 [label=8, shape=doublecircle];
16 | R0_7 [label=6, shape=doublecircle];
17 | }
18 |
19 | subgraph cluster_3 {
20 | color="#aaccf4";
21 | penwidth=2;
22 | R1_1 [label="+", operator=ADD, shape=box, type=int];
23 | R1_2 [label="+", operator=ADD, shape=box, type=int];
24 | R1_3 [label="+", operator=ADD, shape=box, type=int];
25 | R1_4 [label="+", operator=ADD, shape=box, type=int];
26 | R1_5 [label="+", operator=ADD, shape=box, type=int];
27 | R1_6 [label="+", operator=ADD, shape=box, type=int];
28 | R1_7 [label="+", operator=ADD, shape=box, type=int];
29 | }
30 |
31 | subgraph cluster_4 {
32 | color="#aaccf4";
33 | penwidth=2;
34 | R2_2 [label="+", operator=ADD, shape=box, type=int];
35 | R2_3 [label="+", operator=ADD, shape=box, type=int];
36 | R2_4 [label="+", operator=ADD, shape=box, type=int];
37 | R2_5 [label="+", operator=ADD, shape=box, type=int];
38 | R2_6 [label="+", operator=ADD, shape=box, type=int];
39 | R2_7 [label="+", operator=ADD, shape=box, type=int];
40 | }
41 |
42 | subgraph cluster_5 {
43 | color="#aaccf4";
44 | penwidth=2;
45 | R3_4 [label="+", operator=ADD, shape=box, type=int];
46 | R3_5 [label="+", operator=ADD, shape=box, type=int];
47 | R3_6 [label="+", operator=ADD, shape=box, type=int];
48 | R3_7 [label="+", operator=ADD, shape=box, type=int];
49 | }
50 |
51 | subgraph cluster_6 {
52 | color="#aaccf4";
53 | penwidth=2;
54 | R4_0 [label="R4_0", shape=star];
55 | R4_1 [label="R4_1", shape=star];
56 | R4_2 [label="R4_2", shape=star];
57 | R4_3 [label="R4_3", shape=star];
58 | R4_4 [label="R4_4", shape=star];
59 | R4_5 [label="R4_5", shape=star];
60 | R4_6 [label="R4_6", shape=star];
61 | R4_7 [label="R4_7", shape=star];
62 | }
63 |
64 | R0_0 -> R1_1 [label="LHS"];
65 | R0_1 -> R1_1 [label="RHS"];
66 | R0_1 -> R1_2 [label="LHS"];
67 | R0_2 -> R1_2 [label="RHS"];
68 | R0_2 -> R1_3 [label="LHS"];
69 | R0_3 -> R1_3 [label="RHS"];
70 | R0_3 -> R1_4 [label="LHS"];
71 | R0_4 -> R1_4 [label="RHS"];
72 | R0_4 -> R1_5 [label="LHS"];
73 | R0_5 -> R1_5 [label="RHS"];
74 | R0_5 -> R1_6 [label="LHS"];
75 | R0_6 -> R1_6 [label="RHS"];
76 | R0_6 -> R1_7 [label="LHS"];
77 | R0_7 -> R1_7 [label="RHS"];
78 | R0_0 -> R2_2 [label="LHS"];
79 | R1_2 -> R2_2 [label="RHS"];
80 | R1_1 -> R2_3 [label="LHS"];
81 | R1_3 -> R2_3 [label="RHS"];
82 | R1_2 -> R2_4 [label="LHS"];
83 | R1_4 -> R2_4 [label="RHS"];
84 | R1_3 -> R2_5 [label="LHS"];
85 | R1_5 -> R2_5 [label="RHS"];
86 | R1_4 -> R2_6 [label="LHS"];
87 | R1_6 -> R2_6 [label="RHS"];
88 | R1_5 -> R2_7 [label="LHS"];
89 | R1_7 -> R2_7 [label="RHS"];
90 | R0_0 -> R3_4 [label="LHS"];
91 | R2_4 -> R3_4 [label="RHS"];
92 | R1_1 -> R3_5 [label="LHS"];
93 | R2_5 -> R3_5 [label="RHS"];
94 | R2_2 -> R3_6 [label="LHS"];
95 | R2_6 -> R3_6 [label="RHS"];
96 | R2_3 -> R3_7 [label="LHS"];
97 | R2_7 -> R3_7 [label="RHS"];
98 | R0_0 -> R4_0;
99 | R1_1 -> R4_1;
100 | R2_2 -> R4_2;
101 | R2_3 -> R4_3;
102 | R3_4 -> R4_4;
103 | R3_5 -> R4_5;
104 | R3_6 -> R4_6;
105 | R3_7 -> R4_7;
106 | PRED -> R1_1 [style=dotted];
107 | PRED -> R1_2 [style=dotted];
108 | PRED -> R1_3 [style=dotted];
109 | PRED -> R1_4 [style=dotted];
110 | PRED -> R1_5 [style=dotted];
111 | PRED -> R1_6 [style=dotted];
112 | PRED -> R1_7 [style=dotted];
113 | PRED -> R2_2 [style=dotted];
114 | PRED -> R2_3 [style=dotted];
115 | PRED -> R2_4 [style=dotted];
116 | PRED -> R2_5 [style=dotted];
117 | PRED -> R2_6 [style=dotted];
118 | PRED -> R2_7 [style=dotted];
119 | PRED -> R3_4 [style=dotted];
120 | PRED -> R3_5 [style=dotted];
121 | PRED -> R3_6 [style=dotted];
122 | PRED -> R3_7 [style=dotted];
123 | }
124 |
--------------------------------------------------------------------------------
/data/prefix_sum_work_effective.dot:
--------------------------------------------------------------------------------
1 | digraph IR {
2 | graph [bgcolor=transparent, ratio="0.5545"];
3 | node [color="#aaccf4", fillcolor="#1d2f49", fontcolor=white, style=filled];
4 | edge [color=white, fontcolor=white];
5 | PRED [label="T", shape=doublecircle];
6 | subgraph cluster_2 {
7 | color="#aaccf4";
8 | penwidth=2;
9 | R0_0 [label=7, shape=doublecircle];
10 | R0_1 [label=0, shape=doublecircle];
11 | R0_2 [label=2, shape=doublecircle];
12 | R0_3 [label=9, shape=doublecircle];
13 | R0_4 [label=5, shape=doublecircle];
14 | R0_5 [label=1, shape=doublecircle];
15 | R0_6 [label=8, shape=doublecircle];
16 | R0_7 [label=6, shape=doublecircle];
17 | }
18 |
19 | subgraph cluster_3 {
20 | color="#aaccf4";
21 | penwidth=2;
22 | R1_1 [label="+", operator=ADD, shape=box, type=int];
23 | R1_3 [label="+", operator=ADD, shape=box, type=int];
24 | R1_5 [label="+", operator=ADD, shape=box, type=int];
25 | R1_7 [label="+", operator=ADD, shape=box, type=int];
26 | }
27 |
28 | subgraph cluster_4 {
29 | color="#aaccf4";
30 | penwidth=2;
31 | R2_3 [label="+", operator=ADD, shape=box, type=int];
32 | R2_7 [label="+", operator=ADD, shape=box, type=int];
33 | }
34 |
35 | subgraph cluster_5 {
36 | color="#aaccf4";
37 | penwidth=2;
38 | R3_7 [label="+", operator=ADD, shape=box, type=int];
39 | }
40 |
41 | subgraph cluster_6 {
42 | color="#aaccf4";
43 | penwidth=2;
44 | R4_5 [label="+", operator=ADD, shape=box, type=int];
45 | }
46 |
47 | subgraph cluster_7 {
48 | color="#aaccf4";
49 | penwidth=2;
50 | R5_2 [label="+", operator=ADD, shape=box, type=int];
51 | R5_4 [label="+", operator=ADD, shape=box, type=int];
52 | R5_6 [label="+", operator=ADD, shape=box, type=int];
53 | }
54 |
55 | subgraph cluster_8 {
56 | color="#aaccf4";
57 | penwidth=2;
58 | R6_0 [label="R6_0", shape=star];
59 | R6_1 [label="R6_1", shape=star];
60 | R6_2 [label="R6_2", shape=star];
61 | R6_3 [label="R6_3", shape=star];
62 | R6_4 [label="R6_4", shape=star];
63 | R6_5 [label="R6_5", shape=star];
64 | R6_6 [label="R6_6", shape=star];
65 | R6_7 [label="R6_7", shape=star];
66 | }
67 |
68 | R0_0 -> R1_1 [label="LHS"];
69 | R0_1 -> R1_1 [label="RHS"];
70 | R0_2 -> R1_3 [label="LHS"];
71 | R0_3 -> R1_3 [label="RHS"];
72 | R0_4 -> R1_5 [label="LHS"];
73 | R0_5 -> R1_5 [label="RHS"];
74 | R0_6 -> R1_7 [label="LHS"];
75 | R0_7 -> R1_7 [label="RHS"];
76 | R1_1 -> R2_3 [label="LHS"];
77 | R1_3 -> R2_3 [label="RHS"];
78 | R1_5 -> R2_7 [label="LHS"];
79 | R1_7 -> R2_7 [label="RHS"];
80 | R2_3 -> R3_7 [label="LHS"];
81 | R2_7 -> R3_7 [label="RHS"];
82 | R2_3 -> R4_5 [label="LHS"];
83 | R1_5 -> R4_5 [label="RHS"];
84 | R1_1 -> R5_2 [label="LHS"];
85 | R0_2 -> R5_2 [label="RHS"];
86 | R2_3 -> R5_4 [label="LHS"];
87 | R0_4 -> R5_4 [label="RHS"];
88 | R4_5 -> R5_6 [label="LHS"];
89 | R0_6 -> R5_6 [label="RHS"];
90 | R0_0 -> R6_0;
91 | R1_1 -> R6_1;
92 | R5_2 -> R6_2;
93 | R2_3 -> R6_3;
94 | R5_4 -> R6_4;
95 | R4_5 -> R6_5;
96 | R5_6 -> R6_6;
97 | R3_7 -> R6_7;
98 | PRED -> R1_1 [style=dotted];
99 | PRED -> R1_3 [style=dotted];
100 | PRED -> R1_5 [style=dotted];
101 | PRED -> R1_7 [style=dotted];
102 | PRED -> R2_3 [style=dotted];
103 | PRED -> R2_7 [style=dotted];
104 | PRED -> R3_7 [style=dotted];
105 | PRED -> R4_5 [style=dotted];
106 | PRED -> R5_2 [style=dotted];
107 | PRED -> R5_4 [style=dotted];
108 | PRED -> R5_6 [style=dotted];
109 | }
110 |
--------------------------------------------------------------------------------
/data/trmm_MEM.json:
--------------------------------------------------------------------------------
1 | [
2 | ["n", [], 2],
3 | ["m", [], 2],
4 | ["alpha", [], 2],
5 | ["A", [0,0], 1],
6 | ["A", [0,1], 2],
7 | ["A", [1,0], 3],
8 | ["A", [1,1], 4],
9 | ["B", [0,0], 5],
10 | ["B", [0,1], 6],
11 | ["B", [1,0], 7],
12 | ["B", [1,1], 8]
13 | ]
14 |
--------------------------------------------------------------------------------
/data/trmm_atomic_IR.dot:
--------------------------------------------------------------------------------
1 | digraph IR {
2 | graph [bgcolor=transparent, ratio="0.5545"];
3 | node [color="#aaccf4", fillcolor="#1d2f49", fontcolor=white, style=filled];
4 | edge [color=white, fontcolor=white];
5 | E_OC1 [label="T", shape=doublecircle];
6 | subgraph cluster_2 {
7 | color="#aaccf4";
8 | penwidth=2;
9 | E_OC2 [label=1, shape=doublecircle];
10 | E_OC3 [label=0, shape=doublecircle];
11 | E_OC4 [label=0, shape=doublecircle];
12 | E_COMP1 [label="+", operator=ADD, shape=box];
13 | }
14 |
15 | subgraph cluster_3 {
16 | color="#aaccf4";
17 | penwidth=2;
18 | FB_ML1 [label="n", shape=invtriangle, type=int];
19 | FB_COMB1 [label="COMBINE", shape=house];
20 | FB_COMP1 [label="\<", operator=LT, shape=box, type=int];
21 | FB_COMP2 [label="!", operator=NOT, shape=box, type=bool];
22 | FB_ETA1 [label="ETA", shape=parallelogram];
23 | FB_ETA2 [label="ETA", shape=parallelogram];
24 | }
25 |
26 | subgraph cluster_4 {
27 | color="#aaccf4";
28 | penwidth=2;
29 | IE36_CC1 [label=1, shape=circle];
30 | IE36_CC2 [label=1, shape=circle];
31 | IE36_CC3 [label=0, shape=circle];
32 | IE36_COMP1 [label="+", operator=ADD, shape=box, type=int];
33 | IE36_COMP2 [label="+", operator=ADD, shape=box, type=int];
34 | IE36_ETA1 [label="ETA", shape=parallelogram];
35 | }
36 |
37 | subgraph cluster_5 {
38 | color="#aaccf4";
39 | penwidth=2;
40 | IT_ML1 [label="m", shape=invtriangle, type=int];
41 | IT_COMB1 [label="COMBINE", shape=house];
42 | IT_COMP1 [label="\<", operator=LT, shape=box, type=int];
43 | IT_COMP2 [label="!", operator=NOT, shape=box, type=int];
44 | IT_ETA1 [label="ETA", shape=parallelogram];
45 | IT_ETA2 [label="ETA", shape=parallelogram];
46 | }
47 |
48 | subgraph cluster_6 {
49 | color="#aaccf4";
50 | penwidth=2;
51 | IT12_CC1 [label=1, shape=circle];
52 | IT12_COMP1 [label="+", operator=ADD, shape=box, type=int];
53 | IT12_COMP2 [label="*", operator=MUL, shape=box, type=int];
54 | IT12_COMP3 [label="+", operator=ADD, shape=box, type=int];
55 | IT12_ETA1 [label="ETA", shape=parallelogram];
56 | IT12_ETA2 [label="ETA", shape=parallelogram];
57 | IT12_ML1 [label="A", shape=invtriangle, type=int];
58 | IT12_ML2 [label="B", shape=invtriangle, type=int];
59 | IT12_ML3 [label="B", shape=invtriangle, type=int];
60 | IT12_MS1 [label="B", shape=triangle];
61 | IT12_COMB1 [label="COMBINE", shape=house];
62 | }
63 |
64 | subgraph cluster_7 {
65 | color="#aaccf4";
66 | penwidth=2;
67 | IE_CC1 [label=1, shape=circle];
68 | IE_CC2 [label=1, shape=circle];
69 | IE_ML1 [label="alpha", shape=invtriangle, type=int];
70 | IE_ML2 [label="B", shape=invtriangle, type=int];
71 | IE_ETA1 [label="ETA", shape=parallelogram];
72 | IE_COMP1 [label="+", operator=ADD, shape=box, type=int];
73 | IE_COMP2 [label="+", operator=ADD, shape=box, type=int];
74 | IE_COMP3 [label="*", operator=MUL, shape=box, type=int];
75 | IE_MS1 [label="B", shape=triangle];
76 | IE_COMB1 [label="COMBINE", shape=house];
77 | }
78 |
79 | subgraph cluster_8 {
80 | color="#aaccf4";
81 | penwidth=2;
82 | F_MU1 [label="MU", shape=diamond];
83 | F_MU2 [label="MU", shape=diamond];
84 | F_MU3 [label="MU", shape=diamond];
85 | F_MU4 [label="MU", shape=diamond];
86 | F_MS1 [label="k", shape=triangle];
87 | F_MS2 [label="i", shape=triangle];
88 | F_MS3 [label="j", shape=triangle];
89 | }
90 |
91 | E_OC2 -> E_COMP1 [label="RHS"];
92 | E_OC3 -> E_COMP1 [label="LHS"];
93 | FB_ML1 -> FB_COMB1 [style=dotted];
94 | FB_ML1 -> FB_COMP1 [label="RHS"];
95 | FB_COMB1 -> FB_ETA2;
96 | FB_COMB1 -> FB_ETA1;
97 | FB_COMP1 -> FB_COMP2;
98 | FB_COMP1 -> FB_ETA1 [style=dotted];
99 | FB_COMP2 -> FB_ETA2 [style=dotted];
100 | IE36_CC1 -> IE36_COMP1 [label="RHS"];
101 | IE36_COMP2 -> IE36_COMP1 [label="LHS"];
102 | IE36_CC2 -> IE36_COMP2 [label="RHS"];
103 | IE36_CC3 -> IE36_ETA1;
104 | IT_ML1 -> IT_COMB1 [style=dotted];
105 | IT_ML1 -> IT_COMP1 [label="RHS"];
106 | IT_COMB1 -> IT_ETA1;
107 | IT_COMB1 -> IT_ETA2;
108 | IT_COMP1 -> IT_ETA1 [style=dotted];
109 | IT_COMP1 -> IT_COMP2;
110 | IT_COMP2 -> IT_ETA2 [style=dotted];
111 | IT12_CC1 -> IT12_COMP1 [label="RHS"];
112 | IT12_ML1 -> IT12_COMP2 [label="LHS"];
113 | IT12_ML1 -> IT12_COMB1 [style=dotted];
114 | IT12_ML2 -> IT12_COMB1 [style=dotted];
115 | IT12_ML2 -> IT12_COMP2 [label="RHS"];
116 | IT12_COMP2 -> IT12_COMP3 [label="RHS"];
117 | IT12_ML3 -> IT12_COMP3 [label="LHS"];
118 | IT12_ML3 -> IT12_COMB1 [style=dotted];
119 | IT12_COMP3 -> IT12_MS1;
120 | IT12_MS1 -> IT12_COMB1 [style=dotted];
121 | IE_CC1 -> IE_COMP1 [label="RHS"];
122 | IE_CC2 -> IE_COMP2 [label="RHS"];
123 | IE_ML1 -> IE_COMP3 [label="LHS"];
124 | IE_ML1 -> IE_COMB1 [style=dotted];
125 | IE_ML2 -> IE_COMP3 [label="RHS"];
126 | IE_ML2 -> IE_COMB1 [style=dotted];
127 | IE_COMP3 -> IE_MS1;
128 | IE_MS1 -> IE_COMB1 [style=dotted];
129 | F_MU1 -> F_MS1;
130 | F_MU2 -> F_MS2;
131 | F_MU4 -> F_MS3;
132 | F_MU3 -> F_MS1 [style=dotted];
133 | F_MU3 -> F_MS2 [style=dotted];
134 | F_MU3 -> F_MS3 [style=dotted];
135 | E_OC1 -> E_COMP1 [style=dotted];
136 | E_OC1 -> FB_ML1 [style=dotted];
137 | E_OC1 -> FB_COMP1 [style=dotted];
138 | E_OC1 -> FB_COMP2 [style=dotted];
139 | E_OC4 -> FB_COMP1 [label="LHS"];
140 | E_OC3 -> IE36_COMP2 [label="LHS"];
141 | FB_ETA2 -> IE36_COMP1 [style=dotted];
142 | FB_ETA2 -> IE36_COMP2 [style=dotted];
143 | FB_ETA2 -> IE36_ETA1 [style=dotted];
144 | E_COMP1 -> IT_COMP1 [label="LHS"];
145 | FB_ETA1 -> IT_ML1 [style=dotted];
146 | FB_ETA1 -> IT_COMP1 [style=dotted];
147 | FB_ETA1 -> IT_COMP2 [style=dotted];
148 | E_OC3 -> IT12_ETA1;
149 | E_OC3 -> IT12_ML1 [label="[1]"];
150 | E_OC3 -> IT12_ML3 [label="[0]"];
151 | E_OC3 -> IT12_MS1 [label="[0]"];
152 | E_OC4 -> IT12_ETA2;
153 | E_OC4 -> IT12_ML2 [label="[1]"];
154 | E_OC4 -> IT12_ML3 [label="[1]"];
155 | E_OC4 -> IT12_MS1 [label="[1]"];
156 | E_COMP1 -> IT12_COMP1 [label="LHS"];
157 | E_COMP1 -> IT12_ML1 [label="[0]"];
158 | E_COMP1 -> IT12_ML2 [label="[0]"];
159 | IT_ETA1 -> IT12_COMP1 [style=dotted];
160 | IT_ETA1 -> IT12_ETA1 [style=dotted];
161 | IT_ETA1 -> IT12_ML1 [style=dotted];
162 | IT_ETA1 -> IT12_ETA2 [style=dotted];
163 | IT_ETA1 -> IT12_ML2 [style=dotted];
164 | IT_ETA1 -> IT12_COMP2 [style=dotted];
165 | IT_ETA1 -> IT12_ML3 [style=dotted];
166 | IT_ETA1 -> IT12_COMP3 [style=dotted];
167 | IT_ETA1 -> IT12_MS1 [style=dotted];
168 | E_OC3 -> IE_ML2 [label="[0]"];
169 | E_OC3 -> IE_ETA1;
170 | E_OC3 -> IE_COMP1 [label="LHS"];
171 | E_OC3 -> IE_MS1 [label="[0]"];
172 | E_OC4 -> IE_ML2 [label="[1]"];
173 | E_OC4 -> IE_COMP2 [label="LHS"];
174 | E_OC4 -> IE_MS1 [label="[1]"];
175 | IT_ETA2 -> IE_ML1 [style=dotted];
176 | IT_ETA2 -> IE_ML2 [style=dotted];
177 | IT_ETA2 -> IE_ETA1 [style=dotted];
178 | IT_ETA2 -> IE_COMP1 [style=dotted];
179 | IT_ETA2 -> IE_COMP2 [style=dotted];
180 | IT_ETA2 -> IE_COMP3 [style=dotted];
181 | IT_ETA2 -> IE_MS1 [style=dotted];
182 | FB_ETA2 -> F_MU3 [style=dotted];
183 | IE36_COMP1 -> F_MU1;
184 | IE36_COMP2 -> F_MU2;
185 | IE36_ETA1 -> F_MU4;
186 | IT12_COMP1 -> F_MU1;
187 | IT12_ETA1 -> F_MU2;
188 | IT12_COMB1 -> F_MU3 [style=dotted];
189 | IT12_ETA2 -> F_MU4;
190 | IE_COMP1 -> F_MU1;
191 | IE_ETA1 -> F_MU2;
192 | IE_COMB1 -> F_MU3 [style=dotted];
193 | IE_COMP2 -> F_MU4;
194 | }
195 |
--------------------------------------------------------------------------------
/data/trmm_speculative_IR.dot:
--------------------------------------------------------------------------------
1 | digraph IR {
2 | graph [bgcolor=transparent, ratio="0.5545"];
3 | node [color="#aaccf4", fillcolor="#1d2f49", fontcolor=white, style=filled];
4 | edge [color=white, fontcolor=white];
5 | E_OC1 [label="T", shape=doublecircle];
6 | subgraph cluster_2 {
7 | color="#aaccf4";
8 | penwidth=2;
9 | E_OC2 [label=1, shape=doublecircle];
10 | E_OC3 [label=0, shape=doublecircle];
11 | E_OC4 [label=0, shape=doublecircle];
12 | E_COMP1 [label="+", operator=ADD, shape=box];
13 | }
14 |
15 | subgraph cluster_3 {
16 | color="#aaccf4";
17 | penwidth=2;
18 | FB_CC1 [label="T", shape=circle];
19 | FB_ML1 [label="n", shape=invtriangle, type=int];
20 | FB_COMB1 [label="COMBINE", shape=house];
21 | FB_COMB2 [label="COMBINE", shape=house];
22 | FB_COMB3 [label="COMBINE", shape=house];
23 | FB_COMP1 [label="\<", operator=LT, shape=box, type=int];
24 | FB_COMP2 [label="!", operator=NOT, shape=box, type=bool];
25 | }
26 |
27 | subgraph cluster_4 {
28 | color="#aaccf4";
29 | penwidth=2;
30 | IE36_CC1 [label=1, shape=circle];
31 | IE36_CC2 [label=1, shape=circle];
32 | IE36_CC3 [label=0, shape=circle];
33 | IE36_CC4 [label="T", shape=circle];
34 | IE36_COMP1 [label="+", operator=ADD, shape=box, type=int];
35 | IE36_COMP2 [label="+", operator=ADD, shape=box, type=int];
36 | }
37 |
38 | subgraph cluster_5 {
39 | color="#aaccf4";
40 | penwidth=2;
41 | IT_CC1 [label="T", shape=circle];
42 | IT_ML1 [label="m", shape=invtriangle, type=int];
43 | IT_COMB1 [label="COMBINE", shape=house];
44 | IT_COMB2 [label="COMBINE", shape=house];
45 | IT_COMB3 [label="COMBINE", shape=house];
46 | IT_COMP1 [label="\<", operator=LT, shape=box, type=int];
47 | IT_COMP2 [label="!", operator=NOT, shape=box, type=int];
48 | }
49 |
50 | subgraph cluster_6 {
51 | color="#aaccf4";
52 | penwidth=2;
53 | IT12_CC1 [label=1, shape=circle];
54 | IT12_CC2 [label="T", shape=circle];
55 | IT12_COMP1 [label="+", operator=ADD, shape=box, type=int];
56 | IT12_COMP2 [label="*", operator=MUL, shape=box, type=int];
57 | IT12_COMP3 [label="+", operator=ADD, shape=box, type=int];
58 | IT12_ML1 [label="A", shape=invtriangle, type=int];
59 | IT12_ML2 [label="B", shape=invtriangle, type=int];
60 | IT12_ML3 [label="B", shape=invtriangle, type=int];
61 | IT12_MS1 [label="B", shape=triangle];
62 | IT12_COMB1 [label="COMBINE", shape=house];
63 | }
64 |
65 | subgraph cluster_7 {
66 | color="#aaccf4";
67 | penwidth=2;
68 | IE_CC1 [label=1, shape=circle];
69 | IE_CC2 [label=1, shape=circle];
70 | IE_CC3 [label="T", shape=circle];
71 | IE_ML1 [label="alpha", shape=invtriangle, type=int];
72 | IE_ML2 [label="B", shape=invtriangle, type=int];
73 | IE_COMP1 [label="+", operator=ADD, shape=box, type=int];
74 | IE_COMP2 [label="+", operator=ADD, shape=box, type=int];
75 | IE_COMP3 [label="*", operator=MUL, shape=box, type=int];
76 | IE_MS1 [label="B", shape=triangle];
77 | IE_COMB1 [label="COMBINE", shape=house];
78 | }
79 |
80 | subgraph cluster_8 {
81 | color="#aaccf4";
82 | penwidth=2;
83 | F_MUX1 [label="MUX", shape=invtrapezium];
84 | F_MUX2 [label="MUX", shape=invtrapezium];
85 | F_MUX3 [label="MUX", shape=invtrapezium];
86 | F_XOR1 [label="XOR", shape=hexagon];
87 | F_MS1 [label="k", shape=triangle];
88 | F_MS2 [label="i", shape=triangle];
89 | F_MS3 [label="j", shape=triangle];
90 | }
91 |
92 | E_OC2 -> E_COMP1 [label="RHS"];
93 | E_OC3 -> E_COMP1 [label="LHS"];
94 | FB_ML1 -> FB_COMB1 [style=dotted];
95 | FB_ML1 -> FB_COMP1 [label="RHS"];
96 | FB_COMB1 -> FB_COMB3;
97 | FB_COMB1 -> FB_COMB2;
98 | FB_COMP1 -> FB_COMP2;
99 | FB_COMP1 -> FB_COMB2;
100 | FB_COMP2 -> FB_COMB3;
101 | FB_CC1 -> FB_COMP1 [style=dotted];
102 | FB_CC1 -> FB_COMP2 [style=dotted];
103 | IE36_CC1 -> IE36_COMP1 [label="RHS"];
104 | IE36_COMP1 -> IE36_COMP2 [label="LHS"];
105 | IE36_CC2 -> IE36_COMP2 [label="RHS"];
106 | IE36_CC4 -> IE36_COMP1 [style=dotted];
107 | IE36_CC4 -> IE36_COMP2 [style=dotted];
108 | IT_ML1 -> IT_COMB1 [style=dotted];
109 | IT_ML1 -> IT_COMP1 [label="RHS"];
110 | IT_COMB1 -> IT_COMB2;
111 | IT_COMB1 -> IT_COMB3;
112 | IT_COMP1 -> IT_COMB2;
113 | IT_COMP1 -> IT_COMP2;
114 | IT_COMP2 -> IT_COMB3;
115 | IT_CC1 -> IT_COMP1 [style=dotted];
116 | IT_CC1 -> IT_COMP2 [style=dotted];
117 | IT12_CC1 -> IT12_COMP1 [label="RHS"];
118 | IT12_ML1 -> IT12_COMP2 [label="LHS"];
119 | IT12_ML1 -> IT12_COMB1 [style=dotted];
120 | IT12_ML2 -> IT12_COMB1 [style=dotted];
121 | IT12_ML2 -> IT12_COMP2 [label="RHS"];
122 | IT12_COMP2 -> IT12_COMP3 [label="RHS"];
123 | IT12_ML3 -> IT12_COMP3 [label="LHS"];
124 | IT12_ML3 -> IT12_COMB1 [style=dotted];
125 | IT12_COMP3 -> IT12_MS1;
126 | IT12_MS1 -> IT12_COMB1 [style=dotted];
127 | IT12_CC2 -> IT12_COMP1 [style=dotted];
128 | IT12_CC2 -> IT12_COMP2 [style=dotted];
129 | IT12_CC2 -> IT12_COMP3 [style=dotted];
130 | IE_CC1 -> IE_COMP1 [label="RHS"];
131 | IE_CC2 -> IE_COMP2 [label="RHS"];
132 | IE_ML1 -> IE_COMP3 [label="LHS"];
133 | IE_ML1 -> IE_COMB1 [style=dotted];
134 | IE_ML2 -> IE_COMP3 [label="RHS"];
135 | IE_ML2 -> IE_COMB1 [style=dotted];
136 | IE_COMP3 -> IE_MS1;
137 | IE_MS1 -> IE_COMB1 [style=dotted];
138 | IE_CC3 -> IE_COMP1 [style=dotted];
139 | IE_CC3 -> IE_COMP2 [style=dotted];
140 | IE_CC3 -> IE_COMP3 [style=dotted];
141 | F_MUX1 -> F_MS3;
142 | F_MUX2 -> F_MS2;
143 | F_MUX3 -> F_MS1;
144 | F_XOR1 -> F_MS1 [style=dotted];
145 | F_XOR1 -> F_MS2 [style=dotted];
146 | F_XOR1 -> F_MS3 [style=dotted];
147 | E_OC1 -> E_COMP1 [style=dotted];
148 | E_OC1 -> FB_ML1 [style=dotted];
149 | E_OC1 -> FB_COMB1 [style=dotted];
150 | E_OC4 -> FB_COMP1 [label="LHS"];
151 | E_OC3 -> IE36_COMP1 [label="LHS"];
152 | E_COMP1 -> IT_COMP1 [label="LHS"];
153 | FB_COMB2 -> IT_ML1 [style=dotted];
154 | FB_COMB2 -> IT_COMB1 [style=dotted];
155 | E_OC3 -> IT12_ML1 [label="[1]"];
156 | E_OC3 -> IT12_ML3 [label="[0]"];
157 | E_OC3 -> IT12_MS1 [label="[0]"];
158 | E_OC4 -> IT12_ML2 [label="[1]"];
159 | E_OC4 -> IT12_ML3 [label="[1]"];
160 | E_OC4 -> IT12_MS1 [label="[1]"];
161 | E_COMP1 -> IT12_ML1 [label="[0]"];
162 | E_COMP1 -> IT12_ML2 [label="[0]"];
163 | E_COMP1 -> IT12_COMP1 [label="LHS"];
164 | IT_COMB2 -> IT12_ML1 [style=dotted];
165 | IT_COMB2 -> IT12_ML2 [style=dotted];
166 | IT_COMB2 -> IT12_ML3 [style=dotted];
167 | IT_COMB2 -> IT12_MS1 [style=dotted];
168 | IT_COMB2 -> IT12_COMB1 [style=dotted];
169 | E_OC3 -> IE_ML2 [label="[0]"];
170 | E_OC3 -> IE_COMP1 [label="LHS"];
171 | E_OC3 -> IE_MS1 [label="[0]"];
172 | E_OC4 -> IE_ML2 [label="[1]"];
173 | E_OC4 -> IE_COMP2 [label="LHS"];
174 | E_OC4 -> IE_MS1 [label="[1]"];
175 | IT_COMB3 -> IE_ML1 [style=dotted];
176 | IT_COMB3 -> IE_ML2 [style=dotted];
177 | IT_COMB3 -> IE_MS1 [style=dotted];
178 | IT_COMB3 -> IE_COMB1 [style=dotted];
179 | FB_COMB3 -> F_XOR1 [style=dotted];
180 | FB_COMB3 -> F_MUX2 [label="i1", style=dotted];
181 | FB_COMB3 -> F_MUX1 [label="j1", style=dotted];
182 | FB_COMB3 -> F_MUX3 [label="k1", style=dotted];
183 | IE36_COMP1 -> F_MUX2 [label="i1"];
184 | IE36_CC3 -> F_MUX1 [label="j1"];
185 | IE36_COMP2 -> F_MUX3 [label="k1"];
186 | E_OC3 -> F_MUX2 [label="i2"];
187 | E_OC4 -> F_MUX1 [label="j2"];
188 | IT12_COMP1 -> F_MUX3 [label="k2"];
189 | IT12_COMB1 -> F_XOR1 [style=dotted];
190 | IT12_COMB1 -> F_MUX2 [label="i2", style=dotted];
191 | IT12_COMB1 -> F_MUX1 [label="j2", style=dotted];
192 | IT12_COMB1 -> F_MUX3 [label="k2", style=dotted];
193 | E_OC3 -> F_MUX2 [label="i3"];
194 | IE_COMP2 -> F_MUX1 [label="j3"];
195 | IE_COMP1 -> F_MUX3 [label="k3"];
196 | IE_COMB1 -> F_XOR1 [style=dotted];
197 | IE_COMB1 -> F_MUX2 [label="i3", style=dotted];
198 | IE_COMB1 -> F_MUX1 [label="j3", style=dotted];
199 | IE_COMB1 -> F_MUX3 [label="k3", style=dotted];
200 | }
201 |
--------------------------------------------------------------------------------
/header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffreyspaan/coolname/367db6afcab933d9dd494a49dbe51c75007fbd9f/header.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | dearpygui==0.6.415
2 | pydot==1.4.2
3 |
--------------------------------------------------------------------------------
/run.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from coolname.coolname import main
4 |
5 | if __name__ == '__main__':
6 | main()
--------------------------------------------------------------------------------