+
project Name
@@ -163,9 +164,9 @@
diff --git a/v1/src/router/index.ts b/v1/src/router/index.ts
index 730aea09..0a604dab 100644
--- a/v1/src/router/index.ts
+++ b/v1/src/router/index.ts
@@ -2,7 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
import simulatorHandler from '../pages/simulatorHandler.vue'
import Embed from '../pages/embed.vue'
-const routes = [
+export const routes = [
{
path: '/',
redirect: '/simulatorvue', // @TODO: update later back to /simulator
diff --git a/v1/src/simulator/spec/bitConvertor.spec.js b/v1/src/simulator/spec/bitConvertor.spec.js
new file mode 100644
index 00000000..157db0c5
--- /dev/null
+++ b/v1/src/simulator/spec/bitConvertor.spec.js
@@ -0,0 +1,88 @@
+import { setup } from '../src/setup';
+import { bitConverterDialog, setBaseValues, setupBitConvertor } from '../src/utils';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
+
+describe('data dir working', () => {
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
+
+ // Open BitConvertor Dialog
+ test('bitConvertor Dialog working', () => {
+ expect(() => bitConverterDialog()).not.toThrow();
+ });
+
+ test('function setupBitConvertor working', () => {
+ expect(() => setupBitConvertor()).not.toThrow();
+ });
+
+ test('function setBaseValues working', () => {
+ const randomBaseValue = Math.floor(Math.random() * 100);
+ console.log('Testing for Base Value --> ', randomBaseValue);
+ expect(() => setBaseValues(randomBaseValue)).not.toThrow();
+ });
+});
diff --git a/v1/src/simulator/spec/circuits/Decoders-plexers-circuitdata.json b/v1/src/simulator/spec/circuits/Decoders-plexers-circuitdata.json
index bf601345..90b10612 100644
--- a/v1/src/simulator/spec/circuits/Decoders-plexers-circuitdata.json
+++ b/v1/src/simulator/spec/circuits/Decoders-plexers-circuitdata.json
@@ -1,1109 +1,1337 @@
{
- "name": "Decoders and Plexers",
- "timePeriod": 500,
- "clockEnabled": true,
- "projectId": "RVvp1Qq4hf3eVcfUO7sE",
- "focussedCircuit": 11597572508,
- "orderedTabs": ["11597572508"],
- "scopes": [
- {
- "layout": {
- "width": 100,
- "height": 280,
- "title_x": 50,
- "title_y": 13,
- "titleEnabled": true
+ "name": "Decoder&Plexers",
+ "timePeriod": 500,
+ "clockEnabled": true,
+ "projectId": "hWmIAEfeaUjXbtHfKS15",
+ "focussedCircuit": 11597572508,
+ "orderedTabs": [
+ "11597572508"
+ ],
+ "scopes": [
+ {
+ "layout": {
+ "width": 100,
+ "height": 540,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Control Signal",
+ "connections": [
+ 8
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 29
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2
+ ]
+ },
+ {
+ "x": 970,
+ "y": -60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3,
+ 9
+ ]
+ },
+ {
+ "x": 560,
+ "y": -60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8,
+ 17,
+ 29
+ ]
+ },
+ {
+ "x": 560,
+ "y": 590,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 16
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Control Signal",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 860,
+ "y": -150,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 0,
+ 16,
+ 20
+ ]
+ },
+ {
+ "x": 860,
+ "y": 30,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 11,
+ 15
+ ]
+ },
+ {
+ "x": 560,
+ "y": 50,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 9,
+ 10,
+ 14
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13
+ ]
+ },
+ {
+ "x": 820,
+ "y": -150,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5,
+ 15,
+ 37
+ ]
+ },
+ {
+ "x": 780,
+ "y": -130,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 1,
+ 6,
+ 25
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 26
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 28
+ ]
+ },
+ {
+ "x": 780,
+ "y": 410,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21,
+ 31
+ ]
+ },
+ {
+ "x": 820,
+ "y": 620,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22,
+ 37
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 24
+ ]
+ },
+ {
+ "x": 560,
+ "y": -190,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4,
+ 9
+ ]
+ },
+ {
+ "x": -10,
+ "y": -30,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 37
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 25
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 39
+ ]
+ },
+ {
+ "x": 30,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 41
+ ]
+ },
+ {
+ "x": 30,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 42
+ ]
+ },
+ {
+ "x": 10,
+ "y": 50,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40
+ ]
+ },
+ {
+ "x": 820,
+ "y": 390,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20,
+ 26,
+ 30
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 36
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35
+ ]
+ },
+ {
+ "x": -20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "Input",
+ "connections": [
+ 60
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Output",
+ "connections": [
+ 47
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": "2",
+ "label": "Bit Selector",
+ "connections": [
+ 46
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": "2",
+ "label": "",
+ "connections": [
+ 45
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 44
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 51
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 52
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 53
+ ]
+ },
+ {
+ "x": 250,
+ "y": 290,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 48,
+ 57,
+ 60
+ ]
+ },
+ {
+ "x": 40,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 49
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 50
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 57
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 58
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 59
+ ]
+ },
+ {
+ "x": 250,
+ "y": 410,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 51,
+ 54
+ ]
+ },
+ {
+ "x": 40,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 55
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 56
+ ]
+ },
+ {
+ "x": 40,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 43,
+ 51
+ ]
+ }
+ ],
+ "id": 11597572508,
+ "name": "Main",
+ "Input": [
+ {
+ "x": 480,
+ "y": -190,
+ "objectType": "Input",
+ "label": "s",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 4
},
- "verilogMetadata": {
- "isVerilogCircuit": false,
- "isMainCircuit": false,
- "code": "// Write Some Verilog Code Here!",
- "subCircuitScopeIds": []
+ "values": {
+ "state": 1
},
- "allNodes": [
- {
- "x": -10,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [14]
- },
- {
- "x": -10,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [5]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [6]
- },
- {
- "x": 0,
- "y": 20,
- "type": 0,
- "bitWidth": 1,
- "label": "Control Signal",
- "connections": [24]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [14]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [1]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [2]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [15]
- },
- {
- "x": -10,
- "y": -10,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [12]
- },
- {
- "x": -10,
- "y": 10,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [13]
- },
- {
- "x": 0,
- "y": 20,
- "type": 0,
- "bitWidth": 1,
- "label": "Control Signal",
- "connections": [11]
- },
- {
- "x": 80,
- "y": 510,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [10, 25]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [8]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [9]
- },
- {
- "x": -30,
- "y": 130,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [0, 4, 15]
- },
- {
- "x": -30,
- "y": 340,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [7, 14]
- },
- {
- "x": -20,
- "y": 0,
- "type": 0,
- "bitWidth": 2,
- "label": "Input",
- "connections": [20]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "Output",
- "connections": [19]
- },
- {
- "x": 0,
- "y": 20,
- "type": 0,
- "bitWidth": 1,
- "label": "Bit Selector",
- "connections": [26]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [17]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 2,
- "label": "",
- "connections": [16]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [22]
- },
- {
- "x": -180,
- "y": 160,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [21, 23]
- },
- {
- "x": -180,
- "y": 220,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [22, 24, 25]
- },
- {
- "x": 90,
- "y": 220,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [3, 23]
- },
- {
- "x": -180,
- "y": 510,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [11, 23, 27]
- },
- {
- "x": 70,
- "y": 700,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [18, 27]
- },
- {
- "x": -180,
- "y": 700,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [25, 26]
- },
- {
- "x": -10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [33]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [32]
- },
- {
- "x": 20,
- "y": 20,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [31]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [30]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [29]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [28]
- },
- {
- "x": -10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [39]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [37]
- },
- {
- "x": 20,
- "y": 20,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [38]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [35]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [36]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [34]
- },
- {
- "x": -10,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [46]
- },
- {
- "x": -10,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [47]
- },
- {
- "x": 30,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [45]
- },
- {
- "x": 10,
- "y": 30,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [44]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [43]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [42]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [40]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [41]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [53]
- },
- {
- "x": -10,
- "y": -10,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [51]
- },
- {
- "x": -10,
- "y": 10,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [52]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [49]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [50]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [48]
- }
- ],
- "id": 11597572508,
- "name": "Main",
- "Input": [
- {
- "x": -70,
- "y": 130,
- "objectType": "Input",
- "label": "inp1",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 4
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 60,
- "id": "cZW4OLLsTA1aBoRSmHxv"
- }
- ]
- }
- },
- {
- "x": -70,
- "y": 150,
- "objectType": "Input",
- "label": "inp2",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 5
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 20,
- "id": "OhBFKFzir02JVzBVOV44"
- }
- ]
- }
- },
- {
- "x": -30,
- "y": 630,
- "objectType": "Input",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 20
- },
- "values": {
- "state": 3
- },
- "constructorParamaters": [
- "RIGHT",
- 2,
- {
- "x": 0,
- "y": 120,
- "id": "Tci49l79hiLHSfxqSPhk"
- }
- ]
- }
- },
- {
- "x": -360,
- "y": 160,
- "objectType": "Input",
- "label": "s",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 21
- },
- "values": {
- "state": 0
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 40,
- "id": "2jYcmNNFpmoq6jcELh8X"
- }
- ]
- }
- },
- {
- "x": -10,
- "y": 840,
- "objectType": "Input",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 33
- },
- "values": {
- "state": 0
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 80,
- "id": "wUbTZgbmrEStf17qxgOw"
- }
- ]
- }
- },
- {
- "x": 0,
- "y": 1030,
- "objectType": "Input",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 39
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 100,
- "id": "hiFGtGajuArxucFOfydA"
- }
- ]
- }
- },
- {
- "x": -550,
- "y": 310,
- "objectType": "Input",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 46
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 140,
- "id": "6br60gi40FN03qZRFG9W"
- }
- ]
- }
- },
- {
- "x": -550,
- "y": 330,
- "objectType": "Input",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 47
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 160,
- "id": "EcNRmJVcoyFZdMUmGwQw"
- }
- ]
- }
- },
- {
- "x": -600,
- "y": 680,
- "objectType": "Input",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 53
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 180,
- "id": "eAluIwGbrt2vmFD37xUb"
- }
- ]
- }
- }
- ],
- "Output": [
- {
- "x": 250,
- "y": 140,
- "objectType": "Output",
- "label": "out1",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 6
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 40,
- "id": "PQtMRkU1V36zoiUZaKnC"
- }
- ]
- }
- },
- {
- "x": 340,
- "y": 330,
- "objectType": "Output",
- "label": "out3",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 12
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 20,
- "id": "rl7YenrdGRoBr9BXA2Ee"
- }
- ]
- }
- },
- {
- "x": 340,
- "y": 350,
- "objectType": "Output",
- "label": "out4",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 13
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 60,
- "id": "gPrg5glyUDxsQmGldTow"
- }
- ]
- }
- },
- {
- "x": 260,
- "y": 630,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 19
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 80,
- "id": "qqnDrlsm0T8y1dyyiGlL"
- }
- ]
- }
- },
- {
- "x": 270,
- "y": 860,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 31
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 120,
- "id": "2smYfkmptbhEZ2gFBMmf"
- }
- ]
- }
- },
- {
- "x": 270,
- "y": 840,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 32
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 100,
- "id": "45NWNA9b3l54VZE5cFYS"
- }
- ]
- }
- },
- {
- "x": 220,
- "y": 1030,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 37
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 140,
- "id": "COIaU2CIfnmcZ8h0Nxpq"
- }
- ]
- }
- },
- {
- "x": 220,
- "y": 1050,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 38
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 160,
- "id": "bJ7CLsYt9Johbanua2d4"
- }
- ]
- }
- },
- {
- "x": -460,
- "y": 400,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 44
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 180,
- "id": "Of7qPmfBvyW9mhiLkfpN"
- }
- ]
- }
- },
- {
- "x": -290,
- "y": 320,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 45
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 200,
- "id": "LLwXovDSOe6rplHPIDhv"
- }
- ]
- }
- },
- {
- "x": -310,
- "y": 670,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 51
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 220,
- "id": "Yo4Zo5P6gClWQJZWt5DF"
- }
- ]
- }
- },
- {
- "x": -310,
- "y": 690,
- "objectType": "Output",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 52
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 240,
- "id": "T86CxN5DtKbZtDaZXSMx"
- }
- ]
- }
- }
- ],
- "Multiplexer": [
- {
- "x": 90,
- "y": 140,
- "objectType": "Multiplexer",
- "label": "multiplexer",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 1, 1],
- "nodes": {
- "inp": [0, 1],
- "output1": 2,
- "controlSignalInput": 3
- }
- }
- }
- ],
- "BitSelector": [
- {
- "x": 70,
- "y": 630,
- "objectType": "BitSelector",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "nodes": {
- "inp1": 16,
- "output1": 17,
- "bitSelectorInp": 18
- },
- "constructorParamaters": ["RIGHT", 2, 1]
- }
- }
- ],
- "Demultiplexer": [
- {
- "x": 80,
- "y": 340,
- "objectType": "Demultiplexer",
- "label": "demultiplexer",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["LEFT", 1, 1],
- "nodes": {
- "output1": [8, 9],
- "input": 7,
- "controlSignalInput": 10
- }
- }
- }
- ],
- "MSB": [
- {
- "x": 70,
- "y": 840,
- "objectType": "MSB",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "nodes": {
- "inp1": 28,
- "output1": 29,
- "enable": 30
- },
- "constructorParamaters": ["RIGHT", 1]
- }
- }
- ],
- "LSB": [
- {
- "x": 70,
- "y": 1030,
- "objectType": "LSB",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "nodes": {
- "inp1": 34,
- "output1": 35,
- "enable": 36
- },
- "constructorParamaters": ["RIGHT", 1]
- }
- }
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "af8X6iUZ1TNVcEuYsobR"
+ }
+ ]
+ }
+ },
+ {
+ "x": 730,
+ "y": -150,
+ "objectType": "Input",
+ "label": "inp1",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 5
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 80,
+ "id": "AHg5Ngs8KrHtKKUUBv5o"
+ }
+ ]
+ }
+ },
+ {
+ "x": 730,
+ "y": -130,
+ "objectType": "Input",
+ "label": "inp2",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 6
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "0uCn6zjaOWINyTt3INWL"
+ }
+ ]
+ }
+ },
+ {
+ "x": 750,
+ "y": 430,
+ "objectType": "Input",
+ "label": "inp3",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 38
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "OjD26bycgCZOCebnr0Ta"
+ }
+ ]
+ }
+ },
+ {
+ "x": 750,
+ "y": 450,
+ "objectType": "Input",
+ "label": "inp4",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 39
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 100,
+ "id": "YdXUBNPghcKOcTzkSNxJ"
+ }
+ ]
+ }
+ },
+ {
+ "x": 300,
+ "y": 110,
+ "objectType": "Input",
+ "label": "CS",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 46
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "UP",
+ "2",
+ {
+ "x": 0,
+ "y": 120,
+ "id": "W3XYx9tc8fIFjVMFNfU4"
+ }
+ ]
+ }
+ },
+ {
+ "x": 210,
+ "y": 20,
+ "objectType": "Input",
+ "label": "inp5",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 60
+ },
+ "values": {
+ "state": 8
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 4,
+ {
+ "x": 0,
+ "y": 140,
+ "id": "fKHb7DuWJcS9KM2fSxKT"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 1130,
+ "y": -140,
+ "objectType": "Output",
+ "label": "out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 7
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 280,
+ "id": "qkQ6ZVtFDuQN5LjoFSAx"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1130,
+ "y": 20,
+ "objectType": "Output",
+ "label": "out2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 18
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "vRfw4YkouGy4laNyoTHO"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1130,
+ "y": 40,
+ "objectType": "Output",
+ "label": "out3",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 19
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "m1fSssWAIUVKndqPS8U1"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1040,
+ "y": 610,
+ "objectType": "Output",
+ "label": "out11",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 27
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 260,
+ "id": "uN0pAvVNRJQlNB4Vc9o0"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1040,
+ "y": 630,
+ "objectType": "Output",
+ "label": "out12",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 28
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 200,
+ "id": "5UVbtIsq3uzOx0b1RtVW"
+ }
+ ]
+ }
+ },
+ {
+ "x": 940,
+ "y": 540,
+ "objectType": "Output",
+ "label": "en",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 40
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 220,
+ "id": "2xTmvrisBijPkcsbt8lX"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1090,
+ "y": 410,
+ "objectType": "Output",
+ "label": "out9",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 41
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 160,
+ "id": "Jh30ULWWwan7JgfJXssO"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1090,
+ "y": 430,
+ "objectType": "Output",
+ "label": "out10",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 42
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 180,
+ "id": "3RzXrQjoiihgZROY8zOw"
+ }
+ ]
+ }
+ },
+ {
+ "x": 440,
+ "y": 20,
+ "objectType": "Output",
+ "label": "out13",
+ "direction": "LEFT",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 47
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 240,
+ "id": "i9MpQKKTbqxk9t7uOyol"
+ }
+ ]
+ }
+ },
+ {
+ "x": 430,
+ "y": 290,
+ "objectType": "Output",
+ "label": "out4",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 52
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 4,
+ {
+ "x": 100,
+ "y": 60,
+ "id": "Nl8jdW1Ovj3hvi0lyLd6"
+ }
+ ]
+ }
+ },
+ {
+ "x": 400,
+ "y": 310,
+ "objectType": "Output",
+ "label": "out5",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 53
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 80,
+ "id": "lSTBjSRHvf3uvq8AI5FR"
+ }
+ ]
+ }
+ },
+ {
+ "x": 380,
+ "y": 410,
+ "objectType": "Output",
+ "label": "out6",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 58
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 4,
+ {
+ "x": 100,
+ "y": 100,
+ "id": "xfXE7U7J0IRm1FVEzw3I"
+ }
+ ]
+ }
+ },
+ {
+ "x": 350,
+ "y": 430,
+ "objectType": "Output",
+ "label": "out7",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 59
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 120,
+ "id": "0tRtiePfdUKapjpaz8uy"
+ }
+ ]
+ }
+ }
+ ],
+ "Multiplexer": [
+ {
+ "x": 970,
+ "y": -140,
+ "objectType": "Multiplexer",
+ "label": "Multiplexer",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ 1
],
- "PriorityEncoder": [
- {
- "x": -480,
- "y": 320,
- "objectType": "PriorityEncoder",
- "label": "",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "nodes": {
- "inp1": [40, 41],
- "output1": [42],
- "enable": 43
- },
- "constructorParamaters": ["RIGHT", 1]
- }
- }
+ "nodes": {
+ "inp": [
+ 0,
+ 1
+ ],
+ "output1": 2,
+ "controlSignalInput": 3
+ }
+ }
+ }
+ ],
+ "BitSelector": [
+ {
+ "x": 300,
+ "y": 20,
+ "objectType": "BitSelector",
+ "label": "bit-selector",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "inp1": 43,
+ "output1": 44,
+ "bitSelectorInp": 45
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ "4",
+ "2"
+ ]
+ }
+ }
+ ],
+ "Demultiplexer": [
+ {
+ "x": 980,
+ "y": 30,
+ "objectType": "Demultiplexer",
+ "label": "Demultiplexer",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ 1
],
- "Decoder": [
- {
- "x": -480,
- "y": 680,
- "objectType": "Decoder",
- "label": "",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["LEFT", 1],
- "nodes": {
- "output1": [49, 50],
- "input": 48
- }
- }
- }
+ "nodes": {
+ "output1": [
+ 12,
+ 13
+ ],
+ "input": 11,
+ "controlSignalInput": 14
+ }
+ }
+ }
+ ],
+ "MSB": [
+ {
+ "x": 320,
+ "y": 290,
+ "objectType": "MSB",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "inp1": 48,
+ "output1": 49,
+ "enable": 50
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 4
+ ]
+ }
+ }
+ ],
+ "LSB": [
+ {
+ "x": 320,
+ "y": 410,
+ "objectType": "LSB",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "inp1": 54,
+ "output1": 55,
+ "enable": 56
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 4
+ ]
+ }
+ }
+ ],
+ "PriorityEncoder": [
+ {
+ "x": 920,
+ "y": 420,
+ "objectType": "PriorityEncoder",
+ "label": "priority encoder",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "inp1": [
+ 30,
+ 31,
+ 32,
+ 33
+ ],
+ "output1": [
+ 34,
+ 35
+ ],
+ "enable": 36
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 2
+ ]
+ }
+ }
+ ],
+ "Decoder": [
+ {
+ "x": 950,
+ "y": 620,
+ "objectType": "Decoder",
+ "label": "Decoder",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "LEFT",
+ 1
],
- "restrictedCircuitElementsUsed": [],
- "nodes": [11, 14, 15, 22, 23, 24, 25, 26, 27]
+ "nodes": {
+ "output1": [
+ 23,
+ 24
+ ],
+ "input": 22
+ }
+ }
}
- ]
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 8,
+ 9,
+ 10,
+ 15,
+ 16,
+ 17,
+ 20,
+ 21,
+ 25,
+ 26,
+ 29,
+ 37,
+ 51,
+ 57
+ ]
+ }
+ ]
}
diff --git a/v1/src/simulator/spec/circuits/alu-circuitdata.json b/v1/src/simulator/spec/circuits/alu-circuitdata.json
new file mode 100644
index 00000000..cd350e17
--- /dev/null
+++ b/v1/src/simulator/spec/circuits/alu-circuitdata.json
@@ -0,0 +1,8377 @@
+{
+ "name": "ALU-74LS181",
+ "timePeriod": 500,
+ "clockEnabled": true,
+ "projectId": "eWFjA0GCvFw4aqbmWcc4",
+ "focussedCircuit": 33755305138,
+ "orderedTabs": [
+ "33755305138",
+ "35784513673"
+ ],
+ "scopes": [
+ {
+ "layout": {
+ "width": 100,
+ "height": 300,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 36
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 54
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 29
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 52
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 28
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 51
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 39
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 45
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 48
+ ]
+ },
+ {
+ "x": 750,
+ "y": 180,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3,
+ 6,
+ 73
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23
+ ]
+ },
+ {
+ "x": 740,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5,
+ 22,
+ 24
+ ]
+ },
+ {
+ "x": 650,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23,
+ 25,
+ 39
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 24
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": 650,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 26,
+ 28,
+ 29
+ ]
+ },
+ {
+ "x": 620,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13,
+ 27
+ ]
+ },
+ {
+ "x": 690,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8,
+ 27
+ ]
+ },
+ {
+ "x": 700,
+ "y": 160,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2,
+ 9,
+ 82
+ ]
+ },
+ {
+ "x": 540,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19,
+ 33
+ ]
+ },
+ {
+ "x": 520,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18,
+ 33
+ ]
+ },
+ {
+ "x": 530,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31,
+ 32,
+ 34
+ ]
+ },
+ {
+ "x": 530,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33,
+ 35,
+ 37
+ ]
+ },
+ {
+ "x": 710,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 10,
+ 34,
+ 36
+ ]
+ },
+ {
+ "x": 730,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4,
+ 35
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34
+ ]
+ },
+ {
+ "x": 580,
+ "y": 120,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 0,
+ 16,
+ 90
+ ]
+ },
+ {
+ "x": 560,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15,
+ 24
+ ]
+ },
+ {
+ "x": 600,
+ "y": 140,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 1,
+ 12,
+ 92
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 53
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 55
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 366
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 49
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 50
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 364
+ ]
+ },
+ {
+ "x": 530,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20,
+ 49
+ ]
+ },
+ {
+ "x": 560,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 44,
+ 48
+ ]
+ },
+ {
+ "x": 580,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 46,
+ 51
+ ]
+ },
+ {
+ "x": 610,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 14,
+ 50
+ ]
+ },
+ {
+ "x": 700,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 11,
+ 53
+ ]
+ },
+ {
+ "x": 710,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 41,
+ 52
+ ]
+ },
+ {
+ "x": 740,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7,
+ 55
+ ]
+ },
+ {
+ "x": 730,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 42,
+ 54
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 88
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 75
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 73
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 106
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 81
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 82
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 87
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 104
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 92
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 80
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 103
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 91
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 90
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 97
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 84
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 83
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 100
+ ]
+ },
+ {
+ "x": 450,
+ "y": 180,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21,
+ 58,
+ 125
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 75
+ ]
+ },
+ {
+ "x": 440,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 57,
+ 74,
+ 76
+ ]
+ },
+ {
+ "x": 350,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 75,
+ 77,
+ 91
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 76
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 79
+ ]
+ },
+ {
+ "x": 350,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 78,
+ 80,
+ 81
+ ]
+ },
+ {
+ "x": 320,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 65,
+ 79
+ ]
+ },
+ {
+ "x": 390,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 60,
+ 79
+ ]
+ },
+ {
+ "x": 400,
+ "y": 160,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30,
+ 61,
+ 134
+ ]
+ },
+ {
+ "x": 240,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 71,
+ 85
+ ]
+ },
+ {
+ "x": 220,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 70,
+ 85
+ ]
+ },
+ {
+ "x": 230,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 83,
+ 84,
+ 86
+ ]
+ },
+ {
+ "x": 230,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 85,
+ 87,
+ 89
+ ]
+ },
+ {
+ "x": 410,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 62,
+ 86,
+ 88
+ ]
+ },
+ {
+ "x": 430,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 56,
+ 87
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 86
+ ]
+ },
+ {
+ "x": 280,
+ "y": 120,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38,
+ 68,
+ 142
+ ]
+ },
+ {
+ "x": 260,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 67,
+ 76
+ ]
+ },
+ {
+ "x": 300,
+ "y": 140,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40,
+ 64,
+ 144
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 105
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 107
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 352
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 101
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 69
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 102
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 353
+ ]
+ },
+ {
+ "x": 230,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 72,
+ 101
+ ]
+ },
+ {
+ "x": 260,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 96,
+ 100
+ ]
+ },
+ {
+ "x": 280,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 98,
+ 103
+ ]
+ },
+ {
+ "x": 310,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 66,
+ 102
+ ]
+ },
+ {
+ "x": 400,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 63,
+ 105
+ ]
+ },
+ {
+ "x": 410,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 93,
+ 104
+ ]
+ },
+ {
+ "x": 440,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 59,
+ 107
+ ]
+ },
+ {
+ "x": 430,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 94,
+ 106
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 140
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 127
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 125
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 158
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 133
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 134
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 139
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 156
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 144
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 132
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 155
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 143
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 142
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 149
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 136
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 135
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 152
+ ]
+ },
+ {
+ "x": 150,
+ "y": 180,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 73,
+ 110,
+ 177
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 127
+ ]
+ },
+ {
+ "x": 140,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 109,
+ 126,
+ 128
+ ]
+ },
+ {
+ "x": 50,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 127,
+ 129,
+ 143
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 128
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 131
+ ]
+ },
+ {
+ "x": 50,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 130,
+ 132,
+ 133
+ ]
+ },
+ {
+ "x": 20,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 117,
+ 131
+ ]
+ },
+ {
+ "x": 90,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 112,
+ 131
+ ]
+ },
+ {
+ "x": 100,
+ "y": 160,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 82,
+ 113,
+ 186
+ ]
+ },
+ {
+ "x": -60,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 123,
+ 137
+ ]
+ },
+ {
+ "x": -80,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 122,
+ 137
+ ]
+ },
+ {
+ "x": -70,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 135,
+ 136,
+ 138
+ ]
+ },
+ {
+ "x": -70,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 137,
+ 139,
+ 141
+ ]
+ },
+ {
+ "x": 110,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 114,
+ 138,
+ 140
+ ]
+ },
+ {
+ "x": 130,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 108,
+ 139
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 138
+ ]
+ },
+ {
+ "x": -20,
+ "y": 120,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 90,
+ 120,
+ 194
+ ]
+ },
+ {
+ "x": -40,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 119,
+ 128
+ ]
+ },
+ {
+ "x": 0,
+ "y": 140,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 92,
+ 116,
+ 196
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 157
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 159
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 347
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 153
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 121
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 154
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 348
+ ]
+ },
+ {
+ "x": -70,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 124,
+ 153
+ ]
+ },
+ {
+ "x": -40,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 148,
+ 152
+ ]
+ },
+ {
+ "x": -20,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 150,
+ 155
+ ]
+ },
+ {
+ "x": 10,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 118,
+ 154
+ ]
+ },
+ {
+ "x": 100,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 115,
+ 157
+ ]
+ },
+ {
+ "x": 110,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 145,
+ 156
+ ]
+ },
+ {
+ "x": 140,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 111,
+ 159
+ ]
+ },
+ {
+ "x": 130,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 146,
+ 158
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 192
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 179
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 177
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 210
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 185
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 186
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 191
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 208
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 196
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 184
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 207
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 195
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 194
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 201
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 188
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 187
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 204
+ ]
+ },
+ {
+ "x": -140,
+ "y": 180,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 125,
+ 162
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 179
+ ]
+ },
+ {
+ "x": -150,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 161,
+ 178,
+ 180
+ ]
+ },
+ {
+ "x": -240,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 179,
+ 181,
+ 195
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 180
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 183
+ ]
+ },
+ {
+ "x": -240,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 182,
+ 184,
+ 185
+ ]
+ },
+ {
+ "x": -270,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 169,
+ 183
+ ]
+ },
+ {
+ "x": -200,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 164,
+ 183
+ ]
+ },
+ {
+ "x": -190,
+ "y": 160,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 134,
+ 165
+ ]
+ },
+ {
+ "x": -350,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 175,
+ 189
+ ]
+ },
+ {
+ "x": -370,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 174,
+ 189
+ ]
+ },
+ {
+ "x": -360,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 187,
+ 188,
+ 190
+ ]
+ },
+ {
+ "x": -360,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 189,
+ 191,
+ 193
+ ]
+ },
+ {
+ "x": -180,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 166,
+ 190,
+ 192
+ ]
+ },
+ {
+ "x": -160,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 160,
+ 191
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 190
+ ]
+ },
+ {
+ "x": -310,
+ "y": 120,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 142,
+ 172
+ ]
+ },
+ {
+ "x": -330,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 171,
+ 180
+ ]
+ },
+ {
+ "x": -290,
+ "y": 140,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 144,
+ 168
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 209
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 211
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 246
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 205
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 173
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 206
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 253
+ ]
+ },
+ {
+ "x": -360,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 176,
+ 205
+ ]
+ },
+ {
+ "x": -330,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 200,
+ 204
+ ]
+ },
+ {
+ "x": -310,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 202,
+ 207
+ ]
+ },
+ {
+ "x": -280,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 170,
+ 206
+ ]
+ },
+ {
+ "x": -190,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 167,
+ 209
+ ]
+ },
+ {
+ "x": -180,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 197,
+ 208
+ ]
+ },
+ {
+ "x": -150,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 163,
+ 211
+ ]
+ },
+ {
+ "x": -160,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 198,
+ 210
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 214
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 235
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 212
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 238
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 238
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 235
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 219
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 218
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 232
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 290
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 236
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 237
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 228
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 229
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 230
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 248
+ ]
+ },
+ {
+ "x": -310,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 224,
+ 229
+ ]
+ },
+ {
+ "x": -300,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 225,
+ 228
+ ]
+ },
+ {
+ "x": -280,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 226,
+ 231
+ ]
+ },
+ {
+ "x": -270,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 230,
+ 244
+ ]
+ },
+ {
+ "x": -440,
+ "y": 710,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 220,
+ 233
+ ]
+ },
+ {
+ "x": -370,
+ "y": 710,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 232,
+ 439
+ ]
+ },
+ {
+ "x": -380,
+ "y": 510,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 253,
+ 437
+ ]
+ },
+ {
+ "x": -450,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 213,
+ 217,
+ 236
+ ]
+ },
+ {
+ "x": -320,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 222,
+ 235,
+ 240
+ ]
+ },
+ {
+ "x": -300,
+ "y": 510,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 223,
+ 253,
+ 283
+ ]
+ },
+ {
+ "x": -470,
+ "y": 560,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 215,
+ 216,
+ 239
+ ]
+ },
+ {
+ "x": -280,
+ "y": 560,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 238,
+ 241,
+ 456
+ ]
+ },
+ {
+ "x": -270,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 236,
+ 242,
+ 268
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 239
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 240
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 245
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 231
+ ]
+ },
+ {
+ "x": -260,
+ "y": 500,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 243,
+ 247,
+ 246
+ ]
+ },
+ {
+ "x": -170,
+ "y": 500,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 199,
+ 245,
+ 271
+ ]
+ },
+ {
+ "x": -360,
+ "y": 500,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 245,
+ 438
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 227
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 257
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 294
+ ]
+ },
+ {
+ "x": -140,
+ "y": 490,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 348,
+ 440
+ ]
+ },
+ {
+ "x": -120,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 284,
+ 441
+ ]
+ },
+ {
+ "x": -320,
+ "y": 510,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 203,
+ 234,
+ 237
+ ]
+ },
+ {
+ "x": 830,
+ "y": 490,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "3",
+ "connections": [
+ 361,
+ 397
+ ]
+ },
+ {
+ "x": 880,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "4",
+ "connections": [
+ 387,
+ 401
+ ]
+ },
+ {
+ "x": 870,
+ "y": 510,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "1",
+ "connections": [
+ 357,
+ 402
+ ]
+ },
+ {
+ "x": -270,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 249,
+ 258
+ ]
+ },
+ {
+ "x": -130,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 257,
+ 442
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 290
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 294
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 269
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 283
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 284
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 276
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 268
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 282
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 279
+ ]
+ },
+ {
+ "x": -40,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 240,
+ 265,
+ 269
+ ]
+ },
+ {
+ "x": 0,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 261,
+ 268,
+ 270
+ ]
+ },
+ {
+ "x": 30,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 269,
+ 342,
+ 452
+ ]
+ },
+ {
+ "x": 60,
+ "y": 500,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 246,
+ 349,
+ 453
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 278
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 305
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 298
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 280
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 264
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 281
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 272
+ ]
+ },
+ {
+ "x": -30,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 267,
+ 280
+ ]
+ },
+ {
+ "x": 0,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 275,
+ 279
+ ]
+ },
+ {
+ "x": 20,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 277,
+ 458
+ ]
+ },
+ {
+ "x": -20,
+ "y": 490,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 266,
+ 348,
+ 361
+ ]
+ },
+ {
+ "x": 10,
+ "y": 510,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 237,
+ 262,
+ 357
+ ]
+ },
+ {
+ "x": 20,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 252,
+ 263,
+ 457
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 297
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 293
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 301
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 302
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 307
+ ]
+ },
+ {
+ "x": -450,
+ "y": 820,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 221,
+ 259,
+ 291
+ ]
+ },
+ {
+ "x": -180,
+ "y": 820,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 290,
+ 292
+ ]
+ },
+ {
+ "x": -180,
+ "y": 780,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 291,
+ 293
+ ]
+ },
+ {
+ "x": -150,
+ "y": 780,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 286,
+ 292
+ ]
+ },
+ {
+ "x": -280,
+ "y": 810,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 250,
+ 260,
+ 295
+ ]
+ },
+ {
+ "x": -190,
+ "y": 810,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 294,
+ 296
+ ]
+ },
+ {
+ "x": -190,
+ "y": 770,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 295,
+ 297
+ ]
+ },
+ {
+ "x": -140,
+ "y": 770,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 285,
+ 296
+ ]
+ },
+ {
+ "x": 20,
+ "y": 810,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 274,
+ 299,
+ 427
+ ]
+ },
+ {
+ "x": -90,
+ "y": 810,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 298,
+ 300
+ ]
+ },
+ {
+ "x": -90,
+ "y": 770,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 299,
+ 301
+ ]
+ },
+ {
+ "x": -120,
+ "y": 770,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 287,
+ 300
+ ]
+ },
+ {
+ "x": -110,
+ "y": 780,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 288,
+ 303
+ ]
+ },
+ {
+ "x": -80,
+ "y": 780,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 302,
+ 304
+ ]
+ },
+ {
+ "x": -80,
+ "y": 820,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 303,
+ 358
+ ]
+ },
+ {
+ "x": 30,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 273,
+ 306
+ ]
+ },
+ {
+ "x": 170,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 305,
+ 445
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 289
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 342
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 362
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 335
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 346
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 345
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 349
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 350
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 351
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 338
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 357
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 344
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 356
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 355
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 337
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 343
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 361
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 360
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 336
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 332
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 331
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 333
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 334
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 339
+ ]
+ },
+ {
+ "x": 280,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 327,
+ 335
+ ]
+ },
+ {
+ "x": 290,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 326,
+ 336
+ ]
+ },
+ {
+ "x": 310,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 328,
+ 337
+ ]
+ },
+ {
+ "x": 320,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 329,
+ 338
+ ]
+ },
+ {
+ "x": 230,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 310,
+ 331
+ ]
+ },
+ {
+ "x": 280,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 325,
+ 332
+ ]
+ },
+ {
+ "x": 330,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 321,
+ 333
+ ]
+ },
+ {
+ "x": 380,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 316,
+ 334
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 330
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 368
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 358
+ ]
+ },
+ {
+ "x": 220,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 270,
+ 308,
+ 343
+ ]
+ },
+ {
+ "x": 270,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 322,
+ 342,
+ 344
+ ]
+ },
+ {
+ "x": 310,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 318,
+ 343,
+ 345
+ ]
+ },
+ {
+ "x": 360,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 312,
+ 344
+ ]
+ },
+ {
+ "x": 370,
+ "y": 560,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 311,
+ 385,
+ 456
+ ]
+ },
+ {
+ "x": 120,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 147,
+ 356,
+ 457
+ ]
+ },
+ {
+ "x": -30,
+ "y": 490,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 151,
+ 251,
+ 282
+ ]
+ },
+ {
+ "x": 380,
+ "y": 500,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 271,
+ 313,
+ 384
+ ]
+ },
+ {
+ "x": 390,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 314,
+ 356,
+ 383
+ ]
+ },
+ {
+ "x": 400,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 315,
+ 352,
+ 355
+ ]
+ },
+ {
+ "x": 420,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 95,
+ 351,
+ 382
+ ]
+ },
+ {
+ "x": 270,
+ "y": 470,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 99,
+ 354,
+ 362
+ ]
+ },
+ {
+ "x": 780,
+ "y": 470,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "5",
+ "connections": [
+ 353,
+ 394
+ ]
+ },
+ {
+ "x": 350,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 320,
+ 351,
+ 360
+ ]
+ },
+ {
+ "x": 340,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 319,
+ 347,
+ 350
+ ]
+ },
+ {
+ "x": 320,
+ "y": 510,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 256,
+ 283,
+ 317
+ ]
+ },
+ {
+ "x": 310,
+ "y": 820,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 304,
+ 341,
+ 359
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 358
+ ]
+ },
+ {
+ "x": 290,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 324,
+ 355,
+ 447
+ ]
+ },
+ {
+ "x": 280,
+ "y": 490,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 254,
+ 282,
+ 323
+ ]
+ },
+ {
+ "x": 240,
+ "y": 470,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 309,
+ 353,
+ 446
+ ]
+ },
+ {
+ "x": 470,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 364,
+ 448
+ ]
+ },
+ {
+ "x": 570,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 47,
+ 363,
+ 410
+ ]
+ },
+ {
+ "x": 490,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 381,
+ 449
+ ]
+ },
+ {
+ "x": 720,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 43,
+ 389,
+ 411
+ ]
+ },
+ {
+ "x": 910,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "8",
+ "connections": [
+ 404,
+ 412
+ ]
+ },
+ {
+ "x": 320,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 340,
+ 369
+ ]
+ },
+ {
+ "x": 480,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 368,
+ 450
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 383
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 384
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 382
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 381
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 390
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 386
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 385
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 387
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 388
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 389
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 428
+ ]
+ },
+ {
+ "x": 610,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 365,
+ 373,
+ 389
+ ]
+ },
+ {
+ "x": 600,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 352,
+ 372,
+ 388
+ ]
+ },
+ {
+ "x": 580,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 350,
+ 370,
+ 387
+ ]
+ },
+ {
+ "x": 570,
+ "y": 500,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 349,
+ 371,
+ 386
+ ]
+ },
+ {
+ "x": 620,
+ "y": 560,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 346,
+ 376
+ ]
+ },
+ {
+ "x": 630,
+ "y": 500,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 375,
+ 384
+ ]
+ },
+ {
+ "x": 640,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 255,
+ 377,
+ 383
+ ]
+ },
+ {
+ "x": 650,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 378,
+ 382,
+ 413
+ ]
+ },
+ {
+ "x": 660,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 366,
+ 379,
+ 381
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 374
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 407
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 408
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 419
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 354
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 411
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 421
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 254
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 413
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 412
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 423
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 255
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 256
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 406
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 367
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 426
+ ]
+ },
+ {
+ "x": 900,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 403,
+ 413
+ ]
+ },
+ {
+ "x": 730,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 391,
+ 409
+ ]
+ },
+ {
+ "x": 750,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 392,
+ 409
+ ]
+ },
+ {
+ "x": 740,
+ "y": 550,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 407,
+ 408,
+ 410
+ ]
+ },
+ {
+ "x": 740,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 364,
+ 409
+ ]
+ },
+ {
+ "x": 800,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 366,
+ 395,
+ 412
+ ]
+ },
+ {
+ "x": 850,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 367,
+ 399,
+ 411
+ ]
+ },
+ {
+ "x": 840,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 388,
+ 398,
+ 406
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 422
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 420
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 424
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 425
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 431
+ ]
+ },
+ {
+ "x": 740,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 393,
+ 420
+ ]
+ },
+ {
+ "x": 800,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 415,
+ 419
+ ]
+ },
+ {
+ "x": 790,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 396,
+ 422
+ ]
+ },
+ {
+ "x": 810,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 414,
+ 421
+ ]
+ },
+ {
+ "x": 840,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 400,
+ 424
+ ]
+ },
+ {
+ "x": 830,
+ "y": 630,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 416,
+ 423
+ ]
+ },
+ {
+ "x": 840,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 417,
+ 426
+ ]
+ },
+ {
+ "x": 890,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 405,
+ 425
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 298
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 380
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 432
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 435
+ ]
+ },
+ {
+ "x": 820,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 418,
+ 432,
+ 433
+ ]
+ },
+ {
+ "x": 660,
+ "y": 720,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 429,
+ 431
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 431
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 436
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 430
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 434
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 234
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 247
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 233
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 251
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 252
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 258
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 446
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 447
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 306
+ ]
+ },
+ {
+ "x": 160,
+ "y": 470,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 362,
+ 443
+ ]
+ },
+ {
+ "x": 180,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 360,
+ 444
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 363
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 365
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 369
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 456
+ ]
+ },
+ {
+ "x": -10,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 270
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 271
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 457
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 458
+ ]
+ },
+ {
+ "x": 40,
+ "y": 560,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 239,
+ 346,
+ 451
+ ]
+ },
+ {
+ "x": 70,
+ "y": 480,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 284,
+ 347,
+ 454
+ ]
+ },
+ {
+ "x": 50,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 281,
+ 455
+ ]
+ }
+ ],
+ "id": 35784513673,
+ "name": "ALU",
+ "Input": [
+ {
+ "x": 870,
+ "y": 120,
+ "objectType": "Input",
+ "label": "S0",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 0
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "bgyS7iMmTulYzuhvuJAw"
+ }
+ ]
+ }
+ },
+ {
+ "x": 870,
+ "y": 140,
+ "objectType": "Input",
+ "label": "S1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 1
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "WLqXqxdEhvoLWHtBXHjI"
+ }
+ ]
+ }
+ },
+ {
+ "x": 870,
+ "y": 160,
+ "objectType": "Input",
+ "label": "S2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 2
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "a8z7DkCwKWXkSw3WfkAz"
+ }
+ ]
+ }
+ },
+ {
+ "x": 870,
+ "y": 180,
+ "objectType": "Input",
+ "label": "S3",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 3
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 0,
+ "y": 80,
+ "id": "oU212lSCqnaiI2XB6l6k"
+ }
+ ]
+ }
+ },
+ {
+ "x": 740,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~B3",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 22
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 100,
+ "id": "1ukWtQYmxOZZ1aandrYs"
+ }
+ ]
+ }
+ },
+ {
+ "x": 530,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~A3",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 37
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 120,
+ "id": "dtsyFvTYyoF8pFrQ4gZv"
+ }
+ ]
+ }
+ },
+ {
+ "x": 440,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~B2",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 74
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 140,
+ "id": "rMYJA0Nz0IHW6cXFoIMh"
+ }
+ ]
+ }
+ },
+ {
+ "x": 230,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~A2",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 89
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 160,
+ "id": "k4Q6Y6aWUXjA9uMOFLA9"
+ }
+ ]
+ }
+ },
+ {
+ "x": 140,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~B1",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 126
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 180,
+ "id": "omeNlryzvz7Pz0lFjW6r"
+ }
+ ]
+ }
+ },
+ {
+ "x": -70,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~A1",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 141
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 200,
+ "id": "n8heKwweZojnOjBCw7yI"
+ }
+ ]
+ }
+ },
+ {
+ "x": -150,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~B0",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 178
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 220,
+ "id": "EZQWSGwtHHM3LMJAiLUX"
+ }
+ ]
+ }
+ },
+ {
+ "x": -360,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~A0",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 193
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 240,
+ "id": "DnHv05kyFumssr1vnxvh"
+ }
+ ]
+ }
+ },
+ {
+ "x": -450,
+ "y": 30,
+ "objectType": "Input",
+ "label": "M",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 214
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 260,
+ "id": "UrilH2CzjLyUst4aRdT7"
+ }
+ ]
+ }
+ },
+ {
+ "x": -470,
+ "y": 30,
+ "objectType": "Input",
+ "label": "~Cn",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 215
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 1,
+ {
+ "x": 0,
+ "y": 280,
+ "id": "OCylfDQemyKD1ghkGw99"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": -450,
+ "y": 890,
+ "objectType": "Output",
+ "label": "~F0",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 259
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 80,
+ "id": "O88tnQx6pYWyz8DgCW2w"
+ }
+ ]
+ }
+ },
+ {
+ "x": -280,
+ "y": 890,
+ "objectType": "Output",
+ "label": "~F1",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 260
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 100,
+ "id": "Q7u02WLnBPTPrO8hOd0v"
+ }
+ ]
+ }
+ },
+ {
+ "x": -130,
+ "y": 890,
+ "objectType": "Output",
+ "label": "A=B",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 307
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 120,
+ "id": "9FyiglYgXYTjs8PjQO9z"
+ }
+ ]
+ }
+ },
+ {
+ "x": 310,
+ "y": 890,
+ "objectType": "Output",
+ "label": "~F3",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 359
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 140,
+ "id": "pGwpiM47ZeuqcCx5ecc5"
+ }
+ ]
+ }
+ },
+ {
+ "x": 590,
+ "y": 890,
+ "objectType": "Output",
+ "label": "~P",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 390
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 160,
+ "id": "lLu0TkM1mm3IY2JQMoOO"
+ }
+ ]
+ }
+ },
+ {
+ "x": 20,
+ "y": 890,
+ "objectType": "Output",
+ "label": "~F2",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 427
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 180,
+ "id": "iPKabWfwVrry6UrorWWC"
+ }
+ ]
+ }
+ },
+ {
+ "x": 650,
+ "y": 890,
+ "objectType": "Output",
+ "label": "~Cn+4",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 435
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 200,
+ "id": "wyQYiBXlg5PGYSQBqecL"
+ }
+ ]
+ }
+ },
+ {
+ "x": 820,
+ "y": 890,
+ "objectType": "Output",
+ "label": "~G",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 436
+ },
+ "constructorParamaters": [
+ "UP",
+ 1,
+ {
+ "x": 100,
+ "y": 220,
+ "id": "5UE1sKl4PlJGJHUtfQdh"
+ }
+ ]
+ }
+ }
+ ],
+ "NotGate": [
+ {
+ "x": 650,
+ "y": 80,
+ "objectType": "NotGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 1
+ ],
+ "nodes": {
+ "output1": 26,
+ "inp1": 25
+ }
+ }
+ },
+ {
+ "x": 350,
+ "y": 80,
+ "objectType": "NotGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 1
+ ],
+ "nodes": {
+ "output1": 78,
+ "inp1": 77
+ }
+ }
+ },
+ {
+ "x": 50,
+ "y": 80,
+ "objectType": "NotGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 1
+ ],
+ "nodes": {
+ "output1": 130,
+ "inp1": 129
+ }
+ }
+ },
+ {
+ "x": -240,
+ "y": 80,
+ "objectType": "NotGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 1
+ ],
+ "nodes": {
+ "output1": 182,
+ "inp1": 181
+ }
+ }
+ },
+ {
+ "x": -450,
+ "y": 80,
+ "objectType": "NotGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 1
+ ],
+ "nodes": {
+ "output1": 213,
+ "inp1": 212
+ }
+ }
+ },
+ {
+ "x": 820,
+ "y": 830,
+ "objectType": "NotGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 1
+ ],
+ "nodes": {
+ "output1": 434,
+ "inp1": 433
+ }
+ }
+ }
+ ],
+ "AndGate": [
+ {
+ "x": 740,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 4,
+ 5,
+ 6
+ ],
+ "output1": 7
+ }
+ }
+ },
+ {
+ "x": 700,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 8,
+ 9,
+ 10
+ ],
+ "output1": 11
+ }
+ }
+ },
+ {
+ "x": 610,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 12,
+ 13
+ ],
+ "output1": 14
+ }
+ }
+ },
+ {
+ "x": 570,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 15,
+ 16
+ ],
+ "output1": 17
+ }
+ }
+ },
+ {
+ "x": 530,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 18,
+ 19
+ ],
+ "output1": 20
+ }
+ }
+ },
+ {
+ "x": 440,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 56,
+ 57,
+ 58
+ ],
+ "output1": 59
+ }
+ }
+ },
+ {
+ "x": 400,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 60,
+ 61,
+ 62
+ ],
+ "output1": 63
+ }
+ }
+ },
+ {
+ "x": 310,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 64,
+ 65
+ ],
+ "output1": 66
+ }
+ }
+ },
+ {
+ "x": 270,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 67,
+ 68
+ ],
+ "output1": 69
+ }
+ }
+ },
+ {
+ "x": 230,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 70,
+ 71
+ ],
+ "output1": 72
+ }
+ }
+ },
+ {
+ "x": 140,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 108,
+ 109,
+ 110
+ ],
+ "output1": 111
+ }
+ }
+ },
+ {
+ "x": 100,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 112,
+ 113,
+ 114
+ ],
+ "output1": 115
+ }
+ }
+ },
+ {
+ "x": 10,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 116,
+ 117
+ ],
+ "output1": 118
+ }
+ }
+ },
+ {
+ "x": -30,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 119,
+ 120
+ ],
+ "output1": 121
+ }
+ }
+ },
+ {
+ "x": -70,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 122,
+ 123
+ ],
+ "output1": 124
+ }
+ }
+ },
+ {
+ "x": -150,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 160,
+ 161,
+ 162
+ ],
+ "output1": 163
+ }
+ }
+ },
+ {
+ "x": -190,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 164,
+ 165,
+ 166
+ ],
+ "output1": 167
+ }
+ }
+ },
+ {
+ "x": -280,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 168,
+ 169
+ ],
+ "output1": 170
+ }
+ }
+ },
+ {
+ "x": -320,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 171,
+ 172
+ ],
+ "output1": 173
+ }
+ }
+ },
+ {
+ "x": -360,
+ "y": 250,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 174,
+ 175
+ ],
+ "output1": 176
+ }
+ }
+ },
+ {
+ "x": -310,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 222,
+ 223
+ ],
+ "output1": 224
+ }
+ }
+ },
+ {
+ "x": -270,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 241,
+ 242,
+ 243
+ ],
+ "output1": 244
+ }
+ }
+ },
+ {
+ "x": 10,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 261,
+ 262,
+ 263
+ ],
+ "output1": 264
+ }
+ }
+ },
+ {
+ "x": -30,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "2",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 265,
+ 266
+ ],
+ "output1": 267
+ }
+ }
+ },
+ {
+ "x": -130,
+ "y": 800,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 285,
+ 286,
+ 287,
+ 288
+ ],
+ "output1": 289
+ }
+ }
+ },
+ {
+ "x": 230,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "2",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 308,
+ 309
+ ],
+ "output1": 310
+ }
+ }
+ },
+ {
+ "x": 380,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "5",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 311,
+ 312,
+ 313,
+ 314,
+ 315
+ ],
+ "output1": 316
+ }
+ }
+ },
+ {
+ "x": 330,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 317,
+ 318,
+ 319,
+ 320
+ ],
+ "output1": 321
+ }
+ }
+ },
+ {
+ "x": 280,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 322,
+ 323,
+ 324
+ ],
+ "output1": 325
+ }
+ }
+ },
+ {
+ "x": 740,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "2",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 391,
+ 392
+ ],
+ "output1": 393
+ }
+ }
+ },
+ {
+ "x": 790,
+ "y": 590,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "2",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 394,
+ 395
+ ],
+ "output1": 396
+ }
+ }
+ },
+ {
+ "x": 840,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 397,
+ 398,
+ 399
+ ],
+ "output1": 400
+ }
+ }
+ },
+ {
+ "x": 890,
+ "y": 590,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 401,
+ 402,
+ 403,
+ 404
+ ],
+ "output1": 405
+ }
+ }
+ },
+ {
+ "x": 50,
+ "y": 580,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 451,
+ 452,
+ 453,
+ 454
+ ],
+ "output1": 455
+ }
+ }
+ }
+ ],
+ "NorGate": [
+ {
+ "x": 720,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 41,
+ 42
+ ],
+ "output1": 43
+ }
+ }
+ },
+ {
+ "x": 570,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 44,
+ 45,
+ 46
+ ],
+ "output1": 47
+ }
+ }
+ },
+ {
+ "x": 420,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 93,
+ 94
+ ],
+ "output1": 95
+ }
+ }
+ },
+ {
+ "x": 270,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 96,
+ 97,
+ 98
+ ],
+ "output1": 99
+ }
+ }
+ },
+ {
+ "x": 120,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 145,
+ 146
+ ],
+ "output1": 147
+ }
+ }
+ },
+ {
+ "x": -30,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 148,
+ 149,
+ 150
+ ],
+ "output1": 151
+ }
+ }
+ },
+ {
+ "x": -170,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 197,
+ 198
+ ],
+ "output1": 199
+ }
+ }
+ },
+ {
+ "x": -320,
+ "y": 340,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 200,
+ 201,
+ 202
+ ],
+ "output1": 203
+ }
+ }
+ },
+ {
+ "x": -290,
+ "y": 670,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 225,
+ 226
+ ],
+ "output1": 227
+ }
+ }
+ },
+ {
+ "x": 10,
+ "y": 670,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "3",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 275,
+ 276,
+ 277
+ ],
+ "output1": 278
+ }
+ }
+ },
+ {
+ "x": 300,
+ "y": 660,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 326,
+ 327,
+ 328,
+ 329
+ ],
+ "output1": 330
+ }
+ }
+ },
+ {
+ "x": 820,
+ "y": 670,
+ "objectType": "NorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 414,
+ 415,
+ 416,
+ 417
+ ],
+ "output1": 418
+ }
+ }
+ }
+ ],
+ "NandGate": [
+ {
+ "x": -460,
+ "y": 580,
+ "objectType": "NandGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 216,
+ 217
+ ],
+ "output1": 218
+ }
+ }
+ },
+ {
+ "x": 590,
+ "y": 580,
+ "objectType": "NandGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 370,
+ 371,
+ 372,
+ 373
+ ],
+ "output1": 374
+ }
+ }
+ },
+ {
+ "x": 640,
+ "y": 590,
+ "objectType": "NandGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "5",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 375,
+ 376,
+ 377,
+ 378,
+ 379
+ ],
+ "output1": 380
+ }
+ }
+ },
+ {
+ "x": 650,
+ "y": 770,
+ "objectType": "NandGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ "2",
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 428,
+ 429
+ ],
+ "output1": 430
+ }
+ }
+ }
+ ],
+ "XorGate": [
+ {
+ "x": -450,
+ "y": 760,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 219,
+ 220
+ ],
+ "output1": 221
+ }
+ }
+ },
+ {
+ "x": -280,
+ "y": 760,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 248,
+ 249
+ ],
+ "output1": 250
+ }
+ }
+ },
+ {
+ "x": 20,
+ "y": 760,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 272,
+ 273
+ ],
+ "output1": 274
+ }
+ }
+ },
+ {
+ "x": 310,
+ "y": 760,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 339,
+ 340
+ ],
+ "output1": 341
+ }
+ }
+ },
+ {
+ "x": -370,
+ "y": 670,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 437,
+ 438
+ ],
+ "output1": 439
+ }
+ }
+ },
+ {
+ "x": -130,
+ "y": 670,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 440,
+ 441
+ ],
+ "output1": 442
+ }
+ }
+ },
+ {
+ "x": 170,
+ "y": 680,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 443,
+ 444
+ ],
+ "output1": 445
+ }
+ }
+ },
+ {
+ "x": 480,
+ "y": 670,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 448,
+ 449
+ ],
+ "output1": 450
+ }
+ }
+ }
+ ],
+ "nodes": [
+ 21,
+ 23,
+ 24,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 38,
+ 39,
+ 40,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 73,
+ 75,
+ 76,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 90,
+ 91,
+ 92,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 125,
+ 127,
+ 128,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ 140,
+ 142,
+ 143,
+ 144,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 157,
+ 158,
+ 159,
+ 177,
+ 179,
+ 180,
+ 183,
+ 184,
+ 185,
+ 186,
+ 187,
+ 188,
+ 189,
+ 190,
+ 191,
+ 192,
+ 194,
+ 195,
+ 196,
+ 204,
+ 205,
+ 206,
+ 207,
+ 208,
+ 209,
+ 210,
+ 211,
+ 228,
+ 229,
+ 230,
+ 231,
+ 232,
+ 233,
+ 234,
+ 235,
+ 236,
+ 237,
+ 238,
+ 239,
+ 240,
+ 245,
+ 246,
+ 247,
+ 251,
+ 252,
+ 253,
+ 254,
+ 255,
+ 256,
+ 257,
+ 258,
+ 268,
+ 269,
+ 270,
+ 271,
+ 279,
+ 280,
+ 281,
+ 282,
+ 283,
+ 284,
+ 290,
+ 291,
+ 292,
+ 293,
+ 294,
+ 295,
+ 296,
+ 297,
+ 298,
+ 299,
+ 300,
+ 301,
+ 302,
+ 303,
+ 304,
+ 305,
+ 306,
+ 331,
+ 332,
+ 333,
+ 334,
+ 335,
+ 336,
+ 337,
+ 338,
+ 342,
+ 343,
+ 344,
+ 345,
+ 346,
+ 347,
+ 348,
+ 349,
+ 350,
+ 351,
+ 352,
+ 353,
+ 354,
+ 355,
+ 356,
+ 357,
+ 358,
+ 360,
+ 361,
+ 362,
+ 363,
+ 364,
+ 365,
+ 366,
+ 367,
+ 368,
+ 369,
+ 381,
+ 382,
+ 383,
+ 384,
+ 385,
+ 386,
+ 387,
+ 388,
+ 389,
+ 406,
+ 407,
+ 408,
+ 409,
+ 410,
+ 411,
+ 412,
+ 413,
+ 419,
+ 420,
+ 421,
+ 422,
+ 423,
+ 424,
+ 425,
+ 426,
+ 431,
+ 432,
+ 446,
+ 447,
+ 456,
+ 457,
+ 458
+ ]
+ },
+ {
+ "layout": {
+ "width": 100,
+ "height": 140,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": 40,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 1
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 0
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 59
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 9
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 11
+ ]
+ },
+ {
+ "x": 870,
+ "y": 380,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7,
+ 61
+ ]
+ },
+ {
+ "x": 870,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2,
+ 6
+ ]
+ },
+ {
+ "x": 890,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 9,
+ 57
+ ]
+ },
+ {
+ "x": 890,
+ "y": 360,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4,
+ 8
+ ]
+ },
+ {
+ "x": 840,
+ "y": 260,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 11,
+ 55
+ ]
+ },
+ {
+ "x": 840,
+ "y": 380,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5,
+ 10
+ ]
+ },
+ {
+ "x": 40,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 13
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 24
+ ]
+ },
+ {
+ "x": 910,
+ "y": 410,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 14,
+ 19
+ ]
+ },
+ {
+ "x": 910,
+ "y": 360,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18,
+ 60
+ ]
+ },
+ {
+ "x": 900,
+ "y": 430,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15,
+ 21
+ ]
+ },
+ {
+ "x": 900,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20,
+ 58
+ ]
+ },
+ {
+ "x": 860,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 16,
+ 23
+ ]
+ },
+ {
+ "x": 860,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22,
+ 56
+ ]
+ },
+ {
+ "x": 810,
+ "y": 470,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17,
+ 25
+ ]
+ },
+ {
+ "x": 810,
+ "y": 240,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 24,
+ 54
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": 920,
+ "y": 560,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 26,
+ 28
+ ]
+ },
+ {
+ "x": 920,
+ "y": 400,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27,
+ 62
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30
+ ]
+ },
+ {
+ "x": 940,
+ "y": 600,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 29,
+ 31
+ ]
+ },
+ {
+ "x": 940,
+ "y": 420,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30,
+ 63
+ ]
+ },
+ {
+ "x": 40,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 50
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 51
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 52
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 53
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 45
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 64
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 65
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 43
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 67
+ ]
+ },
+ {
+ "x": 1120,
+ "y": 260,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 41,
+ 44
+ ]
+ },
+ {
+ "x": 1120,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 43,
+ 69
+ ]
+ },
+ {
+ "x": 40,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 66
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 68
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 70
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 71
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 36
+ ]
+ },
+ {
+ "x": 0,
+ "y": 80,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 37
+ ]
+ },
+ {
+ "x": 0,
+ "y": 100,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 25
+ ]
+ },
+ {
+ "x": 0,
+ "y": 120,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 10
+ ]
+ },
+ {
+ "x": 0,
+ "y": 140,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23
+ ]
+ },
+ {
+ "x": 0,
+ "y": 160,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8
+ ]
+ },
+ {
+ "x": 0,
+ "y": 180,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 0,
+ "y": 200,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3
+ ]
+ },
+ {
+ "x": 0,
+ "y": 220,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": 0,
+ "y": 240,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 6
+ ]
+ },
+ {
+ "x": 0,
+ "y": 260,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 28
+ ]
+ },
+ {
+ "x": 0,
+ "y": 280,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 100,
+ "y": 80,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 39
+ ]
+ },
+ {
+ "x": 100,
+ "y": 100,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40
+ ]
+ },
+ {
+ "x": 100,
+ "y": 120,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 46
+ ]
+ },
+ {
+ "x": 100,
+ "y": 140,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 42
+ ]
+ },
+ {
+ "x": 100,
+ "y": 160,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 47
+ ]
+ },
+ {
+ "x": 100,
+ "y": 180,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 44
+ ]
+ },
+ {
+ "x": 100,
+ "y": 200,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 48
+ ]
+ },
+ {
+ "x": 100,
+ "y": 220,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 49
+ ]
+ }
+ ],
+ "id": 33755305138,
+ "name": "Main",
+ "Input": [
+ {
+ "x": 710,
+ "y": 390,
+ "objectType": "Input",
+ "label": "~A",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 0
+ },
+ "values": {
+ "state": 15
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 4,
+ {
+ "x": 0,
+ "y": 100,
+ "id": "KkUsNwfO4X0x4c04hwMv"
+ }
+ ]
+ }
+ },
+ {
+ "x": 710,
+ "y": 480,
+ "objectType": "Input",
+ "label": "~B",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 12
+ },
+ "values": {
+ "state": 12
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 4,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "P6IeBwGNUu70jnDV7AEM"
+ }
+ ]
+ }
+ },
+ {
+ "x": 740,
+ "y": 560,
+ "objectType": "Input",
+ "label": "Mode",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 26
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "v6fmRUb6A8NpuXLnnBr2"
+ }
+ ]
+ }
+ },
+ {
+ "x": 740,
+ "y": 600,
+ "objectType": "Input",
+ "label": "~Cn",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 29
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "xxDizRwLr4gvjxzTAF9Q"
+ }
+ ]
+ }
+ },
+ {
+ "x": 700,
+ "y": 230,
+ "objectType": "Input",
+ "label": "S",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 32
+ },
+ "values": {
+ "state": 4
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 4,
+ {
+ "x": 0,
+ "y": 80,
+ "id": "wjiTCwACtzuNTQPiA7Qd"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 1260,
+ "y": 290,
+ "objectType": "Output",
+ "label": "~F",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 45
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 4,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "8EmhK1WYRAieQ1CdZaw8"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1090,
+ "y": 260,
+ "objectType": "Output",
+ "label": "A=B",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 46
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "HBawk8lC7uuFfL6yoUs4"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1090,
+ "y": 300,
+ "objectType": "Output",
+ "label": "",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 47
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 120,
+ "id": "j9nnntr30X9Y0XSOHFG9"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1090,
+ "y": 340,
+ "objectType": "Output",
+ "label": "",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 48
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 60,
+ "id": "82KrKflpCRdOtyEkALcm"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1090,
+ "y": 360,
+ "objectType": "Output",
+ "label": "",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 49
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 80,
+ "id": "dqfl9XSBF9zphXeBra5W"
+ }
+ ]
+ }
+ }
+ ],
+ "Splitter": [
+ {
+ "x": 770,
+ "y": 360,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 4,
+ [
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "inp1": 1
+ }
+ }
+ },
+ {
+ "x": 770,
+ "y": 450,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 4,
+ [
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 14,
+ 15,
+ 16,
+ 17
+ ],
+ "inp1": 13
+ }
+ }
+ },
+ {
+ "x": 780,
+ "y": 200,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 4,
+ [
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 34,
+ 35,
+ 36,
+ 37
+ ],
+ "inp1": 33
+ }
+ }
+ },
+ {
+ "x": 1200,
+ "y": 260,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "LEFT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "LEFT",
+ 4,
+ [
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 39,
+ 40,
+ 41,
+ 42
+ ],
+ "inp1": 38
+ }
+ }
+ }
+ ],
+ "SubCircuit": [
+ {
+ "x": 960,
+ "y": 140,
+ "id": "35784513673",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63
+ ],
+ "outputNodes": [
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71
+ ],
+ "version": "2.0"
+ }
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 27,
+ 28,
+ 30,
+ 31,
+ 43,
+ 44
+ ]
+ }
+ ]
+}
diff --git a/v1/src/simulator/spec/circuits/gates-circuitdata.json b/v1/src/simulator/spec/circuits/gates-circuitdata.json
index a5c96609..7361a1d5 100644
--- a/v1/src/simulator/spec/circuits/gates-circuitdata.json
+++ b/v1/src/simulator/spec/circuits/gates-circuitdata.json
@@ -1,710 +1,879 @@
{
- "name": "gates-circuitdata",
- "timePeriod": 500,
- "clockEnabled": true,
- "projectId": "hCqg1Ns4JVckHsnyKQDi",
- "focussedCircuit": 11597572508,
- "orderedTabs": ["11597572508"],
- "scopes": [
- {
- "layout": {
- "width": 100,
- "height": 280,
- "title_x": 50,
- "title_y": 13,
- "titleEnabled": true
+ "name": "gates-circuitdata",
+ "timePeriod": 500,
+ "clockEnabled": true,
+ "projectId": "hCqg1Ns4JVckHsnyKQDi",
+ "focussedCircuit": 11597572508,
+ "orderedTabs": [
+ "11597572508"
+ ],
+ "scopes": [
+ {
+ "layout": {
+ "width": 100,
+ "height": 280,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 29
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 25
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 24
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 37
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 39
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 28
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 36
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 41
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 26
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 29
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 10
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 16
+ ]
+ },
+ {
+ "x": 260,
+ "y": -10,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 0,
+ 20,
+ 30
+ ]
+ },
+ {
+ "x": 260,
+ "y": 130,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 29,
+ 3,
+ 33
+ ]
+ },
+ {
+ "x": 210,
+ "y": 10,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 1,
+ 21,
+ 32
+ ]
+ },
+ {
+ "x": 210,
+ "y": 150,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31,
+ 4,
+ 34
+ ]
+ },
+ {
+ "x": 260,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30,
+ 11,
+ 35
+ ]
+ },
+ {
+ "x": 210,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 32,
+ 12,
+ 41
+ ]
+ },
+ {
+ "x": 260,
+ "y": 460,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33,
+ 6,
+ 36
+ ]
+ },
+ {
+ "x": 260,
+ "y": 600,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35,
+ 17,
+ 38
+ ]
+ },
+ {
+ "x": 260,
+ "y": 820,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38,
+ 14
+ ]
+ },
+ {
+ "x": 260,
+ "y": 740,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 36,
+ 37,
+ 8
+ ]
+ },
+ {
+ "x": 210,
+ "y": 840,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15,
+ 40
+ ]
+ },
+ {
+ "x": 210,
+ "y": 760,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 39,
+ 9,
+ 41
+ ]
+ },
+ {
+ "x": 210,
+ "y": 620,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34,
+ 40,
+ 18
+ ]
+ }
+ ],
+ "id": 11597572508,
+ "name": "Main",
+ "Input": [
+ {
+ "x": -30,
+ "y": -10,
+ "objectType": "Input",
+ "label": "inp1",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 20
},
- "verilogMetadata": {
- "isVerilogCircuit": false,
- "isMainCircuit": false,
- "code": "// Write Some Verilog Code Here!",
- "subCircuitScopeIds": []
+ "values": {
+ "state": 1
},
- "allNodes": [
- {
- "x": -10,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [29]
- },
- {
- "x": -10,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [31]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [22]
- },
- {
- "x": -10,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [30]
- },
- {
- "x": -10,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [32]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [23]
- },
- {
- "x": -10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [35]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [25]
- },
- {
- "x": -20,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [38]
- },
- {
- "x": -20,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [40]
- },
- {
- "x": 20,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [27]
- },
- {
- "x": -10,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [33]
- },
- {
- "x": -10,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [34]
- },
- {
- "x": 30,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [24]
- },
- {
- "x": -10,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [37]
- },
- {
- "x": -10,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [39]
- },
- {
- "x": 30,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [28]
- },
- {
- "x": -20,
- "y": -10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [36]
- },
- {
- "x": -20,
- "y": 10,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [41]
- },
- {
- "x": 30,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [26]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [29]
- },
- {
- "x": 10,
- "y": 0,
- "type": 1,
- "bitWidth": 1,
- "label": "",
- "connections": [31]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [2]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [5]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [13]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [7]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [19]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [10]
- },
- {
- "x": 10,
- "y": 0,
- "type": 0,
- "bitWidth": 1,
- "label": "",
- "connections": [16]
- },
- {
- "x": 260,
- "y": -10,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [0, 20, 30]
- },
- {
- "x": 260,
- "y": 130,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [29, 3, 33]
- },
- {
- "x": 210,
- "y": 10,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [1, 21, 32]
- },
- {
- "x": 210,
- "y": 150,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [31, 4, 34]
- },
- {
- "x": 260,
- "y": 300,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [30, 11, 35]
- },
- {
- "x": 210,
- "y": 320,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [32, 12, 41]
- },
- {
- "x": 260,
- "y": 460,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [33, 6, 36]
- },
- {
- "x": 260,
- "y": 600,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [35, 17, 38]
- },
- {
- "x": 260,
- "y": 820,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [38, 14]
- },
- {
- "x": 260,
- "y": 740,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [36, 37, 8]
- },
- {
- "x": 210,
- "y": 840,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [15, 40]
- },
- {
- "x": 210,
- "y": 760,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [39, 9, 41]
- },
- {
- "x": 210,
- "y": 620,
- "type": 2,
- "bitWidth": 1,
- "label": "",
- "connections": [34, 40, 18]
- }
- ],
- "id": 11597572508,
- "name": "Main",
- "Input": [
- {
- "x": -30,
- "y": -10,
- "objectType": "Input",
- "label": "inp1",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 20
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 20,
- "id": "55mKFwVFnZeU6ucfO8am"
- }
- ]
- }
- },
- {
- "x": -30,
- "y": 10,
- "objectType": "Input",
- "label": "inp2",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "output1": 21
- },
- "values": {
- "state": 1
- },
- "constructorParamaters": [
- "RIGHT",
- 1,
- {
- "x": 0,
- "y": 40,
- "id": "2O2YfZk7yuqLrtiRb429"
- }
- ]
- }
- }
- ],
- "Output": [
- {
- "x": 500,
- "y": 0,
- "objectType": "Output",
- "label": "out1",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 22
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 20,
- "id": "RarwxCcQgRygZftUFlMr"
- }
- ]
- }
- },
- {
- "x": 510,
- "y": 140,
- "objectType": "Output",
- "label": "out2",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 23
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 40,
- "id": "N0agpzN04aqy9nLexP98"
- }
- ]
- }
- },
- {
- "x": 520,
- "y": 310,
- "objectType": "Output",
- "label": "out3",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 24
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 60,
- "id": "2yO9fxrqrjPk1urH47Fc"
- }
- ]
- }
- },
- {
- "x": 520,
- "y": 460,
- "objectType": "Output",
- "label": "out4",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 25
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 80,
- "id": "IN7sNsKhkByzBHRShVdu"
- }
- ]
- }
- },
- {
- "x": 520,
- "y": 610,
- "objectType": "Output",
- "label": "out5",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 26
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 100,
- "id": "Dfr4VEfv27q3AOwkLqpx"
- }
- ]
- }
- },
- {
- "x": 520,
- "y": 750,
- "objectType": "Output",
- "label": "out6",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 27
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 120,
- "id": "FGeZ7ip5nJo9MUlEyJ35"
- }
- ]
- }
- },
- {
- "x": 530,
- "y": 830,
- "objectType": "Output",
- "label": "out7",
- "direction": "LEFT",
- "labelDirection": "RIGHT",
- "propagationDelay": 0,
- "customData": {
- "nodes": {
- "inp1": 28
- },
- "constructorParamaters": [
- "LEFT",
- 1,
- {
- "x": 100,
- "y": 140,
- "id": "oYVAxzNmrQgKjC7I3xOg"
- }
- ]
- }
- }
- ],
- "NotGate": [
- {
- "x": 340,
- "y": 460,
- "objectType": "NotGate",
- "label": "NOT GATE",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 1],
- "nodes": {
- "output1": 7,
- "inp1": 6
- }
- }
- }
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "55mKFwVFnZeU6ucfO8am"
+ }
+ ]
+ }
+ },
+ {
+ "x": -30,
+ "y": 10,
+ "objectType": "Input",
+ "label": "inp2",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 21
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "2O2YfZk7yuqLrtiRb429"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 500,
+ "y": 0,
+ "objectType": "Output",
+ "label": "out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 22
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "RarwxCcQgRygZftUFlMr"
+ }
+ ]
+ }
+ },
+ {
+ "x": 510,
+ "y": 140,
+ "objectType": "Output",
+ "label": "out2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 23
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "N0agpzN04aqy9nLexP98"
+ }
+ ]
+ }
+ },
+ {
+ "x": 520,
+ "y": 310,
+ "objectType": "Output",
+ "label": "out3",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 24
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 60,
+ "id": "2yO9fxrqrjPk1urH47Fc"
+ }
+ ]
+ }
+ },
+ {
+ "x": 520,
+ "y": 460,
+ "objectType": "Output",
+ "label": "out4",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 25
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 80,
+ "id": "IN7sNsKhkByzBHRShVdu"
+ }
+ ]
+ }
+ },
+ {
+ "x": 520,
+ "y": 610,
+ "objectType": "Output",
+ "label": "out5",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 26
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 100,
+ "id": "Dfr4VEfv27q3AOwkLqpx"
+ }
+ ]
+ }
+ },
+ {
+ "x": 520,
+ "y": 750,
+ "objectType": "Output",
+ "label": "out6",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 27
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 120,
+ "id": "FGeZ7ip5nJo9MUlEyJ35"
+ }
+ ]
+ }
+ },
+ {
+ "x": 530,
+ "y": 830,
+ "objectType": "Output",
+ "label": "out7",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 28
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 140,
+ "id": "oYVAxzNmrQgKjC7I3xOg"
+ }
+ ]
+ }
+ }
+ ],
+ "NotGate": [
+ {
+ "x": 340,
+ "y": 460,
+ "objectType": "NotGate",
+ "label": "NOT GATE",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
],
- "OrGate": [
- {
- "x": 330,
- "y": 140,
- "objectType": "OrGate",
- "label": "OR GATE",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 2, 1],
- "nodes": {
- "inp": [3, 4],
- "output1": 5
- }
- }
- }
+ "nodes": {
+ "output1": 7,
+ "inp1": 6
+ }
+ }
+ }
+ ],
+ "OrGate": [
+ {
+ "x": 330,
+ "y": 140,
+ "objectType": "OrGate",
+ "label": "OR GATE",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
],
- "AndGate": [
- {
- "x": 320,
- "y": 0,
- "objectType": "AndGate",
- "label": "AND GATE",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 2, 1],
- "nodes": {
- "inp": [0, 1],
- "output1": 2
- }
- }
- }
+ "nodes": {
+ "inp": [
+ 3,
+ 4
+ ],
+ "output1": 5
+ }
+ }
+ }
+ ],
+ "AndGate": [
+ {
+ "x": 320,
+ "y": 0,
+ "objectType": "AndGate",
+ "label": "AND GATE",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
],
- "NorGate": [
- {
- "x": 330,
- "y": 830,
- "objectType": "NorGate",
- "label": "NOR",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 2, 1],
- "nodes": {
- "inp": [14, 15],
- "output1": 16
- }
- }
- }
+ "nodes": {
+ "inp": [
+ 0,
+ 1
+ ],
+ "output1": 2
+ }
+ }
+ }
+ ],
+ "NorGate": [
+ {
+ "x": 330,
+ "y": 830,
+ "objectType": "NorGate",
+ "label": "NOR",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
],
- "NandGate": [
- {
- "x": 340,
- "y": 310,
- "objectType": "NandGate",
- "label": "NAND GATE",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 2, 1],
- "nodes": {
- "inp": [11, 12],
- "output1": 13
- }
- }
- }
+ "nodes": {
+ "inp": [
+ 14,
+ 15
+ ],
+ "output1": 16
+ }
+ }
+ }
+ ],
+ "NandGate": [
+ {
+ "x": 340,
+ "y": 310,
+ "objectType": "NandGate",
+ "label": "NAND GATE",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
],
- "XorGate": [
- {
- "x": 330,
- "y": 750,
- "objectType": "XorGate",
- "label": "XOR",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 2, 1],
- "nodes": {
- "inp": [8, 9],
- "output1": 10
- }
- }
- }
+ "nodes": {
+ "inp": [
+ 11,
+ 12
+ ],
+ "output1": 13
+ }
+ }
+ }
+ ],
+ "XorGate": [
+ {
+ "x": 330,
+ "y": 750,
+ "objectType": "XorGate",
+ "label": "XOR",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
],
- "XnorGate": [
- {
- "x": 330,
- "y": 610,
- "objectType": "XnorGate",
- "label": "XNOR GATE",
- "direction": "RIGHT",
- "labelDirection": "LEFT",
- "propagationDelay": 10,
- "customData": {
- "constructorParamaters": ["RIGHT", 2, 1],
- "nodes": {
- "inp": [17, 18],
- "output1": 19
- }
- }
- }
+ "nodes": {
+ "inp": [
+ 8,
+ 9
+ ],
+ "output1": 10
+ }
+ }
+ }
+ ],
+ "XnorGate": [
+ {
+ "x": 330,
+ "y": 610,
+ "objectType": "XnorGate",
+ "label": "XNOR GATE",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
],
- "restrictedCircuitElementsUsed": [],
- "nodes": [29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41]
+ "nodes": {
+ "inp": [
+ 17,
+ 18
+ ],
+ "output1": 19
+ }
+ }
}
- ]
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41
+ ]
+ }
+ ]
}
diff --git a/v1/src/simulator/spec/circuits/misc-circuitdata.json b/v1/src/simulator/spec/circuits/misc-circuitdata.json
new file mode 100644
index 00000000..9da89ca2
--- /dev/null
+++ b/v1/src/simulator/spec/circuits/misc-circuitdata.json
@@ -0,0 +1,1572 @@
+{
+ "name": "misc",
+ "timePeriod": 500,
+ "clockEnabled": true,
+ "projectId": "Z66aSelqsnFvwJteATxg",
+ "focussedCircuit": 60033074305,
+ "orderedTabs": [
+ "60033074305"
+ ],
+ "scopes": [
+ {
+ "layout": {
+ "width": 100,
+ "height": 320,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": -30,
+ "y": -30,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "A",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": -30,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "B",
+ "connections": [
+ 22
+ ]
+ },
+ {
+ "x": -10,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 3,
+ "label": "Ctrl",
+ "connections": [
+ 5
+ ]
+ },
+ {
+ "x": -10,
+ "y": 40,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Cout",
+ "connections": [
+ 10
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Out",
+ "connections": [
+ 8
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 3,
+ "label": "",
+ "connections": [
+ 2,
+ 56
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 10
+ ]
+ },
+ {
+ "x": -20,
+ "y": -240,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3,
+ 9
+ ]
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13
+ ]
+ },
+ {
+ "x": -110,
+ "y": -400,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 0,
+ 6,
+ 13
+ ]
+ },
+ {
+ "x": -110,
+ "y": -150,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 11,
+ 12,
+ 21
+ ]
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 14
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "A",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": -20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "B",
+ "connections": [
+ 23
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Cin",
+ "connections": [
+ 24
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Sum",
+ "connections": [
+ 25
+ ]
+ },
+ {
+ "x": 20,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Cout",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": -110,
+ "y": -20,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13,
+ 16,
+ 31
+ ]
+ },
+ {
+ "x": -170,
+ "y": -340,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 1,
+ 7,
+ 23
+ ]
+ },
+ {
+ "x": -170,
+ "y": -10,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17,
+ 22,
+ 72
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": 70,
+ "y": 60,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20,
+ 26
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 3,
+ "label": "input stream",
+ "connections": [
+ 56
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 3,
+ "label": "2's complement",
+ "connections": [
+ 30
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 3,
+ "label": "",
+ "connections": [
+ 29
+ ]
+ },
+ {
+ "x": -110,
+ "y": 190,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21,
+ 32,
+ 39
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35
+ ]
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Enable",
+ "connections": [
+ 46
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 39
+ ]
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "reset",
+ "connections": []
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40
+ ]
+ },
+ {
+ "x": -110,
+ "y": 340,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31,
+ 36,
+ 44
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": -10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 44
+ ]
+ },
+ {
+ "x": 30,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 45
+ ]
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Enable",
+ "connections": [
+ 50
+ ]
+ },
+ {
+ "x": -110,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 39,
+ 41,
+ 69
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 42
+ ]
+ },
+ {
+ "x": 50,
+ "y": 260,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34,
+ 48
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 48
+ ]
+ },
+ {
+ "x": -160,
+ "y": 260,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 46,
+ 47,
+ 49
+ ]
+ },
+ {
+ "x": -160,
+ "y": 570,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 48,
+ 50
+ ]
+ },
+ {
+ "x": 60,
+ "y": 570,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 43,
+ 49
+ ]
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 3,
+ "label": "",
+ "connections": [
+ 55
+ ]
+ },
+ {
+ "x": 20,
+ "y": -30,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 57
+ ]
+ },
+ {
+ "x": 20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 58
+ ]
+ },
+ {
+ "x": 20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 59
+ ]
+ },
+ {
+ "x": 40,
+ "y": -660,
+ "type": 2,
+ "bitWidth": 3,
+ "label": "",
+ "connections": [
+ 51,
+ 56,
+ 63
+ ]
+ },
+ {
+ "x": 40,
+ "y": -530,
+ "type": 2,
+ "bitWidth": 3,
+ "label": "",
+ "connections": [
+ 5,
+ 28,
+ 55
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 52
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 53
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 54
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 3,
+ "label": "",
+ "connections": [
+ 63
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 64
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 2,
+ "label": "",
+ "connections": [
+ 65
+ ]
+ },
+ {
+ "x": 40,
+ "y": -850,
+ "type": 2,
+ "bitWidth": 3,
+ "label": "",
+ "connections": [
+ 55,
+ 60
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 61
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 2,
+ "label": "",
+ "connections": [
+ 62
+ ]
+ },
+ {
+ "x": -20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 72
+ ]
+ },
+ {
+ "x": 0,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 70
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 71
+ ]
+ },
+ {
+ "x": -110,
+ "y": 700,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 44,
+ 70
+ ]
+ },
+ {
+ "x": 60,
+ "y": 700,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 69,
+ 67
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 68
+ ]
+ },
+ {
+ "x": -170,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23,
+ 66
+ ]
+ }
+ ],
+ "id": 60033074305,
+ "name": "Main",
+ "Input": [
+ {
+ "x": -50,
+ "y": -530,
+ "objectType": "Input",
+ "label": "mode",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 5
+ },
+ "values": {
+ "state": 7
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 3,
+ {
+ "x": 0,
+ "y": 100,
+ "id": "XLIG7xxHzqiqXN4niWjc"
+ }
+ ]
+ }
+ },
+ {
+ "x": -260,
+ "y": -400,
+ "objectType": "Input",
+ "label": "inp1",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 6
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "xnFLotUtTF8dDqzdt63A"
+ }
+ ]
+ }
+ },
+ {
+ "x": -260,
+ "y": -340,
+ "objectType": "Input",
+ "label": "inp2",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 7
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "20RIzYI8HAyZyA6HZkie"
+ }
+ ]
+ }
+ },
+ {
+ "x": -240,
+ "y": 0,
+ "objectType": "Input",
+ "label": "inp3",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 24
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "4Pt2rPBEr90DVh789QpH"
+ }
+ ]
+ }
+ },
+ {
+ "x": -230,
+ "y": 260,
+ "objectType": "Input",
+ "label": "enable",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 47
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 80,
+ "id": "Bvzy3iTJUD5HiGnxpab6"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 250,
+ "y": -370,
+ "objectType": "Output",
+ "label": "ALU-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 8
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "AKbMNYWkZvw4oWCYQ12W"
+ }
+ ]
+ }
+ },
+ {
+ "x": 260,
+ "y": -240,
+ "objectType": "Output",
+ "label": "ALU-out2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 9
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 200,
+ "id": "K7hEEwIPmQ17joAgCPXg"
+ }
+ ]
+ }
+ },
+ {
+ "x": 250,
+ "y": -150,
+ "objectType": "Output",
+ "label": "Tunnel-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 15
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "jgCz5e7jPDpPEbwEaQgh"
+ }
+ ]
+ }
+ },
+ {
+ "x": 150,
+ "y": -10,
+ "objectType": "Output",
+ "label": "Adder-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 25
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 60,
+ "id": "IaKcxWxYEyFXwog5mmN9"
+ }
+ ]
+ }
+ },
+ {
+ "x": 200,
+ "y": 60,
+ "objectType": "Output",
+ "label": "Adder-out2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 26
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 80,
+ "id": "zuWpzdjxikK9URyRNLmT"
+ }
+ ]
+ }
+ },
+ {
+ "x": 270,
+ "y": -530,
+ "objectType": "Output",
+ "label": "2s-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 30
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 3,
+ {
+ "x": 100,
+ "y": 100,
+ "id": "4uEXpHNgO8CNC3NeKPhs"
+ }
+ ]
+ }
+ },
+ {
+ "x": 160,
+ "y": 190,
+ "objectType": "Output",
+ "label": "T-state-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 35
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 120,
+ "id": "MwFKnzZlWzyDBVGrzz5e"
+ }
+ ]
+ }
+ },
+ {
+ "x": 160,
+ "y": 340,
+ "objectType": "Output",
+ "label": "buffer-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 40
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 140,
+ "id": "kCRFdkujlb6UZZaBH2Wi"
+ }
+ ]
+ }
+ },
+ {
+ "x": 180,
+ "y": 450,
+ "objectType": "Output",
+ "label": "CI-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 45
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 160,
+ "id": "vh7IJznYSr54Ohz8GC2R"
+ }
+ ]
+ }
+ },
+ {
+ "x": 240,
+ "y": -710,
+ "objectType": "Output",
+ "label": "s-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 57
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 180,
+ "id": "c4XKu6fhOdVbCK6wqiht"
+ }
+ ]
+ }
+ },
+ {
+ "x": 240,
+ "y": -690,
+ "objectType": "Output",
+ "label": "s-out2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 58
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 220,
+ "id": "IcyojhGiGRYqMM9B87k5"
+ }
+ ]
+ }
+ },
+ {
+ "x": 240,
+ "y": -670,
+ "objectType": "Output",
+ "label": "s-out3",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 59
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 240,
+ "id": "ccIvryJkgZqu7qvSQg4l"
+ }
+ ]
+ }
+ },
+ {
+ "x": 220,
+ "y": -880,
+ "objectType": "Output",
+ "label": "s-un-out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 64
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 260,
+ "id": "9CB5RKzglQEWYo6MvnDa"
+ }
+ ]
+ }
+ },
+ {
+ "x": 230,
+ "y": -860,
+ "objectType": "Output",
+ "label": "s-un-out2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 65
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 2,
+ {
+ "x": 100,
+ "y": 280,
+ "id": "dujdaDsq5xV6Z9bOchmB"
+ }
+ ]
+ }
+ },
+ {
+ "x": 170,
+ "y": 640,
+ "objectType": "Output",
+ "label": "Force-out",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 71
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 300,
+ "id": "iHSRiMZgMM6EXgN1xPfJ"
+ }
+ ]
+ }
+ }
+ ],
+ "Splitter": [
+ {
+ "x": 120,
+ "y": -680,
+ "objectType": "Splitter",
+ "label": "splitter-equal",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 3,
+ [
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 52,
+ 53,
+ 54
+ ],
+ "inp1": 51
+ }
+ }
+ },
+ {
+ "x": 130,
+ "y": -860,
+ "objectType": "Splitter",
+ "label": "splitter-unequal",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 3,
+ [
+ 1,
+ 2
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 61,
+ 62
+ ],
+ "inp1": 60
+ }
+ }
+ }
+ ],
+ "ControlledInverter": [
+ {
+ "x": 60,
+ "y": 450,
+ "objectType": "ControlledInverter",
+ "label": "controlled Inverter",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ],
+ "nodes": {
+ "output1": 42,
+ "inp1": 41,
+ "state": 43
+ }
+ }
+ }
+ ],
+ "TriState": [
+ {
+ "x": 50,
+ "y": 190,
+ "objectType": "TriState",
+ "label": "T-state buffer",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ],
+ "nodes": {
+ "output1": 33,
+ "inp1": 32,
+ "state": 34
+ }
+ }
+ }
+ ],
+ "Adder": [
+ {
+ "x": 50,
+ "y": -10,
+ "objectType": "Adder",
+ "label": "Adder",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ],
+ "nodes": {
+ "inpA": 16,
+ "inpB": 17,
+ "carryIn": 18,
+ "carryOut": 20,
+ "sum": 19
+ }
+ }
+ }
+ ],
+ "TwoComplement": [
+ {
+ "x": 120,
+ "y": -530,
+ "objectType": "TwoComplement",
+ "label": "2's compliment",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 3
+ ],
+ "nodes": {
+ "output1": 29,
+ "inp1": 28
+ }
+ }
+ }
+ ],
+ "Buffer": [
+ {
+ "x": 50,
+ "y": 340,
+ "objectType": "Buffer",
+ "label": "buffer",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ],
+ "nodes": {
+ "output1": 38,
+ "inp1": 36,
+ "reset": 37
+ }
+ }
+ }
+ ],
+ "Tunnel": [
+ {
+ "x": -50,
+ "y": -150,
+ "objectType": "Tunnel",
+ "label": "Tunnel-IN",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ "T"
+ ],
+ "nodes": {
+ "inp1": 11
+ },
+ "values": {
+ "identifier": "T"
+ }
+ }
+ },
+ {
+ "x": 140,
+ "y": -150,
+ "objectType": "Tunnel",
+ "label": "Tunnel-Out",
+ "direction": "LEFT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ "T"
+ ],
+ "nodes": {
+ "inp1": 14
+ },
+ "values": {
+ "identifier": "T"
+ }
+ }
+ }
+ ],
+ "ALU": [
+ {
+ "x": -10,
+ "y": -370,
+ "objectType": "ALU",
+ "label": "ALU",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ],
+ "nodes": {
+ "inp1": 0,
+ "inp2": 1,
+ "output": 4,
+ "carryOut": 3,
+ "controlSignalInput": 2
+ }
+ }
+ }
+ ],
+ "ForceGate": [
+ {
+ "x": 60,
+ "y": 640,
+ "objectType": "ForceGate",
+ "label": "force gate",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ],
+ "nodes": {
+ "output1": 68,
+ "inp1": 66,
+ "inp2": 67
+ }
+ }
+ },
+ {
+ "x": 60,
+ "y": 640,
+ "objectType": "ForceGate",
+ "label": "force gate",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ],
+ "nodes": {
+ "output1": 68,
+ "inp1": 66,
+ "inp2": 67
+ }
+ }
+ }
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 10,
+ 12,
+ 13,
+ 21,
+ 22,
+ 23,
+ 27,
+ 31,
+ 39,
+ 44,
+ 46,
+ 48,
+ 49,
+ 50,
+ 55,
+ 56,
+ 63,
+ 69,
+ 70,
+ 72
+ ]
+ }
+ ]
+}
diff --git a/v1/src/simulator/spec/circuits/rippleCarryAdder-circuitdata.json b/v1/src/simulator/spec/circuits/rippleCarryAdder-circuitdata.json
new file mode 100644
index 00000000..3b684246
--- /dev/null
+++ b/v1/src/simulator/spec/circuits/rippleCarryAdder-circuitdata.json
@@ -0,0 +1,3109 @@
+{
+ "name": "Ripple-carry-adder",
+ "timePeriod": 500,
+ "clockEnabled": true,
+ "projectId": "4XoG4GWmQZ9NS4om0iHI",
+ "focussedCircuit": 93663071628,
+ "orderedTabs": [
+ "93663071628",
+ "71620967501",
+ "51553545569"
+ ],
+ "scopes": [
+ {
+ "layout": {
+ "width": 100,
+ "height": 80,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 28
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 200,
+ "y": 90,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 13,
+ 27
+ ]
+ },
+ {
+ "x": 200,
+ "y": 130,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 14,
+ 28
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 300,
+ "y": 170,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18,
+ 21
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 13
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 14
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": 200,
+ "y": 100,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 3,
+ 10
+ ]
+ },
+ {
+ "x": 200,
+ "y": 120,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 4,
+ 11
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5
+ ]
+ },
+ {
+ "x": 300,
+ "y": 130,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 6,
+ 16
+ ]
+ },
+ {
+ "x": 310,
+ "y": 110,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 12,
+ 15,
+ 20
+ ]
+ },
+ {
+ "x": 310,
+ "y": 170,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7,
+ 19
+ ]
+ },
+ {
+ "x": 260,
+ "y": 170,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2,
+ 6,
+ 22
+ ]
+ },
+ {
+ "x": 260,
+ "y": 190,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8,
+ 21
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 26
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 29
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 160,
+ "y": 200,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 23,
+ 27
+ ]
+ },
+ {
+ "x": 160,
+ "y": 90,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 0,
+ 3,
+ 26
+ ]
+ },
+ {
+ "x": 150,
+ "y": 130,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 1,
+ 4,
+ 29
+ ]
+ },
+ {
+ "x": 150,
+ "y": 220,
+ "type": 2,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 24,
+ 28
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 25
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35
+ ]
+ },
+ {
+ "x": 370,
+ "y": 190,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30,
+ 34
+ ]
+ },
+ {
+ "x": 370,
+ "y": 180,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 9,
+ 33
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 32
+ ]
+ }
+ ],
+ "id": 71620967501,
+ "name": "1 Bit Full adder",
+ "Input": [
+ {
+ "x": 120,
+ "y": 90,
+ "objectType": "Input",
+ "label": "A",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 0
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ "1",
+ {
+ "x": 0,
+ "y": 20,
+ "id": "E2sClOSN6pWrS98RgOYs"
+ }
+ ]
+ }
+ },
+ {
+ "x": 120,
+ "y": 130,
+ "objectType": "Input",
+ "label": "B",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 1
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ "1",
+ {
+ "x": 0,
+ "y": 40,
+ "id": "HTbtSbs9eS4J1TQuPXGO"
+ }
+ ]
+ }
+ },
+ {
+ "x": 120,
+ "y": 170,
+ "objectType": "Input",
+ "label": "Cin",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 2
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "VEynnegCN4NTDTf8CiFi"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 470,
+ "y": 120,
+ "objectType": "Output",
+ "label": "Sum",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 5
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "iaTzfFCd96wCDEqETEJQ"
+ }
+ ]
+ }
+ },
+ {
+ "x": 470,
+ "y": 200,
+ "objectType": "Output",
+ "label": "Cout",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 35
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "dW2kDiC82HpklbBdEwV7"
+ }
+ ]
+ }
+ }
+ ],
+ "OrGate": [
+ {
+ "x": 420,
+ "y": 200,
+ "objectType": "OrGate",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 30,
+ 31
+ ],
+ "output1": 32
+ }
+ }
+ }
+ ],
+ "AndGate": [
+ {
+ "x": 340,
+ "y": 180,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 7,
+ 8
+ ],
+ "output1": 9
+ }
+ }
+ },
+ {
+ "x": 180,
+ "y": 210,
+ "objectType": "AndGate",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 23,
+ 24
+ ],
+ "output1": 25
+ }
+ }
+ }
+ ],
+ "XorGate": [
+ {
+ "x": 260,
+ "y": 110,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 10,
+ 11
+ ],
+ "output1": 12
+ }
+ }
+ },
+ {
+ "x": 350,
+ "y": 120,
+ "objectType": "XorGate",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 15,
+ 16
+ ],
+ "output1": 17
+ }
+ }
+ }
+ ],
+ "nodes": [
+ 3,
+ 4,
+ 6,
+ 13,
+ 14,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 26,
+ 27,
+ 28,
+ 29,
+ 33,
+ 34
+ ]
+ },
+ {
+ "layout": {
+ "width": 100,
+ "height": 80,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 1
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 0
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 16
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 7
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 6
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34
+ ]
+ },
+ {
+ "x": 620,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13,
+ 61
+ ]
+ },
+ {
+ "x": 620,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 12,
+ 64
+ ]
+ },
+ {
+ "x": 830,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15,
+ 66
+ ]
+ },
+ {
+ "x": 830,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 14,
+ 69
+ ]
+ },
+ {
+ "x": 260,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2,
+ 52
+ ]
+ },
+ {
+ "x": 280,
+ "y": 240,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3,
+ 18
+ ]
+ },
+ {
+ "x": 440,
+ "y": 240,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17,
+ 73
+ ]
+ },
+ {
+ "x": 300,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4,
+ 20
+ ]
+ },
+ {
+ "x": 630,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19,
+ 21
+ ]
+ },
+ {
+ "x": 630,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20,
+ 62
+ ]
+ },
+ {
+ "x": 320,
+ "y": 220,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5,
+ 23
+ ]
+ },
+ {
+ "x": 840,
+ "y": 220,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22,
+ 24
+ ]
+ },
+ {
+ "x": 840,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 23,
+ 67
+ ]
+ },
+ {
+ "x": 650,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 26,
+ 33
+ ]
+ },
+ {
+ "x": 650,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 25,
+ 63
+ ]
+ },
+ {
+ "x": 430,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8,
+ 28
+ ]
+ },
+ {
+ "x": 270,
+ "y": 210,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27,
+ 29
+ ]
+ },
+ {
+ "x": 270,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 28,
+ 53
+ ]
+ },
+ {
+ "x": 450,
+ "y": 190,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 9,
+ 31
+ ]
+ },
+ {
+ "x": 460,
+ "y": 190,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 30,
+ 32
+ ]
+ },
+ {
+ "x": 460,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31,
+ 57
+ ]
+ },
+ {
+ "x": 470,
+ "y": 200,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 10,
+ 25
+ ]
+ },
+ {
+ "x": 490,
+ "y": 180,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 11,
+ 35
+ ]
+ },
+ {
+ "x": 850,
+ "y": 180,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34,
+ 36
+ ]
+ },
+ {
+ "x": 850,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35,
+ 68
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 54
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 39
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 72
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 46
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 47
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 50
+ ]
+ },
+ {
+ "x": 600,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 45,
+ 60
+ ]
+ },
+ {
+ "x": 600,
+ "y": 380,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 44,
+ 46
+ ]
+ },
+ {
+ "x": 470,
+ "y": 380,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 41,
+ 45
+ ]
+ },
+ {
+ "x": 490,
+ "y": 400,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 42,
+ 48
+ ]
+ },
+ {
+ "x": 790,
+ "y": 400,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 47,
+ 76
+ ]
+ },
+ {
+ "x": 1000,
+ "y": 420,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 50,
+ 77
+ ]
+ },
+ {
+ "x": 510,
+ "y": 420,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 43,
+ 49
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 79
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 16
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 29
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 37
+ ]
+ },
+ {
+ "x": 100,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 72
+ ]
+ },
+ {
+ "x": 100,
+ "y": 40,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 74
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 73
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 75
+ ]
+ },
+ {
+ "x": 100,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 44
+ ]
+ },
+ {
+ "x": 100,
+ "y": 40,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 26
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13
+ ]
+ },
+ {
+ "x": 100,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 76
+ ]
+ },
+ {
+ "x": 100,
+ "y": 40,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 14
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 24
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": "1",
+ "label": "",
+ "connections": [
+ 36
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15
+ ]
+ },
+ {
+ "x": 100,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 77
+ ]
+ },
+ {
+ "x": 100,
+ "y": 40,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 78
+ ]
+ },
+ {
+ "x": 450,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40,
+ 55
+ ]
+ },
+ {
+ "x": 440,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18,
+ 58
+ ]
+ },
+ {
+ "x": 430,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 56,
+ 75
+ ]
+ },
+ {
+ "x": 430,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 59,
+ 74
+ ]
+ },
+ {
+ "x": 790,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 48,
+ 65
+ ]
+ },
+ {
+ "x": 1000,
+ "y": 280,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 49,
+ 70
+ ]
+ },
+ {
+ "x": 1020,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 71,
+ 79
+ ]
+ },
+ {
+ "x": 1020,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 51,
+ 78
+ ]
+ }
+ ],
+ "id": 51553545569,
+ "name": "4 bit Full adder",
+ "Input": [
+ {
+ "x": 330,
+ "y": 90,
+ "objectType": "Input",
+ "label": "A",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 0
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ {
+ "x": 0,
+ "y": 20,
+ "id": "2bB0Ry57AnIPDOzWSzda"
+ }
+ ]
+ }
+ },
+ {
+ "x": 500,
+ "y": 90,
+ "objectType": "Input",
+ "label": "B",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 6
+ },
+ "values": {
+ "state": 8
+ },
+ "constructorParamaters": [
+ "DOWN",
+ "4",
+ {
+ "x": 0,
+ "y": 40,
+ "id": "Iw9xWH2HyRpquRWUnMOe"
+ }
+ ]
+ }
+ },
+ {
+ "x": 240,
+ "y": 320,
+ "objectType": "Input",
+ "label": "Cin",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 37
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "A9dm3htBUx0UtdfjbjKF"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 520,
+ "y": 500,
+ "objectType": "Output",
+ "label": "Sum",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 38
+ },
+ "constructorParamaters": [
+ "UP",
+ "4",
+ {
+ "x": 100,
+ "y": 30,
+ "id": "Yawujtkc6mntSdTwrzFi"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1050,
+ "y": 310,
+ "objectType": "Output",
+ "label": "Cout",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 51
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 50,
+ "id": "NkU1KLcqXFqu75u3vyJJ"
+ }
+ ]
+ }
+ }
+ ],
+ "Splitter": [
+ {
+ "x": 300,
+ "y": 130,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 4,
+ [
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "inp1": 1
+ }
+ }
+ },
+ {
+ "x": 470,
+ "y": 130,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 4,
+ [
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 8,
+ 9,
+ 10,
+ 11
+ ],
+ "inp1": 7
+ }
+ }
+ },
+ {
+ "x": 490,
+ "y": 450,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "UP",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "UP",
+ 4,
+ [
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 40,
+ 41,
+ 42,
+ 43
+ ],
+ "inp1": 39
+ }
+ }
+ }
+ ],
+ "SubCircuit": [
+ {
+ "x": 310,
+ "y": 260,
+ "id": "71620967501",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 52,
+ 53,
+ 54
+ ],
+ "outputNodes": [
+ 55,
+ 56
+ ],
+ "version": "2.0"
+ },
+ {
+ "x": 480,
+ "y": 260,
+ "id": "71620967501",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 57,
+ 58,
+ 59
+ ],
+ "outputNodes": [
+ 60,
+ 61
+ ],
+ "version": "2.0"
+ },
+ {
+ "x": 670,
+ "y": 260,
+ "id": "71620967501",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 62,
+ 63,
+ 64
+ ],
+ "outputNodes": [
+ 65,
+ 66
+ ],
+ "version": "2.0"
+ },
+ {
+ "x": 870,
+ "y": 260,
+ "id": "71620967501",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 67,
+ 68,
+ 69
+ ],
+ "outputNodes": [
+ 70,
+ 71
+ ],
+ "version": "2.0"
+ }
+ ],
+ "nodes": [
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79
+ ]
+ },
+ {
+ "layout": {
+ "width": 100,
+ "height": 110,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 44
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 76
+ ]
+ },
+ {
+ "x": 100,
+ "y": 30,
+ "type": 1,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 66
+ ]
+ },
+ {
+ "x": 100,
+ "y": 50,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 53
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 16,
+ "label": "",
+ "connections": [
+ 7
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 16,
+ "label": "",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 16,
+ "label": "",
+ "connections": [
+ 5
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 36
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 39
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": 16,
+ "label": "",
+ "connections": [
+ 6
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 42
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 47
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 48
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 51
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 35
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 45
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 54
+ ]
+ },
+ {
+ "x": 100,
+ "y": 30,
+ "type": 1,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 69
+ ]
+ },
+ {
+ "x": 100,
+ "y": 50,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 55
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 38
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 50
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 56
+ ]
+ },
+ {
+ "x": 100,
+ "y": 30,
+ "type": 1,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 71
+ ]
+ },
+ {
+ "x": 100,
+ "y": 50,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 57
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 41
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 52
+ ]
+ },
+ {
+ "x": 0,
+ "y": 60,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 58
+ ]
+ },
+ {
+ "x": 100,
+ "y": 30,
+ "type": 1,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 72
+ ]
+ },
+ {
+ "x": 100,
+ "y": 50,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 75
+ ]
+ },
+ {
+ "x": 720,
+ "y": 410,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 0,
+ 8
+ ]
+ },
+ {
+ "x": 740,
+ "y": 370,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 9,
+ 34
+ ]
+ },
+ {
+ "x": 890,
+ "y": 370,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 33,
+ 35
+ ]
+ },
+ {
+ "x": 890,
+ "y": 410,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 17,
+ 34
+ ]
+ },
+ {
+ "x": 760,
+ "y": 360,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 10,
+ 37
+ ]
+ },
+ {
+ "x": 1040,
+ "y": 360,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 36,
+ 38
+ ]
+ },
+ {
+ "x": 1040,
+ "y": 410,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 22,
+ 37
+ ]
+ },
+ {
+ "x": 780,
+ "y": 340,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 11,
+ 40
+ ]
+ },
+ {
+ "x": 1180,
+ "y": 340,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 39,
+ 41
+ ]
+ },
+ {
+ "x": 1180,
+ "y": 410,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 27,
+ 40
+ ]
+ },
+ {
+ "x": 1090,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 13,
+ 43
+ ]
+ },
+ {
+ "x": 690,
+ "y": 320,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 42,
+ 44
+ ]
+ },
+ {
+ "x": 690,
+ "y": 430,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 1,
+ 43
+ ]
+ },
+ {
+ "x": 900,
+ "y": 430,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 18,
+ 46
+ ]
+ },
+ {
+ "x": 900,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 45,
+ 47
+ ]
+ },
+ {
+ "x": 1110,
+ "y": 300,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 14,
+ 46
+ ]
+ },
+ {
+ "x": 1130,
+ "y": 330,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 15,
+ 49
+ ]
+ },
+ {
+ "x": 1060,
+ "y": 330,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 48,
+ 50
+ ]
+ },
+ {
+ "x": 1060,
+ "y": 430,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 23,
+ 49
+ ]
+ },
+ {
+ "x": 1210,
+ "y": 290,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 16,
+ 52
+ ]
+ },
+ {
+ "x": 1210,
+ "y": 430,
+ "type": 2,
+ "bitWidth": 4,
+ "label": "",
+ "connections": [
+ 28,
+ 51
+ ]
+ },
+ {
+ "x": 890,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4,
+ 54
+ ]
+ },
+ {
+ "x": 890,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19,
+ 53
+ ]
+ },
+ {
+ "x": 1050,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21,
+ 56
+ ]
+ },
+ {
+ "x": 1050,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 24,
+ 55
+ ]
+ },
+ {
+ "x": 1200,
+ "y": 440,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 26,
+ 58
+ ]
+ },
+ {
+ "x": 1200,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 29,
+ 57
+ ]
+ },
+ {
+ "x": -10,
+ "y": 30,
+ "type": 0,
+ "bitWidth": "16",
+ "label": "",
+ "connections": [
+ 78
+ ]
+ },
+ {
+ "x": 20,
+ "y": -40,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 64
+ ]
+ },
+ {
+ "x": 20,
+ "y": -20,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 67
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 70
+ ]
+ },
+ {
+ "x": 20,
+ "y": 20,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 74
+ ]
+ },
+ {
+ "x": 900,
+ "y": 530,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 60,
+ 65
+ ]
+ },
+ {
+ "x": 870,
+ "y": 530,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 64,
+ 66
+ ]
+ },
+ {
+ "x": 870,
+ "y": 420,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 3,
+ 65
+ ]
+ },
+ {
+ "x": 920,
+ "y": 520,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 61,
+ 68
+ ]
+ },
+ {
+ "x": 1030,
+ "y": 520,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 67,
+ 69
+ ]
+ },
+ {
+ "x": 1030,
+ "y": 420,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 20,
+ 68
+ ]
+ },
+ {
+ "x": 940,
+ "y": 560,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 62,
+ 80
+ ]
+ },
+ {
+ "x": 1180,
+ "y": 420,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 25,
+ 81
+ ]
+ },
+ {
+ "x": 1350,
+ "y": 420,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 30,
+ 73
+ ]
+ },
+ {
+ "x": 1350,
+ "y": 600,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 72,
+ 74
+ ]
+ },
+ {
+ "x": 960,
+ "y": 600,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 63,
+ 73
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": "16",
+ "label": "",
+ "connections": [
+ 78
+ ]
+ },
+ {
+ "x": 1020,
+ "y": 660,
+ "type": 2,
+ "bitWidth": "16",
+ "label": "",
+ "connections": [
+ 59,
+ 77
+ ]
+ },
+ {
+ "x": 40,
+ "y": 0,
+ "type": 0,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 81
+ ]
+ },
+ {
+ "x": 1180,
+ "y": 560,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 70,
+ 81
+ ]
+ },
+ {
+ "x": 1180,
+ "y": 540,
+ "type": 2,
+ "bitWidth": "4",
+ "label": "",
+ "connections": [
+ 71,
+ 79,
+ 80
+ ]
+ }
+ ],
+ "id": 93663071628,
+ "name": "Main",
+ "Input": [
+ {
+ "x": 790,
+ "y": 230,
+ "objectType": "Input",
+ "label": "A",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 5
+ },
+ "values": {
+ "state": 14332
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 16,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "RSEDtPWAqfBaZZokKbtT"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1160,
+ "y": 230,
+ "objectType": "Input",
+ "label": "B",
+ "direction": "DOWN",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 6
+ },
+ "values": {
+ "state": 24572
+ },
+ "constructorParamaters": [
+ "DOWN",
+ 16,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "Txd27FkQfb3c95FRrcnk"
+ }
+ ]
+ }
+ },
+ {
+ "x": 700,
+ "y": 450,
+ "objectType": "Input",
+ "label": "Cin",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 76
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "DemZmzyVBGIMNFmj70kj"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 1380,
+ "y": 440,
+ "objectType": "Output",
+ "label": "Cout",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 75
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 90,
+ "id": "tLrcFmdJBCxYVIMskoQb"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1020,
+ "y": 740,
+ "objectType": "Output",
+ "label": "Sum",
+ "direction": "UP",
+ "labelDirection": "DOWN",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 77
+ },
+ "constructorParamaters": [
+ "UP",
+ 16,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "o31VsUe37gDTsycMMgVW"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1250,
+ "y": 540,
+ "objectType": "Output",
+ "label": "",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 79
+ },
+ "constructorParamaters": [
+ "LEFT",
+ "4",
+ {
+ "x": 100,
+ "y": 40,
+ "id": "XOjb1SYysdaUdivdnR9O"
+ }
+ ]
+ }
+ }
+ ],
+ "Splitter": [
+ {
+ "x": 760,
+ "y": 270,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 16,
+ [
+ 4,
+ 4,
+ 4,
+ 4
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 8,
+ 9,
+ 10,
+ 11
+ ],
+ "inp1": 7
+ }
+ }
+ },
+ {
+ "x": 1130,
+ "y": 270,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "DOWN",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "DOWN",
+ 16,
+ [
+ 4,
+ 4,
+ 4,
+ 4
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 13,
+ 14,
+ 15,
+ 16
+ ],
+ "inp1": 12
+ }
+ }
+ },
+ {
+ "x": 940,
+ "y": 650,
+ "objectType": "Splitter",
+ "label": "",
+ "direction": "UP",
+ "labelDirection": "LEFT",
+ "propagationDelay": 100,
+ "customData": {
+ "constructorParamaters": [
+ "UP",
+ 16,
+ [
+ 4,
+ 4,
+ 4,
+ 4
+ ]
+ ],
+ "nodes": {
+ "outputs": [
+ 60,
+ 61,
+ 62,
+ 63
+ ],
+ "inp1": 59
+ }
+ }
+ }
+ ],
+ "SubCircuit": [
+ {
+ "x": 760,
+ "y": 390,
+ "id": "51553545569",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 0,
+ 1,
+ 2
+ ],
+ "outputNodes": [
+ 3,
+ 4
+ ],
+ "version": "2.0"
+ },
+ {
+ "x": 920,
+ "y": 390,
+ "id": "51553545569",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 17,
+ 18,
+ 19
+ ],
+ "outputNodes": [
+ 20,
+ 21
+ ],
+ "version": "2.0"
+ },
+ {
+ "x": 1070,
+ "y": 390,
+ "id": "51553545569",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 22,
+ 23,
+ 24
+ ],
+ "outputNodes": [
+ 25,
+ 26
+ ],
+ "version": "2.0"
+ },
+ {
+ "x": 1230,
+ "y": 390,
+ "id": "51553545569",
+ "label": "",
+ "labelDirection": "RIGHT",
+ "inputNodes": [
+ 27,
+ 28,
+ 29
+ ],
+ "outputNodes": [
+ 30,
+ 31
+ ],
+ "version": "2.0"
+ }
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 78,
+ 80,
+ 81
+ ]
+ }
+ ]
+}
diff --git a/v1/src/simulator/spec/circuits/sequential-circuitdata.json b/v1/src/simulator/spec/circuits/sequential-circuitdata.json
new file mode 100644
index 00000000..b97d60ce
--- /dev/null
+++ b/v1/src/simulator/spec/circuits/sequential-circuitdata.json
@@ -0,0 +1,1184 @@
+{
+ "name": "sample",
+ "timePeriod": 500,
+ "clockEnabled": true,
+ "projectId": "yDvzoCP6Qa2VDwWDoj5Q",
+ "focussedCircuit": 81140742990,
+ "orderedTabs": [
+ "81140742990"
+ ],
+ "scopes": [
+ {
+ "layout": {
+ "width": 100,
+ "height": 220,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Clock",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "D",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 20,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q",
+ "connections": [
+ 0
+ ]
+ },
+ {
+ "x": 20,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q Inverse",
+ "connections": [
+ 8
+ ]
+ },
+ {
+ "x": 10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Asynchronous Reset",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Preset",
+ "connections": []
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Enable",
+ "connections": []
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 19
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34
+ ]
+ },
+ {
+ "x": 790,
+ "y": 390,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5,
+ 34
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Clock",
+ "connections": [
+ 20
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "D",
+ "connections": [
+ 18
+ ]
+ },
+ {
+ "x": 20,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 20,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q Inverse",
+ "connections": [
+ 22
+ ]
+ },
+ {
+ "x": 600,
+ "y": 310,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2,
+ 9,
+ 18
+ ]
+ },
+ {
+ "x": 600,
+ "y": 450,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 14,
+ 17,
+ 32
+ ]
+ },
+ {
+ "x": 480,
+ "y": 330,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 1,
+ 10,
+ 20
+ ]
+ },
+ {
+ "x": 480,
+ "y": 470,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13,
+ 19,
+ 33
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 16
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Clock",
+ "connections": [
+ 33
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "T",
+ "connections": [
+ 32
+ ]
+ },
+ {
+ "x": 20,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q",
+ "connections": [
+ 30
+ ]
+ },
+ {
+ "x": 20,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q Inverse",
+ "connections": [
+ 31
+ ]
+ },
+ {
+ "x": 10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Asynchronous Reset",
+ "connections": [
+ 36
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Preset",
+ "connections": []
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Enable",
+ "connections": []
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 25
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 26
+ ]
+ },
+ {
+ "x": 600,
+ "y": 620,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18,
+ 24,
+ 49
+ ]
+ },
+ {
+ "x": 480,
+ "y": 640,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20,
+ 23,
+ 50
+ ]
+ },
+ {
+ "x": 400,
+ "y": 390,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 11,
+ 12,
+ 35
+ ]
+ },
+ {
+ "x": 400,
+ "y": 710,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 34,
+ 36,
+ 47
+ ]
+ },
+ {
+ "x": 800,
+ "y": 710,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 27,
+ 35
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "J",
+ "connections": [
+ 49
+ ]
+ },
+ {
+ "x": -20,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "K",
+ "connections": [
+ 62
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Clock",
+ "connections": [
+ 50
+ ]
+ },
+ {
+ "x": 20,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q",
+ "connections": [
+ 45
+ ]
+ },
+ {
+ "x": 20,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q Inverse",
+ "connections": [
+ 46
+ ]
+ },
+ {
+ "x": 10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Asynchronous Reset",
+ "connections": [
+ 48
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Preset",
+ "connections": []
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Enable",
+ "connections": []
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 40
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 41
+ ]
+ },
+ {
+ "x": 400,
+ "y": 890,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 35,
+ 48,
+ 64
+ ]
+ },
+ {
+ "x": 790,
+ "y": 890,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 42,
+ 47
+ ]
+ },
+ {
+ "x": 600,
+ "y": 820,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 32,
+ 37,
+ 61
+ ]
+ },
+ {
+ "x": 480,
+ "y": 840,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 33,
+ 39
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 62
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "R",
+ "connections": [
+ 63
+ ]
+ },
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "S",
+ "connections": [
+ 61
+ ]
+ },
+ {
+ "x": 20,
+ "y": -10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q",
+ "connections": [
+ 59
+ ]
+ },
+ {
+ "x": 20,
+ "y": 10,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "Q Inverse",
+ "connections": [
+ 60
+ ]
+ },
+ {
+ "x": 10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Asynchronous Reset",
+ "connections": [
+ 65
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Preset",
+ "connections": []
+ },
+ {
+ "x": -10,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "Enable",
+ "connections": []
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 54
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 55
+ ]
+ },
+ {
+ "x": 600,
+ "y": 990,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 49,
+ 53
+ ]
+ },
+ {
+ "x": 570,
+ "y": 830,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 38,
+ 51,
+ 63
+ ]
+ },
+ {
+ "x": 570,
+ "y": 1010,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 52,
+ 62
+ ]
+ },
+ {
+ "x": 400,
+ "y": 1060,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 47,
+ 65
+ ]
+ },
+ {
+ "x": 790,
+ "y": 1060,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 56,
+ 64
+ ]
+ }
+ ],
+ "id": 81140742990,
+ "name": "Main",
+ "Input": [
+ {
+ "x": 270,
+ "y": 310,
+ "objectType": "Input",
+ "label": "inp1",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 9
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "ADKJudOKQoIs54SteC0v"
+ }
+ ]
+ }
+ },
+ {
+ "x": 270,
+ "y": 390,
+ "objectType": "Input",
+ "label": "RST",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 11
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "auACgXFHbJMmKSylcRIS"
+ }
+ ]
+ }
+ },
+ {
+ "x": 540,
+ "y": 830,
+ "objectType": "Input",
+ "label": "inp2",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 51
+ },
+ "values": {
+ "state": 0
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "gxYJoZ7q7csS6z5HFjAu"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 920,
+ "y": 310,
+ "objectType": "Output",
+ "label": "out1",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 0
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "p812Pea4ZmGV5PkGdpPe"
+ }
+ ]
+ }
+ },
+ {
+ "x": 920,
+ "y": 330,
+ "objectType": "Output",
+ "label": "out2",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 8
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "bQnnZVmd5kDPIeO22TfP"
+ }
+ ]
+ }
+ },
+ {
+ "x": 920,
+ "y": 450,
+ "objectType": "Output",
+ "label": "out3",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 21
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 60,
+ "id": "7kEPCd8x0CsWmJDHGtz7"
+ }
+ ]
+ }
+ },
+ {
+ "x": 920,
+ "y": 470,
+ "objectType": "Output",
+ "label": "out4",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 22
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 80,
+ "id": "umwIPzgaQxhyw3KXeoIe"
+ }
+ ]
+ }
+ },
+ {
+ "x": 900,
+ "y": 620,
+ "objectType": "Output",
+ "label": "out5",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 30
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 100,
+ "id": "ACFEeZBErU96lY78ng2n"
+ }
+ ]
+ }
+ },
+ {
+ "x": 900,
+ "y": 640,
+ "objectType": "Output",
+ "label": "out6",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 31
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 120,
+ "id": "3TD9jZdXa1AX43jOeh4V"
+ }
+ ]
+ }
+ },
+ {
+ "x": 900,
+ "y": 820,
+ "objectType": "Output",
+ "label": "out7",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 45
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 140,
+ "id": "hCbf5heEes1MWbjfBxag"
+ }
+ ]
+ }
+ },
+ {
+ "x": 900,
+ "y": 840,
+ "objectType": "Output",
+ "label": "out8",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 46
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 160,
+ "id": "U33L7gSGF200Koy8RUpn"
+ }
+ ]
+ }
+ },
+ {
+ "x": 900,
+ "y": 990,
+ "objectType": "Output",
+ "label": "out9",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 59
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 180,
+ "id": "4rIpXftfQyQsEnQT7uXl"
+ }
+ ]
+ }
+ },
+ {
+ "x": 900,
+ "y": 1010,
+ "objectType": "Output",
+ "label": "out10",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 60
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 200,
+ "id": "CYefIzHlGgRM7OF8Ctdw"
+ }
+ ]
+ }
+ }
+ ],
+ "TflipFlop": [
+ {
+ "x": 790,
+ "y": 630,
+ "objectType": "TflipFlop",
+ "label": "T Flip Flop",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "clockInp": 23,
+ "dInp": 24,
+ "qOutput": 25,
+ "qInvOutput": 26,
+ "reset": 27,
+ "preset": 28,
+ "en": 29
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ]
+ }
+ }
+ ],
+ "JKflipFlop": [
+ {
+ "x": 780,
+ "y": 830,
+ "objectType": "JKflipFlop",
+ "label": "Jk Flip Flop",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "J": 37,
+ "K": 38,
+ "clockInp": 39,
+ "qOutput": 40,
+ "qInvOutput": 41,
+ "reset": 42,
+ "preset": 43,
+ "en": 44
+ },
+ "constructorParamaters": [
+ "RIGHT"
+ ]
+ }
+ }
+ ],
+ "SRflipFlop": [
+ {
+ "x": 780,
+ "y": 1000,
+ "objectType": "SRflipFlop",
+ "label": "SR Flip Flop",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "S": 53,
+ "R": 52,
+ "qOutput": 54,
+ "qInvOutput": 55,
+ "reset": 56,
+ "preset": 57,
+ "en": 58
+ },
+ "constructorParamaters": [
+ "RIGHT"
+ ]
+ }
+ }
+ ],
+ "DflipFlop": [
+ {
+ "x": 780,
+ "y": 320,
+ "objectType": "DflipFlop",
+ "label": "D Flip Flop",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "clockInp": 1,
+ "dInp": 2,
+ "qOutput": 3,
+ "qInvOutput": 4,
+ "reset": 5,
+ "preset": 6,
+ "en": 7
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ]
+ }
+ }
+ ],
+ "Clock": [
+ {
+ "x": 270,
+ "y": 330,
+ "objectType": "Clock",
+ "label": "CLOCK",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 10
+ },
+ "constructorParamaters": [
+ "RIGHT"
+ ]
+ }
+ }
+ ],
+ "Dlatch": [
+ {
+ "x": 790,
+ "y": 460,
+ "objectType": "Dlatch",
+ "label": "D latch",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 10,
+ "customData": {
+ "nodes": {
+ "clockInp": 13,
+ "dInp": 14,
+ "qOutput": 15,
+ "qInvOutput": 16
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1
+ ]
+ }
+ }
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 12,
+ 17,
+ 18,
+ 19,
+ 20,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 47,
+ 48,
+ 49,
+ 50,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65
+ ]
+ }
+ ]
+}
diff --git a/v1/src/simulator/spec/circuits/subCircuit-circuitdata.json b/v1/src/simulator/spec/circuits/subCircuit-circuitdata.json
new file mode 100644
index 00000000..e1703e76
--- /dev/null
+++ b/v1/src/simulator/spec/circuits/subCircuit-circuitdata.json
@@ -0,0 +1,814 @@
+{
+ "name": "SubCircuit",
+ "timePeriod": 500,
+ "clockEnabled": true,
+ "projectId": "KXmhGDZlwFlzVjPmxY8g",
+ "focussedCircuit": 69980799589,
+ "orderedTabs": [
+ "69980799589",
+ "98622262167"
+ ],
+ "scopes": [
+ {
+ "layout": {
+ "width": 100,
+ "height": 60,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": -20,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8
+ ]
+ },
+ {
+ "x": -20,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 6
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 12
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 9
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13
+ ]
+ },
+ {
+ "x": 660,
+ "y": 250,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 1,
+ 7,
+ 11
+ ]
+ },
+ {
+ "x": 660,
+ "y": 370,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3,
+ 6
+ ]
+ },
+ {
+ "x": 620,
+ "y": 230,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 0,
+ 9,
+ 10
+ ]
+ },
+ {
+ "x": 620,
+ "y": 390,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4,
+ 8
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 6
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5
+ ]
+ }
+ ],
+ "id": 98622262167,
+ "name": "Half-adder",
+ "Input": [
+ {
+ "x": 580,
+ "y": 230,
+ "objectType": "Input",
+ "label": "inp1",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 10
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "yDbVL6dY6nnuOp5jcZ95"
+ }
+ ]
+ }
+ },
+ {
+ "x": 580,
+ "y": 250,
+ "objectType": "Input",
+ "label": "inp2",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 11
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "xQoyxdS12E5xJ9dmz35B"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 990,
+ "y": 240,
+ "objectType": "Output",
+ "label": "sum",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 12
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 20,
+ "id": "dzWcRuJoJdE8Bg2MY1KI"
+ }
+ ]
+ }
+ },
+ {
+ "x": 1010,
+ "y": 380,
+ "objectType": "Output",
+ "label": "carry",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 13
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "MxBKygipJq4eP2ofPb14"
+ }
+ ]
+ }
+ }
+ ],
+ "AndGate": [
+ {
+ "x": 740,
+ "y": 380,
+ "objectType": "AndGate",
+ "label": "AND",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 3,
+ 4
+ ],
+ "output1": 5
+ }
+ }
+ }
+ ],
+ "XorGate": [
+ {
+ "x": 750,
+ "y": 240,
+ "objectType": "XorGate",
+ "label": "Xor",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 0,
+ 1
+ ],
+ "output1": 2
+ }
+ }
+ }
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 6,
+ 7,
+ 8,
+ 9
+ ]
+ },
+ {
+ "layout": {
+ "width": 100,
+ "height": 80,
+ "title_x": 50,
+ "title_y": 13,
+ "titleEnabled": true
+ },
+ "verilogMetadata": {
+ "isVerilogCircuit": false,
+ "isMainCircuit": false,
+ "code": "// Write Some Verilog Code Here!",
+ "subCircuitScopeIds": []
+ },
+ "allNodes": [
+ {
+ "x": 100,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 6
+ ]
+ },
+ {
+ "x": 100,
+ "y": 40,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 16
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 100,
+ "y": 20,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 14
+ ]
+ },
+ {
+ "x": 100,
+ "y": 40,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 8
+ ]
+ },
+ {
+ "x": 0,
+ "y": 20,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 0
+ ]
+ },
+ {
+ "x": 0,
+ "y": 40,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 20
+ ]
+ },
+ {
+ "x": -10,
+ "y": -10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 5
+ ]
+ },
+ {
+ "x": -10,
+ "y": 10,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 24
+ ]
+ },
+ {
+ "x": 20,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 15
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 17
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 16
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 1,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 4
+ ]
+ },
+ {
+ "x": 10,
+ "y": 0,
+ "type": 0,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 10
+ ]
+ },
+ {
+ "x": -270,
+ "y": 0,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 2,
+ 12
+ ]
+ },
+ {
+ "x": -310,
+ "y": 20,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 3,
+ 11
+ ]
+ },
+ {
+ "x": -240,
+ "y": 110,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 13,
+ 19
+ ]
+ },
+ {
+ "x": 40,
+ "y": 110,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 18,
+ 20
+ ]
+ },
+ {
+ "x": 40,
+ "y": 20,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 7,
+ 19
+ ]
+ },
+ {
+ "x": -20,
+ "y": 20,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 1,
+ 22
+ ]
+ },
+ {
+ "x": -20,
+ "y": 70,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 21,
+ 23
+ ]
+ },
+ {
+ "x": 270,
+ "y": 70,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 22,
+ 24
+ ]
+ },
+ {
+ "x": 270,
+ "y": 40,
+ "type": 2,
+ "bitWidth": 1,
+ "label": "",
+ "connections": [
+ 9,
+ 23
+ ]
+ }
+ ],
+ "id": 69980799589,
+ "name": "Main",
+ "Input": [
+ {
+ "x": -320,
+ "y": -140,
+ "objectType": "Input",
+ "label": "x",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 11
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 40,
+ "id": "TzPoFqkKRnczSlQMidjq"
+ }
+ ]
+ }
+ },
+ {
+ "x": -280,
+ "y": -140,
+ "objectType": "Input",
+ "label": "y",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 12
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 60,
+ "id": "XBpwBuRDlldQywdEHsgz"
+ }
+ ]
+ }
+ },
+ {
+ "x": -250,
+ "y": -140,
+ "objectType": "Input",
+ "label": "cin",
+ "direction": "RIGHT",
+ "labelDirection": "UP",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "output1": 13
+ },
+ "values": {
+ "state": 1
+ },
+ "constructorParamaters": [
+ "RIGHT",
+ 1,
+ {
+ "x": 0,
+ "y": 20,
+ "id": "HQYLk2tHMKI6uYYikApo"
+ }
+ ]
+ }
+ }
+ ],
+ "Output": [
+ {
+ "x": 420,
+ "y": 0,
+ "objectType": "Output",
+ "label": "sum",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 14
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 40,
+ "id": "GOiOE9VzXMlMW1txqFEb"
+ }
+ ]
+ }
+ },
+ {
+ "x": 420,
+ "y": 30,
+ "objectType": "Output",
+ "label": "carry",
+ "direction": "LEFT",
+ "labelDirection": "RIGHT",
+ "propagationDelay": 0,
+ "customData": {
+ "nodes": {
+ "inp1": 15
+ },
+ "constructorParamaters": [
+ "LEFT",
+ 1,
+ {
+ "x": 100,
+ "y": 60,
+ "id": "ASuCOL13vtFBub8uPD7N"
+ }
+ ]
+ }
+ }
+ ],
+ "OrGate": [
+ {
+ "x": 320,
+ "y": 30,
+ "objectType": "OrGate",
+ "label": "",
+ "direction": "RIGHT",
+ "labelDirection": "LEFT",
+ "propagationDelay": 10,
+ "customData": {
+ "constructorParamaters": [
+ "RIGHT",
+ 2,
+ 1
+ ],
+ "nodes": {
+ "inp": [
+ 8,
+ 9
+ ],
+ "output1": 10
+ }
+ }
+ }
+ ],
+ "SubCircuit": [
+ {
+ "x": -180,
+ "y": -20,
+ "id": "98622262167",
+ "label": "half-adder",
+ "labelDirection": "UP",
+ "inputNodes": [
+ 2,
+ 3
+ ],
+ "outputNodes": [
+ 0,
+ 1
+ ],
+ "version": "2.0"
+ },
+ {
+ "x": 110,
+ "y": -20,
+ "id": "98622262167",
+ "label": "half-adder",
+ "labelDirection": "UP",
+ "inputNodes": [
+ 6,
+ 7
+ ],
+ "outputNodes": [
+ 4,
+ 5
+ ],
+ "version": "2.0"
+ }
+ ],
+ "restrictedCircuitElementsUsed": [],
+ "nodes": [
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24
+ ]
+ }
+ ]
+}
diff --git a/v1/src/simulator/spec/combinationalAnalysis.spec.js b/v1/src/simulator/spec/combinationalAnalysis.spec.js
new file mode 100644
index 00000000..646187cd
--- /dev/null
+++ b/v1/src/simulator/spec/combinationalAnalysis.spec.js
@@ -0,0 +1,92 @@
+import { setup } from '../src/setup';
+import { runAll } from '../src/testbench';
+import testData from './testData/gates-testdata.json';
+import { GenerateCircuit, performCombinationalAnalysis } from '../src/combinationalAnalysis';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
+
+describe('Combinational Analysis Testing', () => {
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
+
+ test('performCombinationalAnalysis function working', () => {
+ expect(() => performCombinationalAnalysis('', '', 'AB')).not.toThrow();
+ });
+
+ test('Generating Circuit', () => {
+ expect(() => GenerateCircuit([13], ['A', 'B'], [0, 0, 0, 1], 'AB')).not.toThrow();
+ });
+
+ test('testing Combinational circuit', () => {
+ testData.AndGate.groups[0].inputs[0].label = 'A';
+ testData.AndGate.groups[0].inputs[1].label = 'B';
+ testData.AndGate.groups[0].outputs[0].label = 'AB';
+
+ const result = runAll(testData.AndGate);
+ expect(result.summary.passed).toBe(3);
+ });
+});
diff --git a/v1/src/simulator/spec/complexCircuit.spec.js b/v1/src/simulator/spec/complexCircuit.spec.js
new file mode 100644
index 00000000..32b33083
--- /dev/null
+++ b/v1/src/simulator/spec/complexCircuit.spec.js
@@ -0,0 +1,96 @@
+import { setup } from '../src/setup';
+import load from '../src/data/load';
+import { runAll } from '../src/testbench';
+import aluCircuitData from './circuits/alu-circuitdata.json';
+import rippleCircuitData from './circuits/rippleCarryAdder-circuitdata.json';
+import rippleTestData from './testData/ripple-carry-adder.json';
+import aluTestData from './testData/alu-testdata.json';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
+
+describe('data dir working', () => {
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
+
+ test('load ripple carry adder circuit-data', () => {
+ expect(() => load(rippleCircuitData)).not.toThrow();
+ });
+
+ test('ripple carry adder circuit testing', () => {
+ const result = runAll(rippleTestData.testData);
+ expect(result.summary.passed).toBe(10);
+ });
+
+ test('load ALU circuit-data', () => {
+ expect(() => load(aluCircuitData)).not.toThrow();
+ });
+
+ test('ALU circuit testing', () => {
+ const result = runAll(aluTestData.testData);
+ expect(result.summary.passed).toBe(5);
+ });
+});
diff --git a/v1/src/simulator/spec/data.spec.js b/v1/src/simulator/spec/data.spec.js
index f91a08c8..f1626d66 100644
--- a/v1/src/simulator/spec/data.spec.js
+++ b/v1/src/simulator/spec/data.spec.js
@@ -1,121 +1,170 @@
-/**
- * @jest-environment jsdom
- */
-
-import CodeMirror from 'codemirror'
-import { setup } from '../src/setup'
-import load from '../src/data/load'
-import gatesCircuitData from './circuits/gates-circuitdata.json'
-import decoderCircuitData from './circuits/Decoders-plexers-circuitdata.json'
-import { checkIfBackup, scheduleBackup } from '../src/data/backupCircuit'
-import undo from '../src/data/undo'
-import redo from '../src/data/redo'
-import save from '../src/data/save'
+import { describe, test, expect, vi, beforeAll } from 'vitest';
+import { setup } from '../src/setup';
+import load from '../src/data/load';
+import gatesCircuitData from './circuits/gates-circuitdata.json';
+import decoderCircuitData from './circuits/Decoders-plexers-circuitdata.json';
+import { checkIfBackup, scheduleBackup } from '../src/data/backupCircuit';
+import undo from '../src/data/undo';
+import redo from '../src/data/redo';
+import save from '../src/data/save';
import {
clearProject,
newProject,
recoverProject,
saveOffline,
openOffline,
-} from '../src/data/project'
-import createSaveAsImgPrompt from '../src/data/saveImage'
-
-jest.mock('codemirror')
+} from '../src/data/project';
+import createSaveAsImgPrompt from '../src/data/saveImage';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import simulator from '#/pages/simulatorHandler.vue';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import vuetify from '#/plugins/vuetify';
+import { routes } from '#/router';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => {} })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
describe('data dir working', () => {
- CodeMirror.fromTextArea.mockReturnValueOnce({ setValue: () => {} })
- window.confirm = jest.fn(() => true)
- setup()
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
test('load gates_circuitData without throwing error', () => {
- expect(() => load(gatesCircuitData)).not.toThrow()
- })
+ expect(() => load(gatesCircuitData)).not.toThrow();
+ });
test('should load another circuit data decoder_circuitData', () => {
- expect(() => load(decoderCircuitData)).not.toThrow()
- })
+ expect(() => load(decoderCircuitData)).not.toThrow();
+ });
test('schedule backup working', () => {
- // toggle states of inputs a dn then run schedule backup
globalScope.Input.forEach((input) => {
- input.state = input.state === 1 ? 0 : 1
- expect(() => scheduleBackup()).not.toThrow()
- })
- })
+ input.state = input.state === 1 ? 0 : 1;
+ expect(() => scheduleBackup()).not.toThrow();
+ });
+ });
test('check if backup performed', () => {
- expect(() => checkIfBackup(globalScope)).toBeTruthy()
- })
+ expect(checkIfBackup(globalScope)).toBeTruthy();
+ });
test('undo working', () => {
const beforeUndo = {
backups: globalScope.backups.length,
history: globalScope.history.length,
- }
+ };
for (let i = 1; i < beforeUndo.backups; i++) {
- undo()
+ undo();
const afterUndo = {
backups: globalScope.backups.length + i,
history: globalScope.history.length - i,
- }
- expect(afterUndo).toEqual(beforeUndo)
+ };
+ expect(afterUndo).toEqual(beforeUndo);
}
- })
+ });
test('redo working', () => {
const beforeRedo = {
backups: globalScope.backups.length,
history: globalScope.history.length,
- }
+ };
for (let i = 1; i < beforeRedo.history; i++) {
- redo()
+ redo();
const afterRedo = {
backups: globalScope.backups.length - i,
history: globalScope.history.length + i,
- }
- expect(afterRedo).toEqual(beforeRedo)
+ };
+ expect(afterRedo).toEqual(beforeRedo);
}
- })
+ });
test('save updated circuit_data', () => {
- // save project
- window.logixProjectId = decoderCircuitData.projectId
- expect(() => save()).not.toThrow()
- })
+ window.logixProjectId = decoderCircuitData.projectId;
+ expect(() => save()).not.toThrow();
+ });
test('project working', () => {
- // create new project
- expect(() => newProject(true)).not.toThrow()
- })
+ expect(() => newProject(true)).not.toThrow();
+ });
test('clear Project working', () => {
- // clear project
- expect(() => clearProject()).not.toThrow()
- })
+ expect(() => clearProject()).not.toThrow();
+ });
test('recover Project working', () => {
- // recover project from localstorage
- localStorage.setItem('recover', JSON.stringify(gatesCircuitData))
- expect(() => recoverProject()).not.toThrow()
- })
+ localStorage.setItem('recover', JSON.stringify(gatesCircuitData));
+ expect(() => recoverProject()).not.toThrow();
+ });
test('SaveOffline working', () => {
- // save offline gate project
- expect(() => saveOffline()).not.toThrow()
- })
+ expect(() => saveOffline()).not.toThrow();
+ });
test('OpenOffline working', () => {
- // open dialog
- openOffline()
- // click on first input
- $('#openProjectDialog input')[0].click()
- // click on open button
- $('#Open_offline_btn')[0].click()
- // it should load the offline saved project
- expect(globalScope.id).toBe(11597572508)
- })
+ openOffline();
+ document.querySelector('#openProjectDialog input')?.click();
+ document.querySelector('#Open_offline_btn')?.click();
+ expect(globalScope.id).toBe(11597572508);
+ });
test('saveImage working', () => {
- expect(() => createSaveAsImgPrompt()).not.toThrow()
- })
-})
+ expect(() => createSaveAsImgPrompt()).not.toThrow();
+ });
+});
diff --git a/v1/src/simulator/spec/decoders-plexers.spec.js b/v1/src/simulator/spec/decoders-plexers.spec.js
new file mode 100644
index 00000000..2c4151b1
--- /dev/null
+++ b/v1/src/simulator/spec/decoders-plexers.spec.js
@@ -0,0 +1,115 @@
+import { setup } from '../src/setup';
+import load from '../src/data/load';
+import circuitData from './circuits/Decoders-plexers-circuitdata.json';
+import testData from './testData/decoders-plexers.json';
+import { runAll } from '../src/testbench';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
+
+describe('Simulator Decoders and Plexers Testing', () => {
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
+
+ test('load decoders-plexers circuitData', () => {
+ expect(() => load(circuitData)).not.toThrow();
+ });
+
+ test('Multiplexer working', () => {
+ const result = runAll(testData.Multiplexers);
+ expect(result.summary.passed).toBe(8);
+ });
+
+ test('Demultiplexer working', () => {
+ const result = runAll(testData.Demultiplexer);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('BitSelector working', () => {
+ const result = runAll(testData['bit-selector']);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('MSB working', () => {
+ const result = runAll(testData.msb);
+ expect(result.summary.passed).toBe(5);
+ });
+
+ test('LSB working', () => {
+ const result = runAll(testData.lsb);
+ expect(result.summary.passed).toBe(10);
+ });
+
+ test('Priority Encoder working', () => {
+ const result = runAll(testData['priority-encoder']);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('Decoder working', () => {
+ const result = runAll(testData.Decoder);
+ expect(result.summary.passed).toBe(2);
+ });
+});
diff --git a/v1/src/simulator/spec/gates.spec.js b/v1/src/simulator/spec/gates.spec.js
index 90c7b1bd..1af5a4a7 100644
--- a/v1/src/simulator/spec/gates.spec.js
+++ b/v1/src/simulator/spec/gates.spec.js
@@ -1,57 +1,115 @@
-/**
- * @jest-environment jsdom
- */
+import { setup } from '../src/setup';
+import load from '../src/data/load';
+import circuitData from './circuits/gates-circuitdata.json';
+import testData from './testData/gates-testdata.json';
+import { runAll } from '../src/testbench';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
-import CodeMirror from 'codemirror'
-import { setup } from '../src/setup'
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
-import load from '../src/data/load'
-import circuitData from './circuits/gates-circuitdata.json'
-import testData from './testData/gates-testdata.json'
-import { runAll } from '../src/testbench'
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
-jest.mock('codemirror')
+describe('Simulator Gates Working', () => {
+ let pinia;
+ let router;
-describe('Simulator Gates Testing', () => {
- CodeMirror.fromTextArea.mockReturnValueOnce({ setValue: (text) => {} })
- setup()
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
test('load circuitData', () => {
- expect(() => load(circuitData)).not.toThrow()
- })
-
- test('AND gate testing', () => {
- const result = runAll(testData.AndGate)
- expect(result.summary.passed).toBe(4)
- })
-
- test('NAND gate testing', () => {
- const result = runAll(testData.nandGate)
- expect(result.summary.passed).toBe(4)
- })
-
- test('NOR gate testing', () => {
- const result = runAll(testData.norGate)
- expect(result.summary.passed).toBe(4)
- })
-
- test('NOT gate testing', () => {
- const result = runAll(testData.notGate)
- expect(result.summary.passed).toBe(2)
- })
-
- test('OR gate testing', () => {
- const result = runAll(testData.OrGate)
- expect(result.summary.passed).toBe(4)
- })
-
- test('XNOR gate testing', () => {
- const result = runAll(testData.xnorGate)
- expect(result.summary.passed).toBe(4)
- })
-
- test('XOR gate testing', () => {
- const result = runAll(testData.xorGate)
- expect(result.summary.passed).toBe(4)
- })
-})
+ expect(() => load(circuitData)).not.toThrow();
+ });
+
+ test('AND gate working', () => {
+ const result = runAll(testData.AndGate);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('NAND gate working', () => {
+ const result = runAll(testData.nandGate);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('NOR gate working', () => {
+ const result = runAll(testData.norGate);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('NOT gate working', () => {
+ const result = runAll(testData.notGate);
+ expect(result.summary.passed).toBe(2);
+ });
+
+ test('OR gate working', () => {
+ const result = runAll(testData.OrGate);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('XNOR gate working', () => {
+ const result = runAll(testData.xnorGate);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('XOR gate working', () => {
+ const result = runAll(testData.xorGate);
+ expect(result.summary.passed).toBe(4);
+ });
+});
diff --git a/v1/src/simulator/spec/misc.spec.js b/v1/src/simulator/spec/misc.spec.js
new file mode 100644
index 00000000..57a217e2
--- /dev/null
+++ b/v1/src/simulator/spec/misc.spec.js
@@ -0,0 +1,130 @@
+import { setup } from '../src/setup';
+import load from '../src/data/load';
+import circuitData from './circuits/misc-circuitdata.json';
+import testData from './testData/misc-testdata.json';
+import { runAll } from '../src/testbench';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
+
+describe('Simulator Misc-Elements Testing', () => {
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
+
+ test('load circuitData', () => {
+ expect(() => load(circuitData)).not.toThrow();
+ });
+
+ test('ALU working', () => {
+ const result = runAll(testData.ALU);
+ expect(result.summary.passed).toBe(28);
+ });
+
+ test('Adder working', () => {
+ const result = runAll(testData.Adder);
+ expect(result.summary.passed).toBe(8);
+ });
+
+ test('Buffer working', () => {
+ const result = runAll(testData.buffer);
+ expect(result.summary.passed).toBe(2);
+ });
+
+ test('TriState Buffer working', () => {
+ const result = runAll(testData.Tristate);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('Tunnel working', () => {
+ const result = runAll(testData.Tunnel);
+ expect(result.summary.passed).toBe(2);
+ });
+
+ test("2's Compliment working", () => {
+ const result = runAll(testData.comp);
+ expect(result.summary.passed).toBe(8);
+ });
+
+ test('Controlled Inverter working', () => {
+ const result = runAll(testData.ControlledInverter);
+ expect(result.summary.passed).toBe(3);
+ });
+
+ test('Equal Splitter working', () => {
+ const result = runAll(testData.SplitterEqual);
+ expect(result.summary.passed).toBe(8);
+ });
+
+ test('UnEqual Splitter working', () => {
+ const result = runAll(testData.SplitterUnEqual);
+ expect(result.summary.passed).toBe(8);
+ });
+
+ test('Force Gate working', () => {
+ const result = runAll(testData.ForceGate);
+ expect(result.summary.passed).toBe(2);
+ });
+});
diff --git a/v1/src/simulator/spec/sequential.spec.js b/v1/src/simulator/spec/sequential.spec.js
new file mode 100644
index 00000000..74cdb75f
--- /dev/null
+++ b/v1/src/simulator/spec/sequential.spec.js
@@ -0,0 +1,105 @@
+import { setup } from '../src/setup';
+import load from '../src/data/load';
+import circuitData from './circuits/sequential-circuitdata.json';
+import testData from './testData/sequential-testdata.json';
+import { runAll } from '../src/testbench';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
+
+describe('Simulator Sequential Element Testing', () => {
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
+
+ test('load circuitData', () => {
+ expect(() => load(circuitData)).not.toThrow();
+ });
+
+ test('D Flip Flop working', () => {
+ const result = runAll(testData.DFlipFlop);
+ expect(result.summary.passed).toBe(2);
+ });
+
+ test('D latch working', () => {
+ const result = runAll(testData.DLatch);
+ expect(result.summary.passed).toBe(2);
+ });
+
+ test('JK Flip Flop working', () => {
+ const result = runAll(testData.JkFlipFlop);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('SR Flip Flop working', () => {
+ const result = runAll(testData.SRFlipFlop);
+ expect(result.summary.passed).toBe(4);
+ });
+
+ test('T Flip Flop working', () => {
+ const result = runAll(testData.TFlipFlop);
+ expect(result.summary.passed).toBe(4);
+ });
+});
diff --git a/v1/src/simulator/spec/subCircuit.spec.js b/v1/src/simulator/spec/subCircuit.spec.js
new file mode 100644
index 00000000..f8bae60b
--- /dev/null
+++ b/v1/src/simulator/spec/subCircuit.spec.js
@@ -0,0 +1,85 @@
+import { setup } from '../src/setup';
+import load from '../src/data/load';
+import circuitData from './circuits/subCircuit-circuitdata.json';
+import { runAll } from '../src/testbench';
+import testData from './testData/subCircuit-testdata.json';
+import { createPinia, setActivePinia } from 'pinia';
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from 'vue-router';
+import i18n from '#/locales/i18n';
+import { routes } from '#/router';
+import vuetify from '#/plugins/vuetify';
+import simulator from '#/pages/simulator.vue';
+
+vi.mock('codemirror', async (importOriginal) => {
+ const actual = await importOriginal();
+ return {
+ ...actual,
+ fromTextArea: vi.fn(() => ({ setValue: () => { } })),
+ };
+});
+
+vi.mock('codemirror-editor-vue3', () => ({
+ defineSimpleMode: vi.fn(),
+}));
+
+describe('SubCircuit Testing', () => {
+ let pinia;
+ let router;
+
+ beforeAll(async () => {
+ pinia = createPinia();
+ setActivePinia(pinia);
+
+ router = createRouter({
+ history: createWebHistory(),
+ routes,
+ });
+
+ const elem = document.createElement('div')
+
+ if (document.body) {
+ document.body.appendChild(elem)
+ }
+
+ global.document.createRange = vi.fn(() => ({
+ setEnd: vi.fn(),
+ setStart: vi.fn(),
+ getBoundingClientRect: vi.fn(() => ({
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ })),
+ getClientRects: vi.fn(() => ({
+ item: vi.fn(() => null),
+ length: 0,
+ [Symbol.iterator]: vi.fn(() => []),
+ })),
+ }));
+
+ global.globalScope = global.globalScope || {};
+
+ mount(simulator, {
+ global: {
+ plugins: [pinia, router, i18n, vuetify],
+ },
+ attachTo: elem,
+ });
+
+ setup();
+ });
+
+ test('load subCircuit data without throwing error', () => {
+ expect(() => load(circuitData)).not.toThrow();
+ });
+
+ test('subCircuit working', () => {
+ const result = runAll(testData.subCircuit);
+ expect(result.summary.passed).toBe(8);
+ });
+});
diff --git a/v1/src/simulator/spec/testData/alu-testdata.json b/v1/src/simulator/spec/testData/alu-testdata.json
new file mode 100644
index 00000000..ada54b17
--- /dev/null
+++ b/v1/src/simulator/spec/testData/alu-testdata.json
@@ -0,0 +1,108 @@
+{
+ "testData": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "S",
+ "bitWidth": 4,
+ "values": [
+ "0000",
+ "0000",
+ "0010",
+ "1111",
+ "0100"
+ ]
+ },
+ {
+ "label": "~A",
+ "bitWidth": 4,
+ "values": [
+ "0000",
+ "0000",
+ "1100",
+ "1100",
+ "1111"
+ ]
+ },
+ {
+ "label": "~B",
+ "bitWidth": 4,
+ "values": [
+ "0000",
+ "0000",
+ "1100",
+ "1100",
+ "1100"
+ ]
+ },
+ {
+ "label": "Mode",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "~Cn",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "~F",
+ "bitWidth": 4,
+ "values": [
+ "0001",
+ "0000",
+ "1111",
+ "1011",
+ "0011"
+ ],
+ "results": [
+ "0001",
+ "0000",
+ "1111",
+ "1011",
+ "0011"
+ ]
+ },
+ {
+ "label": "A=B",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "1",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 5
+ }
+ ]
+ }
+}
+
diff --git a/v1/src/simulator/spec/testData/decoders-plexers.json b/v1/src/simulator/spec/testData/decoders-plexers.json
new file mode 100644
index 00000000..504919c3
--- /dev/null
+++ b/v1/src/simulator/spec/testData/decoders-plexers.json
@@ -0,0 +1,401 @@
+{
+ "Multiplexers": {
+ "type": "comb",
+ "title": "Decoders And Plexers",
+ "groups": [
+ {
+ "label": "Multiplexers",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1",
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "s",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0",
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 8
+ }
+ ]
+ },
+ "Demultiplexer":{
+ "type": "comb",
+ "title": "Decoders And Plexers",
+ "groups": [
+ {
+ "label": "Demultiplexer",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "s",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "0"
+ ]
+ },
+ {
+ "label": "out3",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "Decoder":{
+ "type": "comb",
+ "title": "Decoders And Plexers",
+ "groups": [
+ {
+ "label": "Decoder",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out11",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0"
+ ]
+ },
+ {
+ "label": "out12",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 2
+ }
+ ]
+ },
+ "priority-encoder":{
+ "type": "comb",
+ "title": "Decoders And Plexers",
+ "groups": [
+ {
+ "label": "priority-encoder",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp3",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp4",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out9",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "out10",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "en",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "bit-selector": {
+ "type": "comb",
+ "title": "Decoders And Plexers",
+ "groups": [
+ {
+ "label": "bit-selector",
+ "inputs": [
+ {
+ "label": "inp5",
+ "bitWidth": 4,
+ "values": [
+ "0001",
+ "0010",
+ "0100",
+ "1000"
+ ]
+ },
+ {
+ "label": "CS",
+ "bitWidth": 2,
+ "values": [
+ "00",
+ "01",
+ "10",
+ "11"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out13",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "msb": {
+ "type": "comb",
+ "title": "Decoders And Plexers",
+ "groups": [
+ {
+ "label": "msb",
+ "inputs": [
+ {
+ "label": "inp5",
+ "bitWidth": 4,
+ "values": [
+ "0000",
+ "0001",
+ "0010",
+ "0100",
+ "1000"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out4",
+ "bitWidth": 4,
+ "values": [
+ "0000",
+ "0000",
+ "0001",
+ "0010",
+ "0011"
+ ]
+ },
+ {
+ "label": "out5",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 5
+ }
+ ]
+ },
+ "lsb": {
+ "type": "comb",
+ "title": "Decoders And Plexers",
+ "groups": [
+ {
+ "label": "lsb",
+ "inputs": [
+ {
+ "label": "inp5",
+ "bitWidth": 4,
+ "values": [
+ "0000",
+ "0001",
+ "0011",
+ "0111",
+ "1111",
+ "1000",
+ "1100",
+ "1110",
+ "0100",
+ "0010"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out6",
+ "bitWidth": 4,
+ "values": [
+ "0000",
+ "0000",
+ "0000",
+ "0000",
+ "0000",
+ "0011",
+ "0010",
+ "0001",
+ "0010",
+ "0001"
+ ]
+ },
+ {
+ "label": "out7",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "1",
+ "1",
+ "1",
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 10
+ }
+ ]
+ }
+ }
diff --git a/v1/src/simulator/spec/testData/gates-testdata.json b/v1/src/simulator/spec/testData/gates-testdata.json
index 3152253b..18cdf8fc 100644
--- a/v1/src/simulator/spec/testData/gates-testdata.json
+++ b/v1/src/simulator/spec/testData/gates-testdata.json
@@ -1,200 +1,296 @@
{
- "AndGate": {
- "type": "comb",
- "title": "AND Gate",
- "groups": [
- {
- "label": "Group 1",
- "inputs": [
- {
- "label": "inp1",
- "bitWidth": 1,
- "values": ["0", "0", "1", "1"]
- },
- {
- "label": "inp2",
- "bitWidth": 1,
- "values": ["0", "1", "0", "1"]
- }
- ],
- "outputs": [
- {
- "label": "out1",
- "bitWidth": 1,
- "values": ["0", "0", "0", "1"]
- }
- ],
- "n": 4
- }
- ]
- },
- "OrGate": {
- "type": "comb",
- "title": "OR Gate",
- "groups": [
- {
- "label": "Group 1",
- "inputs": [
- {
- "label": "inp1",
- "bitWidth": 1,
- "values": ["0", "0", "1", "1"]
- },
- {
- "label": "inp2",
- "bitWidth": 1,
- "values": ["0", "1", "0", "1"]
- }
- ],
- "outputs": [
- {
- "label": "out2",
- "bitWidth": 1,
- "values": ["0", "1", "1", "1"]
- }
- ],
- "n": 4
- }
- ]
- },
- "nandGate": {
- "type": "comb",
- "title": "NAND Gate",
- "groups": [
- {
- "label": "Group 1",
- "inputs": [
- {
- "label": "inp1",
- "bitWidth": 1,
- "values": ["0", "0", "1", "1"]
- },
- {
- "label": "inp2",
- "bitWidth": 1,
- "values": ["0", "1", "0", "1"]
- }
- ],
- "outputs": [
- {
- "label": "out3",
- "bitWidth": 1,
- "values": ["1", "1", "1", "0"]
- }
- ],
- "n": 4
- }
- ]
- },
- "xorGate": {
- "type": "comb",
- "title": "XOR Gate",
- "groups": [
- {
- "label": "Group 1",
- "inputs": [
- {
- "label": "inp1",
- "bitWidth": 1,
- "values": ["0", "0", "1", "1"]
- },
- {
- "label": "inp2",
- "bitWidth": 1,
- "values": ["0", "1", "0", "1"]
- }
- ],
- "outputs": [
- {
- "label": "out6",
- "bitWidth": 1,
- "values": ["0", "1", "1", "0"]
- }
- ],
- "n": 4
- }
- ]
- },
- "norGate": {
- "type": "comb",
- "title": "NOR Gate",
- "groups": [
- {
- "label": "Group 1",
- "inputs": [
- {
- "label": "inp1",
- "bitWidth": 1,
- "values": ["0", "0", "1", "1"]
- },
- {
- "label": "inp2",
- "bitWidth": 1,
- "values": ["0", "1", "0", "1"]
- }
- ],
- "outputs": [
- {
- "label": "out7",
- "bitWidth": 1,
- "values": ["1", "0", "0", "0"]
- }
- ],
- "n": 4
- }
- ]
- },
- "notGate": {
- "type": "comb",
- "title": "NOT GAte",
- "groups": [
- {
- "label": "Group 1",
- "inputs": [
- {
- "label": "inp1",
- "bitWidth": 1,
- "values": ["0", "1"]
- }
- ],
- "outputs": [
- {
- "label": "out4",
- "bitWidth": 1,
- "values": ["1", "0"]
- }
- ],
- "n": 2
- }
- ]
- },
- "xnorGate": {
- "type": "comb",
- "title": "XNOR GAte",
- "groups": [
- {
- "label": "Group 1",
- "inputs": [
- {
- "label": "inp1",
- "bitWidth": 1,
- "values": ["0", "0", "1", "1"]
- },
- {
- "label": "inp2",
- "bitWidth": 1,
- "values": ["0", "1", "0", "1"]
- }
- ],
- "outputs": [
- {
- "label": "out5",
- "bitWidth": 1,
- "values": ["1", "0", "0", "1"]
- }
- ],
- "n": 4
- }
- ]
- }
+ "AndGate": {
+ "type": "comb",
+ "title": "AND Gate",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "OrGate": {
+ "type": "comb",
+ "title": "OR Gate",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "nandGate": {
+ "type": "comb",
+ "title": "NAND Gate",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out3",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "1",
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "xorGate": {
+ "type": "comb",
+ "title": "XOR Gate",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out6",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "norGate": {
+ "type": "comb",
+ "title": "NOR Gate",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out7",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "notGate": {
+ "type": "comb",
+ "title": "NOT GAte",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out4",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "n": 2
+ }
+ ]
+ },
+ "xnorGate": {
+ "type": "comb",
+ "title": "XNOR GAte",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out5",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ }
}
diff --git a/v1/src/simulator/spec/testData/misc-testdata.json b/v1/src/simulator/spec/testData/misc-testdata.json
new file mode 100644
index 00000000..df7e6509
--- /dev/null
+++ b/v1/src/simulator/spec/testData/misc-testdata.json
@@ -0,0 +1,959 @@
+{
+ "ALU": {
+ "type": "comb",
+ "title": "ALU",
+ "groups": [
+ {
+ "label": "000",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ]
+ },
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "000",
+ "000",
+ "000",
+ "000"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "ALU-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "1",
+ "0"
+ ]
+ },
+ {
+ "label": "ALU-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ },
+ {
+ "label": "001",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "001",
+ "001",
+ "001",
+ "001"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "ALU-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "1"
+ ],
+ "results": [
+ "0",
+ "1",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "ALU-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ },
+ {
+ "label": "010",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "010",
+ "010",
+ "010",
+ "010"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "ALU-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ],
+ "results": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ]
+ },
+ {
+ "label": "ALU-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "1"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ },
+ {
+ "label": "100",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "100",
+ "100",
+ "100",
+ "100"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "ALU-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "1",
+ "0"
+ ]
+ },
+ {
+ "label": "ALU-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ },
+ {
+ "label": "101",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "101",
+ "101",
+ "101",
+ "101"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "ALU-out1",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "1",
+ "1"
+ ],
+ "results": [
+ "1",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "ALU-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ },
+ {
+ "label": "110",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "110",
+ "110",
+ "110",
+ "110"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "ALU-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ],
+ "results": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ]
+ },
+ {
+ "label": "ALU-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ },
+ {
+ "label": "111",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "111",
+ "111",
+ "111",
+ "111"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "ALU-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "1",
+ "0",
+ "0"
+ ]
+ },
+ {
+ "label": "ALU-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "Adder": {
+ "type": "comb",
+ "title": "Adder",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0",
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1",
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp3",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "Adder-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0",
+ "1",
+ "0",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "Adder-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "1",
+ "0",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 8
+ }
+ ]
+ },
+ "buffer": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "buffer-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 2
+ }
+ ]
+ },
+ "Tristate": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "enable",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "T-state-out1",
+ "bitWidth": 1,
+ "values": [
+ "X",
+ "X",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "Tunnel": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "Tunnel-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 2
+ }
+ ]
+ },
+ "comp": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "000",
+ "001",
+ "010",
+ "011",
+ "100",
+ "101",
+ "110",
+ "111"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "2s-out1",
+ "bitWidth": 3,
+ "values": [
+ "000",
+ "111",
+ "110",
+ "101",
+ "100",
+ "011",
+ "010",
+ "001"
+ ]
+ }
+ ],
+ "n": 8
+ }
+ ]
+ },
+ "ControlledInverter": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "enable",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "CI-out1",
+ "bitWidth": 1,
+ "values": [
+ "X",
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "n": 3
+ }
+ ]
+ },
+ "SplitterEqual": {
+ "type": "comb",
+ "title": "Splitter",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0",
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1",
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "inp3",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "Adder-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0",
+ "1",
+ "0",
+ "0",
+ "1"
+ ],
+ "results": [
+ "0",
+ "1",
+ "1",
+ "0",
+ "1",
+ "0",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "Adder-out2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "1",
+ "0",
+ "1",
+ "1",
+ "1"
+ ],
+ "results": [
+ "0",
+ "0",
+ "0",
+ "1",
+ "0",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 8
+ }
+ ]
+ },
+ "SplitterUnEqual": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "mode",
+ "bitWidth": 3,
+ "values": [
+ "000",
+ "001",
+ "010",
+ "011",
+ "100",
+ "101",
+ "110",
+ "111"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "s-un-out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "s-un-out2",
+ "bitWidth": 2,
+ "values": [
+ "00",
+ "00",
+ "01",
+ "01",
+ "10",
+ "10",
+ "11",
+ "11"
+ ]
+ }
+ ],
+ "n": 8
+ }
+ ]
+ },
+ "ForceGate": {
+ "type": "comb",
+ "title": "Force Gate",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "Force-out",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "n": 8
+ }
+ ]
+ }
+}
diff --git a/v1/src/simulator/spec/testData/ripple-carry-adder.json b/v1/src/simulator/spec/testData/ripple-carry-adder.json
new file mode 100644
index 00000000..1a76b9ce
--- /dev/null
+++ b/v1/src/simulator/spec/testData/ripple-carry-adder.json
@@ -0,0 +1,92 @@
+{
+ "testData": {
+ "type": "comb",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "A",
+ "bitWidth": 16,
+ "values": [
+ "0",
+ "1111111111111111",
+ "1111111111111111",
+ "1111111111111110",
+ "1111111111111110",
+ "1111111111111100",
+ "1111111111111100",
+ "0011111111111100",
+ "0011111111111100",
+ "0011011111111100"
+ ]
+ },
+ {
+ "label": "B",
+ "bitWidth": 16,
+ "values": [
+ "0",
+ "1111111111111111",
+ "1111111111111111",
+ "1111111111111110",
+ "1111111111111110",
+ "1111111111111100",
+ "1111111111111100",
+ "1101111111111100",
+ "1101111111111100",
+ "0101111111111100"
+ ]
+ },
+ {
+ "label": "Cin",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "Sum",
+ "bitWidth": 16,
+ "values": [
+ "0000000000000000",
+ "1111111111111110",
+ "1111111111111111",
+ "1111111111111100",
+ "1111111111111101",
+ "1111111111111000",
+ "1111111111111001",
+ "0001111111111000",
+ "0001111111111001",
+ "1001011111111001"
+ ],
+ "results": [
+ "0000000000000000",
+ "1111111111111110",
+ "1111111111111111",
+ "1111111111111100",
+ "1111111111111101",
+ "1111111111111000",
+ "1111111111111001",
+ "0001111111111000",
+ "0001111111111001",
+ "1001011111111001"
+ ]
+ }
+ ],
+ "n": 10
+ }
+ ]
+ }
+}
diff --git a/v1/src/simulator/spec/testData/sequential-testdata.json b/v1/src/simulator/spec/testData/sequential-testdata.json
new file mode 100644
index 00000000..545ed223
--- /dev/null
+++ b/v1/src/simulator/spec/testData/sequential-testdata.json
@@ -0,0 +1,250 @@
+{
+ "DFlipFlop": {
+ "type": "seq",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Set 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ],
+ "results": [
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "out2",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0"
+ ],
+ "results": [
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "n": 2
+ }
+ ]
+ },
+ "DLatch": {
+ "type": "seq",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Set 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out3",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "out4",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "n": 2
+ }
+ ]
+ },
+ "JkFlipFlop": {
+ "type": "seq",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Set 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out7",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "0",
+ "1"
+ ],
+ "results": [
+ "1",
+ "0",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "out8",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ],
+ "results": [
+ "0",
+ "1",
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "SRFlipFlop": {
+ "type": "seq",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Set 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "inp2",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out9",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "0",
+ "0"
+ ]
+ },
+ {
+ "label": "out10",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ },
+ "TFlipFlop": {
+ "type": "seq",
+ "title": "Untitled",
+ "groups": [
+ {
+ "label": "Set 1",
+ "inputs": [
+ {
+ "label": "inp1",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "0",
+ "1",
+ "0"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "out5",
+ "bitWidth": 1,
+ "values": [
+ "1",
+ "1",
+ "0",
+ "0"
+ ]
+ },
+ {
+ "label": "out6",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 4
+ }
+ ]
+ }
+}
diff --git a/v1/src/simulator/spec/testData/subCircuit-testdata.json b/v1/src/simulator/spec/testData/subCircuit-testdata.json
new file mode 100644
index 00000000..2bd50617
--- /dev/null
+++ b/v1/src/simulator/spec/testData/subCircuit-testdata.json
@@ -0,0 +1,86 @@
+{
+ "subCircuit": {
+ "type": "comb",
+ "title": "fullAdder",
+ "groups": [
+ {
+ "label": "Group 1",
+ "inputs": [
+ {
+ "label": "x",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "0",
+ "1",
+ "1",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "y",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "1",
+ "1",
+ "0",
+ "0",
+ "1",
+ "1"
+ ]
+ },
+ {
+ "label": "cin",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1",
+ "0",
+ "1"
+ ]
+ }
+ ],
+ "outputs": [
+ {
+ "label": "sum",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "1",
+ "1",
+ "0",
+ "1",
+ "0",
+ "0",
+ "1"
+ ]
+ },
+ {
+ "label": "carry",
+ "bitWidth": 1,
+ "values": [
+ "0",
+ "0",
+ "0",
+ "1",
+ "0",
+ "1",
+ "1",
+ "1"
+ ]
+ }
+ ],
+ "n": 8
+ }
+ ]
+ }
+ }
diff --git a/v1/src/simulator/spec/vitestSetup.ts b/v1/src/simulator/spec/vitestSetup.ts
new file mode 100644
index 00000000..1f2780a0
--- /dev/null
+++ b/v1/src/simulator/spec/vitestSetup.ts
@@ -0,0 +1,11 @@
+global.window = window;
+global.jQuery = require('jquery');
+global.DPR = true;
+global.width = true;
+global.height = true;
+
+window.Jquery = require('jquery');
+window.$ = require('jquery');
+window.restrictedElements = [];
+window.userSignedIn = true;
+window.embed = false;
diff --git a/v1/src/simulator/src/Verilog2CV.js b/v1/src/simulator/src/Verilog2CV.js
index 83e7641e..bc1a755d 100644
--- a/v1/src/simulator/src/Verilog2CV.js
+++ b/v1/src/simulator/src/Verilog2CV.js
@@ -4,7 +4,7 @@ import {
changeCircuitName,
} from './circuit'
import SubCircuit from './subcircuit'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import CodeMirror from 'codemirror/lib/codemirror.js'
import 'codemirror/lib/codemirror.css'
@@ -31,6 +31,8 @@ import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/display/autorefresh.js'
import { showError, showMessage } from './utils'
import { showProperties } from './ux'
+import { useSimulatorMobileStore } from '#/store/simulatorMobileStore'
+import { toRefs } from 'vue'
var editor
var verilogMode = false
@@ -42,7 +44,17 @@ export async function createVerilogCircuit() {
true,
true
)
- if (returned) verilogModeSet(true)
+
+ if (returned) {
+ verilogModeSet(true)
+
+ try {
+ const simulatorMobileStore = toRefs(useSimulatorMobileStore())
+ simulatorMobileStore.isVerilog.value = true
+ } catch (error) {
+ console.error('Failed to update simulatorMobileStore:', error)
+ }
+ }
}
export function saveVerilogCode() {
@@ -72,11 +84,26 @@ export function verilogModeSet(mode) {
if (mode == verilogMode) return
verilogMode = mode
if (mode) {
+ const code_window = document.getElementById('code-window')
+ if(code_window)
document.getElementById('code-window').style.display = 'block'
+
+ const elementPanel = document.querySelector('.elementPanel')
+ if(elementPanel)
document.querySelector('.elementPanel').style.display = 'none'
+
+ const timingDiagramPanel = document.querySelector('.timing-diagram-panel')
+ if(timingDiagramPanel)
document.querySelector('.timing-diagram-panel').style.display = 'none'
+
+ const quickBtn = document.querySelector('.quick-btn')
+ if(quickBtn)
document.querySelector('.quick-btn').style.display = 'none'
+
+ const verilogEditorPanel = document.getElementById('verilogEditorPanel')
+ if(verilogEditorPanel)
document.getElementById('verilogEditorPanel').style.display = 'block'
+
if (!embed) {
simulationArea.lastSelected = globalScope.root
showProperties(undefined)
@@ -84,10 +111,24 @@ export function verilogModeSet(mode) {
}
resetVerilogCode()
} else {
+ const code_window = document.getElementById('code-window')
+ if(code_window)
document.getElementById('code-window').style.display = 'none'
+
+ const elementPanel = document.querySelector('.elementPanel')
+ if(elementPanel)
document.querySelector('.elementPanel').style.display = ''
+
+ const timingDiagramPanel = document.querySelector('.timing-diagram-panel')
+ if(timingDiagramPanel)
document.querySelector('.timing-diagram-panel').style.display = ''
+
+ const quickBtn = document.querySelector('.quick-btn')
+ if(quickBtn)
document.querySelector('.quick-btn').style.display = ''
+
+ const verilogEditorPanel = document.getElementById('verilogEditorPanel')
+ if(verilogEditorPanel)
document.getElementById('verilogEditorPanel').style.display = 'none'
}
}
diff --git a/v1/src/simulator/src/VerilogClasses.js b/v1/src/simulator/src/VerilogClasses.js
index 253748af..3dfe92ca 100644
--- a/v1/src/simulator/src/VerilogClasses.js
+++ b/v1/src/simulator/src/VerilogClasses.js
@@ -3,67 +3,27 @@ import NandGate from './modules/NandGate'
import Multiplexer from './modules/Multiplexer'
import XorGate from './modules/XorGate'
import XnorGate from './modules/XnorGate'
-import SevenSegDisplay from './modules/SevenSegDisplay'
-import SixteenSegDisplay from './modules/SixteenSegDisplay'
-import HexDisplay from './modules/HexDisplay'
import OrGate from './modules/OrGate'
-import Stepper from './modules/Stepper'
import NotGate from './modules/NotGate'
-import Text from './modules/Text'
-import TriState from './modules/TriState'
import Buffer from './modules/Buffer'
-import ControlledInverter from './modules/ControlledInverter'
import Adder from './modules/Adder'
import verilogMultiplier from './modules/verilogMultiplier'
import verilogDivider from './modules/verilogDivider'
import verilogPower from './modules/verilogPower'
import verilogShiftLeft from './modules/verilogShiftLeft'
import verilogShiftRight from './modules/verilogShiftRight'
-import TwoComplement from './modules/TwoComplement'
import Splitter from './modules/Splitter'
-import Ground from './modules/Ground'
-import Power from './modules/Power'
import Input from './modules/Input'
import Output from './modules/Output'
-import BitSelector from './modules/BitSelector'
import ConstantVal from './modules/ConstantVal'
import NorGate from './modules/NorGate'
import DigitalLed from './modules/DigitalLed'
-import VariableLed from './modules/VariableLed'
import Button from './modules/Button'
-import RGBLed from './modules/RGBLed'
-import SquareRGBLed from './modules/SquareRGBLed'
-import Demultiplexer from './modules/Demultiplexer'
-import Decoder from './modules/Decoder'
-import Flag from './modules/Flag'
-import MSB from './modules/MSB'
import LSB from './modules/LSB'
-import PriorityEncoder from './modules/PriorityEncoder'
-import Tunnel from './modules/Tunnel'
import ALU from './modules/ALU'
-import Rectangle from './modules/Rectangle'
-import Arrow from './modules/Arrow'
-import Counter from './modules/Counter'
-import Random from './modules/Random'
-import RGBLedMatrix from './modules/RGBLedMatrix'
-import simulationArea from './simulationArea'
-import TflipFlop from './sequential/TflipFlop'
import DflipFlop from './sequential/DflipFlop'
-import Dlatch from './sequential/Dlatch'
-import SRflipFlop from './sequential/SRflipFlop'
-import JKflipFlop from './sequential/JKflipFlop'
-import TTY from './sequential/TTY'
-import Keyboard from './sequential/Keyboard'
import Clock from './sequential/Clock'
-import RAM from './sequential/RAM'
import verilogRAM from './sequential/verilogRAM'
-import EEPROM from './sequential/EEPROM'
-import Rom from './sequential/Rom'
-import TB_Input from './testbench/testbenchInput'
-import TB_Output from './testbench/testbenchOutput'
-import ForceGate from './testbench/ForceGate'
-import { newCircuit, switchCircuit, changeCircuitName } from './circuit'
-import SubCircuit from './subcircuit'
function getBitWidth(bitsJSON) {
if (Number.isInteger(bitsJSON)) {
diff --git a/v1/src/simulator/src/app.js b/v1/src/simulator/src/app.ts
similarity index 97%
rename from v1/src/simulator/src/app.js
rename to v1/src/simulator/src/app.ts
index 00b64e60..0f4c7940 100644
--- a/v1/src/simulator/src/app.js
+++ b/v1/src/simulator/src/app.ts
@@ -1,9 +1,9 @@
-import { setup } from './setup'
-import Array from './arrayHelpers'
+import { setup } from './setup';
+import { JsConfig } from './types/app.types'
document.addEventListener('DOMContentLoaded', () => {
- setup()
- var js = {
+ setup();
+ const js: JsConfig = {
devices: {
dev0: {
type: 'Input',
@@ -207,7 +207,5 @@ document.addEventListener('DOMContentLoaded', () => {
},
],
subcircuits: {},
- }
-})
-
-window.Array = Array
+ };
+});
\ No newline at end of file
diff --git a/v1/src/simulator/src/arrayHelpers.js b/v1/src/simulator/src/arrayHelpers.js
deleted file mode 100644
index 8d10917e..00000000
--- a/v1/src/simulator/src/arrayHelpers.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* eslint-disable func-names */
-/* eslint-disable no-global-assign */
-/* eslint-disable no-extend-native */
-export default Array = window.Array
-
-Object.defineProperty(Array.prototype, 'clean', {
- value: function (deleteValue) {
- for (var i = 0; i < this.length; i++) {
- if (this[i] === deleteValue) {
- this.splice(i, 1)
- i--
- }
- }
- return this
- },
- enumerable: false,
-})
-
-Object.defineProperty(Array.prototype, 'extend', {
- value: function (otherArray) {
- /* you should include a test to check whether other_array really is an array */
- otherArray.forEach(function (v) {
- this.push(v)
- }, this)
- },
- enumerable: false,
-})
-
-Object.defineProperty(Array.prototype, 'contains', {
- value: function (value) {
- return this.indexOf(value) > -1
- },
- enumerable: false,
-})
diff --git a/v1/src/simulator/src/backgroundArea.js b/v1/src/simulator/src/backgroundArea.js
deleted file mode 100644
index 49da21aa..00000000
--- a/v1/src/simulator/src/backgroundArea.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { dots } from './canvasApi'
-
-var backgroundArea
-export default backgroundArea = {
- canvas: document.getElementById('backgroundArea'),
- setup() {
- this.canvas = document.getElementById('backgroundArea')
- this.canvas.width = width
- this.canvas.height = height
- this.context = this.canvas.getContext('2d')
- dots(true, false)
- },
- clear() {
- if (!this.context) return
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
- },
-}
diff --git a/v1/src/simulator/src/backgroundArea.ts b/v1/src/simulator/src/backgroundArea.ts
new file mode 100644
index 00000000..7556b0f8
--- /dev/null
+++ b/v1/src/simulator/src/backgroundArea.ts
@@ -0,0 +1,20 @@
+import { BackgroundArea } from './interface/backgroundArea'
+import { dots } from './canvasApi';
+
+export const backgroundArea: BackgroundArea = {
+ canvas: null,
+ context: null,
+ setup() {
+ this.canvas = document.getElementById('backgroundArea') as HTMLCanvasElement;
+ this.canvas.width = width;
+ this.canvas.height = height;
+ this.context = this.canvas.getContext('2d');
+ dots(true, false);
+ },
+ clear() {
+ if (!this.context || !this.canvas) {
+ return;
+ }
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ },
+};
diff --git a/v1/src/simulator/src/canvas2svg.js b/v1/src/simulator/src/canvas2svg.js
deleted file mode 100644
index d6f5dc64..00000000
--- a/v1/src/simulator/src/canvas2svg.js
+++ /dev/null
@@ -1,1433 +0,0 @@
-/*!!
- * Canvas 2 Svg v1.0.19
- * A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document.
- *
- * Licensed under the MIT license:
- * http://www.opensource.org/licenses/mit-license.php
- *
- * Author:
- * Kerry Liu
- *
- * Copyright (c) 2014 Gliffy Inc.
- */
-
-/**
- * CircuitVerse - Edited
- * Latest npm package is 1.0.16 but we need 1.0.19
- */
-
-'use strict'
-
-var STYLES, ctx, CanvasGradient, CanvasPattern, namedEntities
-
-//helper function to format a string
-function format(str, args) {
- var keys = Object.keys(args),
- i
- for (i = 0; i < keys.length; i++) {
- str = str.replace(
- new RegExp('\\{' + keys[i] + '\\}', 'gi'),
- args[keys[i]]
- )
- }
- return str
-}
-
-//helper function that generates a random string
-function randomString(holder) {
- var chars, randomstring, i
- if (!holder) {
- throw new Error(
- 'cannot create a random attribute name for an undefined object'
- )
- }
- chars = 'ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'
- randomstring = ''
- do {
- randomstring = ''
- for (i = 0; i < 12; i++) {
- randomstring += chars[Math.floor(Math.random() * chars.length)]
- }
- } while (holder[randomstring])
- return randomstring
-}
-
-//helper function to map named to numbered entities
-function createNamedToNumberedLookup(items, radix) {
- var i,
- entity,
- lookup = {},
- base10,
- base16
- items = items.split(',')
- radix = radix || 10
- // Map from named to numbered entities.
- for (i = 0; i < items.length; i += 2) {
- entity = '&' + items[i + 1] + ';'
- base10 = parseInt(items[i], radix)
- lookup[entity] = '' + base10 + ';'
- }
- //FF and IE need to create a regex from hex values ie == \xa0
- lookup['\\xa0'] = ' '
- return lookup
-}
-
-//helper function to map canvas-textAlign to svg-textAnchor
-function getTextAnchor(textAlign) {
- //TODO: support rtl languages
- var mapping = {
- left: 'start',
- right: 'end',
- center: 'middle',
- start: 'start',
- end: 'end',
- }
- return mapping[textAlign] || mapping.start
-}
-
-//helper function to map canvas-textBaseline to svg-dominantBaseline
-function getDominantBaseline(textBaseline) {
- //INFO: not supported in all browsers
- var mapping = {
- alphabetic: 'alphabetic',
- hanging: 'hanging',
- top: 'text-before-edge',
- bottom: 'text-after-edge',
- middle: 'central',
- }
- return mapping[textBaseline] || mapping.alphabetic
-}
-
-// Unpack entities lookup where the numbers are in radix 32 to reduce the size
-// entity mapping courtesy of tinymce
-namedEntities = createNamedToNumberedLookup(
- '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
- '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
- '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
- '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
- '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
- '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
- '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
- '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
- '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
- '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
- 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
- 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
- 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
- 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
- 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
- '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
- '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
- '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
- '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
- '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
- 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
- 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
- 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
- '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
- '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro',
- 32
-)
-
-//Some basic mappings for attributes and default values.
-STYLES = {
- strokeStyle: {
- svgAttr: 'stroke', //corresponding svg attribute
- canvas: '#000000', //canvas default
- svg: 'none', //svg default
- apply: 'stroke', //apply on stroke() or fill()
- },
- fillStyle: {
- svgAttr: 'fill',
- canvas: '#000000',
- svg: null, //svg default is black, but we need to special case this to handle canvas stroke without fill
- apply: 'fill',
- },
- lineCap: {
- svgAttr: 'stroke-linecap',
- canvas: 'butt',
- svg: 'butt',
- apply: 'stroke',
- },
- lineJoin: {
- svgAttr: 'stroke-linejoin',
- canvas: 'miter',
- svg: 'miter',
- apply: 'stroke',
- },
- miterLimit: {
- svgAttr: 'stroke-miterlimit',
- canvas: 10,
- svg: 4,
- apply: 'stroke',
- },
- lineWidth: {
- svgAttr: 'stroke-width',
- canvas: 1,
- svg: 1,
- apply: 'stroke',
- },
- globalAlpha: {
- svgAttr: 'opacity',
- canvas: 1,
- svg: 1,
- apply: 'fill stroke',
- },
- font: {
- //font converts to multiple svg attributes, there is custom logic for this
- canvas: '10px sans-serif',
- },
- shadowColor: {
- canvas: '#000000',
- },
- shadowOffsetX: {
- canvas: 0,
- },
- shadowOffsetY: {
- canvas: 0,
- },
- shadowBlur: {
- canvas: 0,
- },
- textAlign: {
- canvas: 'start',
- },
- textBaseline: {
- canvas: 'alphabetic',
- },
- lineDash: {
- svgAttr: 'stroke-dasharray',
- canvas: [],
- svg: null,
- apply: 'stroke',
- },
-}
-
-/**
- *
- * @param gradientNode - reference to the gradient
- * @constructor
- */
-CanvasGradient = function (gradientNode, ctx) {
- this.__root = gradientNode
- this.__ctx = ctx
-}
-
-/**
- * Adds a color stop to the gradient root
- */
-CanvasGradient.prototype.addColorStop = function (offset, color) {
- var stop = this.__ctx.__createElement('stop'),
- regex,
- matches
- stop.setAttribute('offset', offset)
- if (color.indexOf('rgba') !== -1) {
- //separate alpha value, since webkit can't handle it
- regex =
- /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi
- matches = regex.exec(color)
- stop.setAttribute(
- 'stop-color',
- format('rgb({r},{g},{b})', {
- r: matches[1],
- g: matches[2],
- b: matches[3],
- })
- )
- stop.setAttribute('stop-opacity', matches[4])
- } else {
- stop.setAttribute('stop-color', color)
- }
- this.__root.appendChild(stop)
-}
-
-CanvasPattern = function (pattern, ctx) {
- this.__root = pattern
- this.__ctx = ctx
-}
-
-/**
- * The mock canvas context
- * @param o - options include:
- * ctx - existing Context2D to wrap around
- * width - width of your canvas (defaults to 500)
- * height - height of your canvas (defaults to 500)
- * enableMirroring - enables canvas mirroring (get image data) (defaults to false)
- * document - the document object (defaults to the current document)
- */
-ctx = function (o) {
- var defaultOptions = { width: 500, height: 500, enableMirroring: false },
- options
-
- //keep support for this way of calling C2S: new C2S(width,height)
- if (arguments.length > 1) {
- options = defaultOptions
- options.width = arguments[0]
- options.height = arguments[1]
- } else if (!o) {
- options = defaultOptions
- } else {
- options = o
- }
-
- if (!(this instanceof ctx)) {
- //did someone call this without new?
- return new ctx(options)
- }
-
- //setup options
- this.width = options.width || defaultOptions.width
- this.height = options.height || defaultOptions.height
- this.enableMirroring =
- options.enableMirroring !== undefined
- ? options.enableMirroring
- : defaultOptions.enableMirroring
-
- this.canvas = this ///point back to this instance!
- this.__document = options.document || document
-
- // allow passing in an existing context to wrap around
- // if a context is passed in, we know a canvas already exist
- if (options.ctx) {
- this.__ctx = options.ctx
- } else {
- this.__canvas = this.__document.createElement('canvas')
- this.__ctx = this.__canvas.getContext('2d')
- }
-
- this.__setDefaultStyles()
- this.__stack = [this.__getStyleState()]
- this.__groupStack = []
-
- //the root svg element
- this.__root = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'svg'
- )
- this.__root.setAttribute('version', 1.1)
- this.__root.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
- this.__root.setAttributeNS(
- 'http://www.w3.org/2000/xmlns/',
- 'xmlns:xlink',
- 'http://www.w3.org/1999/xlink'
- )
- this.__root.setAttribute('width', this.width)
- this.__root.setAttribute('height', this.height)
-
- //make sure we don't generate the same ids in defs
- this.__ids = {}
-
- //defs tag
- this.__defs = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'defs'
- )
- this.__root.appendChild(this.__defs)
-
- //also add a group child. the svg element can't use the transform attribute
- this.__currentElement = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'g'
- )
- this.__root.appendChild(this.__currentElement)
-}
-
-/**
- * Creates the specified svg element
- * @private
- */
-ctx.prototype.__createElement = function (elementName, properties, resetFill) {
- if (typeof properties === 'undefined') {
- properties = {}
- }
-
- var element = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- elementName
- ),
- keys = Object.keys(properties),
- i,
- key
- if (resetFill) {
- //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black.
- element.setAttribute('fill', 'none')
- element.setAttribute('stroke', 'none')
- }
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- element.setAttribute(key, properties[key])
- }
- return element
-}
-
-/**
- * Applies default canvas styles to the context
- * @private
- */
-ctx.prototype.__setDefaultStyles = function () {
- //default 2d canvas context properties see:http://www.w3.org/TR/2dcontext/
- var keys = Object.keys(STYLES),
- i,
- key
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- this[key] = STYLES[key].canvas
- }
-}
-
-/**
- * Applies styles on restore
- * @param styleState
- * @private
- */
-ctx.prototype.__applyStyleState = function (styleState) {
- var keys = Object.keys(styleState),
- i,
- key
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- this[key] = styleState[key]
- }
-}
-
-/**
- * Gets the current style state
- * @return {Object}
- * @private
- */
-ctx.prototype.__getStyleState = function () {
- var i,
- styleState = {},
- keys = Object.keys(STYLES),
- key
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- styleState[key] = this[key]
- }
- return styleState
-}
-
-/**
- * Apples the current styles to the current SVG element. On "ctx.fill" or "ctx.stroke"
- * @param type
- * @private
- */
-ctx.prototype.__applyStyleToCurrentElement = function (type) {
- var currentElement = this.__currentElement
- var currentStyleGroup = this.__currentElementsToStyle
- if (currentStyleGroup) {
- currentElement.setAttribute(type, '')
- currentElement = currentStyleGroup.element
- currentStyleGroup.children.forEach(function (node) {
- node.setAttribute(type, '')
- })
- }
-
- var keys = Object.keys(STYLES),
- i,
- style,
- value,
- id,
- regex,
- matches
- for (i = 0; i < keys.length; i++) {
- style = STYLES[keys[i]]
- value = this[keys[i]]
- if (style.apply) {
- //is this a gradient or pattern?
- if (value instanceof CanvasPattern) {
- //pattern
- if (value.__ctx) {
- //copy over defs
- while (value.__ctx.__defs.childNodes.length) {
- id = value.__ctx.__defs.childNodes[0].getAttribute('id')
- this.__ids[id] = id
- this.__defs.appendChild(
- value.__ctx.__defs.childNodes[0]
- )
- }
- }
- currentElement.setAttribute(
- style.apply,
- format('url(#{id})', {
- id: value.__root.getAttribute('id'),
- })
- )
- } else if (value instanceof CanvasGradient) {
- //gradient
- currentElement.setAttribute(
- style.apply,
- format('url(#{id})', {
- id: value.__root.getAttribute('id'),
- })
- )
- } else if (
- style.apply.indexOf(type) !== -1 &&
- style.svg !== value
- ) {
- if (
- (style.svgAttr === 'stroke' || style.svgAttr === 'fill') &&
- value.indexOf('rgba') !== -1
- ) {
- //separate alpha value, since illustrator can't handle it
- regex =
- /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi
- matches = regex.exec(value)
- currentElement.setAttribute(
- style.svgAttr,
- format('rgb({r},{g},{b})', {
- r: matches[1],
- g: matches[2],
- b: matches[3],
- })
- )
- //should take globalAlpha here
- var opacity = matches[4]
- var globalAlpha = this.globalAlpha
- if (globalAlpha != null) {
- opacity *= globalAlpha
- }
- currentElement.setAttribute(
- style.svgAttr + '-opacity',
- opacity
- )
- } else {
- var attr = style.svgAttr
- if (keys[i] === 'globalAlpha') {
- attr = type + '-' + style.svgAttr
- if (currentElement.getAttribute(attr)) {
- //fill-opacity or stroke-opacity has already been set by stroke or fill.
- continue
- }
- }
- //otherwise only update attribute if right type, and not svg default
- currentElement.setAttribute(attr, value)
- }
- }
- }
- }
-}
-
-/**
- * Will return the closest group or svg node. May return the current element.
- * @private
- */
-ctx.prototype.__closestGroupOrSvg = function (node) {
- node = node || this.__currentElement
- if (node.nodeName === 'g' || node.nodeName === 'svg') {
- return node
- } else {
- return this.__closestGroupOrSvg(node.parentNode)
- }
-}
-
-/**
- * Returns the serialized value of the svg so far
- * @param fixNamedEntities - Standalone SVG doesn't support named entities, which document.createTextNode encodes.
- * If true, we attempt to find all named entities and encode it as a numeric entity.
- * @return serialized svg
- */
-ctx.prototype.getSerializedSvg = function (fixNamedEntities) {
- var serialized = new XMLSerializer().serializeToString(this.__root),
- keys,
- i,
- key,
- value,
- regexp,
- xmlns
-
- //IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
- xmlns =
- /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi
- if (xmlns.test(serialized)) {
- serialized = serialized.replace(
- 'xmlns="http://www.w3.org/2000/svg',
- 'xmlns:xlink="http://www.w3.org/1999/xlink'
- )
- }
-
- if (fixNamedEntities) {
- keys = Object.keys(namedEntities)
- //loop over each named entity and replace with the proper equivalent.
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- value = namedEntities[key]
- regexp = new RegExp(key, 'gi')
- if (regexp.test(serialized)) {
- serialized = serialized.replace(regexp, value)
- }
- }
- }
-
- return serialized
-}
-
-/**
- * Returns the root svg
- * @return svg
- */
-ctx.prototype.getSvg = function () {
- return this.__root
-}
-/**
- * Will generate a group tag.
- */
-ctx.prototype.save = function () {
- var group = this.__createElement('g')
- var parent = this.__closestGroupOrSvg()
- this.__groupStack.push(parent)
- parent.appendChild(group)
- this.__currentElement = group
- this.__stack.push(this.__getStyleState())
-}
-/**
- * Sets current element to parent, or just root if already root
- */
-ctx.prototype.restore = function () {
- this.__currentElement = this.__groupStack.pop()
- this.__currentElementsToStyle = null
- //Clearing canvas will make the poped group invalid, currentElement is set to the root group node.
- if (!this.__currentElement) {
- this.__currentElement = this.__root.childNodes[1]
- }
- var state = this.__stack.pop()
- this.__applyStyleState(state)
-}
-
-/**
- * Helper method to add transform
- * @private
- */
-ctx.prototype.__addTransform = function (t) {
- //if the current element has siblings, add another group
- var parent = this.__closestGroupOrSvg()
- if (parent.childNodes.length > 0) {
- if (this.__currentElement.nodeName === 'path') {
- if (!this.__currentElementsToStyle)
- this.__currentElementsToStyle = {
- element: parent,
- children: [],
- }
- this.__currentElementsToStyle.children.push(this.__currentElement)
- this.__applyCurrentDefaultPath()
- }
-
- var group = this.__createElement('g')
- parent.appendChild(group)
- this.__currentElement = group
- }
-
- var transform = this.__currentElement.getAttribute('transform')
- if (transform) {
- transform += ' '
- } else {
- transform = ''
- }
- transform += t
- this.__currentElement.setAttribute('transform', transform)
-}
-
-/**
- * scales the current element
- */
-ctx.prototype.scale = function (x, y) {
- if (y === undefined) {
- y = x
- }
- this.__addTransform(format('scale({x},{y})', { x: x, y: y }))
-}
-
-/**
- * rotates the current element
- */
-ctx.prototype.rotate = function (angle) {
- var degrees = (angle * 180) / Math.PI
- this.__addTransform(
- format('rotate({angle},{cx},{cy})', { angle: degrees, cx: 0, cy: 0 })
- )
-}
-
-/**
- * translates the current element
- */
-ctx.prototype.translate = function (x, y) {
- this.__addTransform(format('translate({x},{y})', { x: x, y: y }))
-}
-
-/**
- * applies a transform to the current element
- */
-ctx.prototype.transform = function (a, b, c, d, e, f) {
- this.__addTransform(
- format('matrix({a},{b},{c},{d},{e},{f})', {
- a: a,
- b: b,
- c: c,
- d: d,
- e: e,
- f: f,
- })
- )
-}
-
-/**
- * Create a new Path Element
- */
-ctx.prototype.beginPath = function () {
- var path, parent
-
- // Note that there is only one current default path, it is not part of the drawing state.
- // See also: https://html.spec.whatwg.org/multipage/scripting.html#current-default-path
- this.__currentDefaultPath = ''
- this.__currentPosition = {}
-
- path = this.__createElement('path', {}, true)
- parent = this.__closestGroupOrSvg()
- parent.appendChild(path)
- this.__currentElement = path
-}
-
-/**
- * Helper function to apply currentDefaultPath to current path element
- * @private
- */
-ctx.prototype.__applyCurrentDefaultPath = function () {
- var currentElement = this.__currentElement
- if (currentElement.nodeName === 'path') {
- currentElement.setAttribute('d', this.__currentDefaultPath)
- } else {
- console.error(
- 'Attempted to apply path command to node',
- currentElement.nodeName
- )
- }
-}
-
-/**
- * Helper function to add path command
- * @private
- */
-ctx.prototype.__addPathCommand = function (command) {
- this.__currentDefaultPath += ' '
- this.__currentDefaultPath += command
-}
-
-/**
- * Adds the move command to the current path element,
- * if the currentPathElement is not empty create a new path element
- */
-ctx.prototype.moveTo = function (x, y) {
- if (this.__currentElement.nodeName !== 'path') {
- this.beginPath()
- }
-
- // creates a new subpath with the given point
- this.__currentPosition = { x: x, y: y }
- this.__addPathCommand(format('M {x} {y}', { x: x, y: y }))
-}
-
-/**
- * Closes the current path
- */
-ctx.prototype.closePath = function () {
- if (this.__currentDefaultPath) {
- this.__addPathCommand('Z')
- }
-}
-
-/**
- * Adds a line to command
- */
-ctx.prototype.lineTo = function (x, y) {
- this.__currentPosition = { x: x, y: y }
- if (this.__currentDefaultPath.indexOf('M') > -1) {
- this.__addPathCommand(format('L {x} {y}', { x: x, y: y }))
- } else {
- this.__addPathCommand(format('M {x} {y}', { x: x, y: y }))
- }
-}
-
-/**
- * Add a bezier command
- */
-ctx.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
- this.__currentPosition = { x: x, y: y }
- this.__addPathCommand(
- format('C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}', {
- cp1x: cp1x,
- cp1y: cp1y,
- cp2x: cp2x,
- cp2y: cp2y,
- x: x,
- y: y,
- })
- )
-}
-
-/**
- * Adds a quadratic curve to command
- */
-ctx.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
- this.__currentPosition = { x: x, y: y }
- this.__addPathCommand(
- format('Q {cpx} {cpy} {x} {y}', { cpx: cpx, cpy: cpy, x: x, y: y })
- )
-}
-
-/**
- * Return a new normalized vector of given vector
- */
-var normalize = function (vector) {
- var len = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1])
- return [vector[0] / len, vector[1] / len]
-}
-
-/**
- * Adds the arcTo to the current path
- *
- * @see http://www.w3.org/TR/2015/WD-2dcontext-20150514/#dom-context-2d-arcto
- */
-ctx.prototype.arcTo = function (x1, y1, x2, y2, radius) {
- // Let the point (x0, y0) be the last point in the subpath.
- var x0 = this.__currentPosition && this.__currentPosition.x
- var y0 = this.__currentPosition && this.__currentPosition.y
-
- // First ensure there is a subpath for (x1, y1).
- if (typeof x0 == 'undefined' || typeof y0 == 'undefined') {
- return
- }
-
- // Negative values for radius must cause the implementation to throw an IndexSizeError exception.
- if (radius < 0) {
- throw new Error(
- 'IndexSizeError: The radius provided (' + radius + ') is negative.'
- )
- }
-
- // If the point (x0, y0) is equal to the point (x1, y1),
- // or if the point (x1, y1) is equal to the point (x2, y2),
- // or if the radius radius is zero,
- // then the method must add the point (x1, y1) to the subpath,
- // and connect that point to the previous point (x0, y0) by a straight line.
- if ((x0 === x1 && y0 === y1) || (x1 === x2 && y1 === y2) || radius === 0) {
- this.lineTo(x1, y1)
- return
- }
-
- // Otherwise, if the points (x0, y0), (x1, y1), and (x2, y2) all lie on a single straight line,
- // then the method must add the point (x1, y1) to the subpath,
- // and connect that point to the previous point (x0, y0) by a straight line.
- var unit_vec_p1_p0 = normalize([x0 - x1, y0 - y1])
- var unit_vec_p1_p2 = normalize([x2 - x1, y2 - y1])
- if (
- unit_vec_p1_p0[0] * unit_vec_p1_p2[1] ===
- unit_vec_p1_p0[1] * unit_vec_p1_p2[0]
- ) {
- this.lineTo(x1, y1)
- return
- }
-
- // Otherwise, let The Arc be the shortest arc given by circumference of the circle that has radius radius,
- // and that has one point tangent to the half-infinite line that crosses the point (x0, y0) and ends at the point (x1, y1),
- // and that has a different point tangent to the half-infinite line that ends at the point (x1, y1), and crosses the point (x2, y2).
- // The points at which this circle touches these two lines are called the start and end tangent points respectively.
-
- // note that both vectors are unit vectors, so the length is 1
- var cos =
- unit_vec_p1_p0[0] * unit_vec_p1_p2[0] +
- unit_vec_p1_p0[1] * unit_vec_p1_p2[1]
- var theta = Math.acos(Math.abs(cos))
-
- // Calculate origin
- var unit_vec_p1_origin = normalize([
- unit_vec_p1_p0[0] + unit_vec_p1_p2[0],
- unit_vec_p1_p0[1] + unit_vec_p1_p2[1],
- ])
- var len_p1_origin = radius / Math.sin(theta / 2)
- var x = x1 + len_p1_origin * unit_vec_p1_origin[0]
- var y = y1 + len_p1_origin * unit_vec_p1_origin[1]
-
- // Calculate start angle and end angle
- // rotate 90deg clockwise (note that y axis points to its down)
- var unit_vec_origin_start_tangent = [-unit_vec_p1_p0[1], unit_vec_p1_p0[0]]
- // rotate 90deg counter clockwise (note that y axis points to its down)
- var unit_vec_origin_end_tangent = [unit_vec_p1_p2[1], -unit_vec_p1_p2[0]]
- var getAngle = function (vector) {
- // get angle (clockwise) between vector and (1, 0)
- var x = vector[0]
- var y = vector[1]
- if (y >= 0) {
- // note that y axis points to its down
- return Math.acos(x)
- } else {
- return -Math.acos(x)
- }
- }
- var startAngle = getAngle(unit_vec_origin_start_tangent)
- var endAngle = getAngle(unit_vec_origin_end_tangent)
-
- // Connect the point (x0, y0) to the start tangent point by a straight line
- this.lineTo(
- x + unit_vec_origin_start_tangent[0] * radius,
- y + unit_vec_origin_start_tangent[1] * radius
- )
-
- // Connect the start tangent point to the end tangent point by arc
- // and adding the end tangent point to the subpath.
- this.arc(x, y, radius, startAngle, endAngle)
-}
-
-/**
- * Sets the stroke property on the current element
- */
-ctx.prototype.stroke = function () {
- if (this.__currentElement.nodeName === 'path') {
- this.__currentElement.setAttribute('paint-order', 'fill stroke markers')
- }
- this.__applyCurrentDefaultPath()
- this.__applyStyleToCurrentElement('stroke')
-}
-
-/**
- * Sets fill properties on the current element
- */
-ctx.prototype.fill = function () {
- if (this.__currentElement.nodeName === 'path') {
- this.__currentElement.setAttribute('paint-order', 'stroke fill markers')
- }
- this.__applyCurrentDefaultPath()
- this.__applyStyleToCurrentElement('fill')
-}
-
-/**
- * Adds a rectangle to the path.
- */
-ctx.prototype.rect = function (x, y, width, height) {
- if (this.__currentElement.nodeName !== 'path') {
- this.beginPath()
- }
- this.moveTo(x, y)
- this.lineTo(x + width, y)
- this.lineTo(x + width, y + height)
- this.lineTo(x, y + height)
- this.lineTo(x, y)
- this.closePath()
-}
-
-/**
- * adds a rectangle element
- */
-ctx.prototype.fillRect = function (x, y, width, height) {
- var rect, parent
- rect = this.__createElement(
- 'rect',
- {
- x: x,
- y: y,
- width: width,
- height: height,
- },
- true
- )
- parent = this.__closestGroupOrSvg()
- parent.appendChild(rect)
- this.__currentElement = rect
- this.__applyStyleToCurrentElement('fill')
-}
-
-/**
- * Draws a rectangle with no fill
- * @param x
- * @param y
- * @param width
- * @param height
- */
-ctx.prototype.strokeRect = function (x, y, width, height) {
- var rect, parent
- rect = this.__createElement(
- 'rect',
- {
- x: x,
- y: y,
- width: width,
- height: height,
- },
- true
- )
- parent = this.__closestGroupOrSvg()
- parent.appendChild(rect)
- this.__currentElement = rect
- this.__applyStyleToCurrentElement('stroke')
-}
-
-/**
- * Clear entire canvas:
- * 1. save current transforms
- * 2. remove all the childNodes of the root g element
- */
-ctx.prototype.__clearCanvas = function () {
- var current = this.__closestGroupOrSvg(),
- transform = current.getAttribute('transform')
- var rootGroup = this.__root.childNodes[1]
- var childNodes = rootGroup.childNodes
- for (var i = childNodes.length - 1; i >= 0; i--) {
- if (childNodes[i]) {
- rootGroup.removeChild(childNodes[i])
- }
- }
- this.__currentElement = rootGroup
- //reset __groupStack as all the child group nodes are all removed.
- this.__groupStack = []
- if (transform) {
- this.__addTransform(transform)
- }
-}
-
-/**
- * "Clears" a canvas by just drawing a white rectangle in the current group.
- */
-ctx.prototype.clearRect = function (x, y, width, height) {
- //clear entire canvas
- if (x === 0 && y === 0 && width === this.width && height === this.height) {
- this.__clearCanvas()
- return
- }
- var rect,
- parent = this.__closestGroupOrSvg()
- rect = this.__createElement(
- 'rect',
- {
- x: x,
- y: y,
- width: width,
- height: height,
- fill: '#FFFFFF',
- },
- true
- )
- parent.appendChild(rect)
-}
-
-/**
- * Adds a linear gradient to a defs tag.
- * Returns a canvas gradient object that has a reference to it's parent def
- */
-ctx.prototype.createLinearGradient = function (x1, y1, x2, y2) {
- var grad = this.__createElement(
- 'linearGradient',
- {
- id: randomString(this.__ids),
- x1: x1 + 'px',
- x2: x2 + 'px',
- y1: y1 + 'px',
- y2: y2 + 'px',
- gradientUnits: 'userSpaceOnUse',
- },
- false
- )
- this.__defs.appendChild(grad)
- return new CanvasGradient(grad, this)
-}
-
-/**
- * Adds a radial gradient to a defs tag.
- * Returns a canvas gradient object that has a reference to it's parent def
- */
-ctx.prototype.createRadialGradient = function (x0, y0, r0, x1, y1, r1) {
- var grad = this.__createElement(
- 'radialGradient',
- {
- id: randomString(this.__ids),
- cx: x1 + 'px',
- cy: y1 + 'px',
- r: r1 + 'px',
- fx: x0 + 'px',
- fy: y0 + 'px',
- gradientUnits: 'userSpaceOnUse',
- },
- false
- )
- this.__defs.appendChild(grad)
- return new CanvasGradient(grad, this)
-}
-
-/**
- * Parses the font string and returns svg mapping
- * @private
- */
-ctx.prototype.__parseFont = function () {
- var regex =
- /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z0-9]+?)\s*$/i
- var fontPart = regex.exec(this.font)
- var data = {
- style: fontPart[1] || 'normal',
- size: fontPart[4] || '10px',
- family: fontPart[6] || 'sans-serif',
- weight: fontPart[3] || 'normal',
- decoration: fontPart[2] || 'normal',
- href: null,
- }
-
- //canvas doesn't support underline natively, but we can pass this attribute
- if (this.__fontUnderline === 'underline') {
- data.decoration = 'underline'
- }
-
- //canvas also doesn't support linking, but we can pass this as well
- if (this.__fontHref) {
- data.href = this.__fontHref
- }
-
- return data
-}
-
-/**
- * Helper to link text fragments
- * @param font
- * @param element
- * @return {*}
- * @private
- */
-ctx.prototype.__wrapTextLink = function (font, element) {
- if (font.href) {
- var a = this.__createElement('a')
- a.setAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'xlink:href',
- font.href
- )
- a.appendChild(element)
- return a
- }
- return element
-}
-
-/**
- * Fills or strokes text
- * @param text
- * @param x
- * @param y
- * @param action - stroke or fill
- * @private
- */
-ctx.prototype.__applyText = function (text, x, y, action) {
- var font = this.__parseFont(),
- parent = this.__closestGroupOrSvg(),
- textElement = this.__createElement(
- 'text',
- {
- 'font-family': font.family,
- 'font-size': font.size,
- 'font-style': font.style,
- 'font-weight': font.weight,
- 'text-decoration': font.decoration,
- x: x,
- y: y,
- 'text-anchor': getTextAnchor(this.textAlign),
- 'dominant-baseline': getDominantBaseline(this.textBaseline),
- },
- true
- )
-
- textElement.appendChild(this.__document.createTextNode(text))
- this.__currentElement = textElement
- this.__applyStyleToCurrentElement(action)
- parent.appendChild(this.__wrapTextLink(font, textElement))
-}
-
-/**
- * Creates a text element
- * @param text
- * @param x
- * @param y
- */
-ctx.prototype.fillText = function (text, x, y) {
- this.__applyText(text, x, y, 'fill')
-}
-
-/**
- * Strokes text
- * @param text
- * @param x
- * @param y
- */
-ctx.prototype.strokeText = function (text, x, y) {
- this.__applyText(text, x, y, 'stroke')
-}
-
-/**
- * No need to implement this for svg.
- * @param text
- * @return {TextMetrics}
- */
-ctx.prototype.measureText = function (text) {
- this.__ctx.font = this.font
- return this.__ctx.measureText(text)
-}
-
-/**
- * Arc command!
- */
-ctx.prototype.arc = function (
- x,
- y,
- radius,
- startAngle,
- endAngle,
- counterClockwise
-) {
- // in canvas no circle is drawn if no angle is provided.
- if (startAngle === endAngle) {
- return
- }
- startAngle = startAngle % (2 * Math.PI)
- endAngle = endAngle % (2 * Math.PI)
- if (startAngle === endAngle) {
- //circle time! subtract some of the angle so svg is happy (svg elliptical arc can't draw a full circle)
- endAngle =
- (endAngle + 2 * Math.PI - 0.001 * (counterClockwise ? -1 : 1)) %
- (2 * Math.PI)
- }
- var endX = x + radius * Math.cos(endAngle),
- endY = y + radius * Math.sin(endAngle),
- startX = x + radius * Math.cos(startAngle),
- startY = y + radius * Math.sin(startAngle),
- sweepFlag = counterClockwise ? 0 : 1,
- largeArcFlag = 0,
- diff = endAngle - startAngle
-
- // https://github.com/gliffy/canvas2svg/issues/4
- if (diff < 0) {
- diff += 2 * Math.PI
- }
-
- if (counterClockwise) {
- largeArcFlag = diff > Math.PI ? 0 : 1
- } else {
- largeArcFlag = diff > Math.PI ? 1 : 0
- }
-
- this.lineTo(startX, startY)
- this.__addPathCommand(
- format(
- 'A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}',
- {
- rx: radius,
- ry: radius,
- xAxisRotation: 0,
- largeArcFlag: largeArcFlag,
- sweepFlag: sweepFlag,
- endX: endX,
- endY: endY,
- }
- )
- )
-
- this.__currentPosition = { x: endX, y: endY }
-}
-
-/**
- * Generates a ClipPath from the clip command.
- */
-ctx.prototype.clip = function () {
- var group = this.__closestGroupOrSvg(),
- clipPath = this.__createElement('clipPath'),
- id = randomString(this.__ids),
- newGroup = this.__createElement('g')
-
- this.__applyCurrentDefaultPath()
- group.removeChild(this.__currentElement)
- clipPath.setAttribute('id', id)
- clipPath.appendChild(this.__currentElement)
-
- this.__defs.appendChild(clipPath)
-
- //set the clip path to this group
- group.setAttribute('clip-path', format('url(#{id})', { id: id }))
-
- //clip paths can be scaled and transformed, we need to add another wrapper group to avoid later transformations
- // to this path
- group.appendChild(newGroup)
-
- this.__currentElement = newGroup
-}
-
-/**
- * Draws a canvas, image or mock context to this canvas.
- * Note that all svg dom manipulation uses node.childNodes rather than node.children for IE support.
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage
- */
-ctx.prototype.drawImage = function () {
- //convert arguments to a real array
- var args = Array.prototype.slice.call(arguments),
- image = args[0],
- dx,
- dy,
- dw,
- dh,
- sx = 0,
- sy = 0,
- sw,
- sh,
- parent,
- svg,
- defs,
- group,
- currentElement,
- svgImage,
- canvas,
- context,
- id
-
- if (args.length === 3) {
- dx = args[1]
- dy = args[2]
- sw = image.width
- sh = image.height
- dw = sw
- dh = sh
- } else if (args.length === 5) {
- dx = args[1]
- dy = args[2]
- dw = args[3]
- dh = args[4]
- sw = image.width
- sh = image.height
- } else if (args.length === 9) {
- sx = args[1]
- sy = args[2]
- sw = args[3]
- sh = args[4]
- dx = args[5]
- dy = args[6]
- dw = args[7]
- dh = args[8]
- } else {
- throw new Error(
- 'Inavlid number of arguments passed to drawImage: ' +
- arguments.length
- )
- }
-
- parent = this.__closestGroupOrSvg()
- currentElement = this.__currentElement
- var translateDirective = 'translate(' + dx + ', ' + dy + ')'
- if (image instanceof ctx) {
- //canvas2svg mock canvas context. In the future we may want to clone nodes instead.
- //also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context.
- svg = image.getSvg().cloneNode(true)
- if (svg.childNodes && svg.childNodes.length > 1) {
- defs = svg.childNodes[0]
- while (defs.childNodes.length) {
- id = defs.childNodes[0].getAttribute('id')
- this.__ids[id] = id
- this.__defs.appendChild(defs.childNodes[0])
- }
- group = svg.childNodes[1]
- if (group) {
- //save original transform
- var originTransform = group.getAttribute('transform')
- var transformDirective
- if (originTransform) {
- transformDirective =
- originTransform + ' ' + translateDirective
- } else {
- transformDirective = translateDirective
- }
- group.setAttribute('transform', transformDirective)
- parent.appendChild(group)
- }
- }
- } else if (image.nodeName === 'CANVAS' || image.nodeName === 'IMG') {
- //canvas or image
- svgImage = this.__createElement('image')
- svgImage.setAttribute('width', dw)
- svgImage.setAttribute('height', dh)
- svgImage.setAttribute('preserveAspectRatio', 'none')
-
- if (sx || sy || sw !== image.width || sh !== image.height) {
- //crop the image using a temporary canvas
- canvas = this.__document.createElement('canvas')
- canvas.width = dw
- canvas.height = dh
- context = canvas.getContext('2d')
- context.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh)
- image = canvas
- }
- svgImage.setAttribute('transform', translateDirective)
- svgImage.setAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'xlink:href',
- image.nodeName === 'CANVAS'
- ? image.toDataURL()
- : image.getAttribute('src')
- )
- parent.appendChild(svgImage)
- }
-}
-
-/**
- * Generates a pattern tag
- */
-ctx.prototype.createPattern = function (image, repetition) {
- var pattern = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'pattern'
- ),
- id = randomString(this.__ids),
- img
- pattern.setAttribute('id', id)
- pattern.setAttribute('width', image.width)
- pattern.setAttribute('height', image.height)
- if (image.nodeName === 'CANVAS' || image.nodeName === 'IMG') {
- img = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'image'
- )
- img.setAttribute('width', image.width)
- img.setAttribute('height', image.height)
- img.setAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'xlink:href',
- image.nodeName === 'CANVAS'
- ? image.toDataURL()
- : image.getAttribute('src')
- )
- pattern.appendChild(img)
- this.__defs.appendChild(pattern)
- } else if (image instanceof ctx) {
- pattern.appendChild(image.__root.childNodes[1])
- this.__defs.appendChild(pattern)
- }
- return new CanvasPattern(pattern, this)
-}
-
-ctx.prototype.setLineDash = function (dashArray) {
- if (dashArray && dashArray.length > 0) {
- this.lineDash = dashArray.join(',')
- } else {
- this.lineDash = null
- }
-}
-
-/**
- * Not yet implemented
- */
-ctx.prototype.drawFocusRing = function () {}
-ctx.prototype.createImageData = function () {}
-ctx.prototype.getImageData = function () {}
-ctx.prototype.putImageData = function () {}
-ctx.prototype.globalCompositeOperation = function () {}
-ctx.prototype.setTransform = function () {}
-
-//add options for alternative namespace
-// if (typeof window === "object") {
-// window.C2S = ctx;
-// }
-
-// CommonJS/Browserify
-// if (typeof module === "object" && typeof module.exports === "object") {
-// module.exports = ctx;
-// }
-
-export default ctx
diff --git a/v1/src/simulator/src/canvasApi.js b/v1/src/simulator/src/canvasApi.js
index 08ee65d3..950bb2b8 100644
--- a/v1/src/simulator/src/canvasApi.js
+++ b/v1/src/simulator/src/canvasApi.js
@@ -1,8 +1,9 @@
/* eslint-disable no-param-reassign */
-import backgroundArea from './backgroundArea'
-import simulationArea from './simulationArea'
+import { backgroundArea } from './backgroundArea'
+import { simulationArea } from './simulationArea'
import miniMapArea, { removeMiniMap, updatelastMinimapShown } from './minimap'
import { colors } from './themer/themer'
+import { updateOrder } from './metadata'
var unit = 10
@@ -107,9 +108,10 @@ export function changeScale(delta, xx, yy, method = 1) {
if (!embed && !lightMode) {
findDimensions(globalScope)
miniMapArea.setup()
- $('#miniMap').show()
+ let miniMap = document.querySelector('#miniMap');
+ miniMap.style.display = 'block';
updatelastMinimapShown()
- $('#miniMap').show()
+ miniMap.style.display = 'block';
setTimeout(removeMiniMap, 2000)
}
}
@@ -240,7 +242,10 @@ export function moveTo(ctx, x1, y1, xx, yy, dir, bypass = false) {
xx *= globalScope.scale
yy *= globalScope.scale
if (bypass) {
- ctx.moveTo(xx + globalScope.ox + newX, yy + globalScope.oy + newY)
+ ctx.moveTo(
+ Math.round(xx + globalScope.ox + newX),
+ Math.round(yy + globalScope.oy + newY)
+ )
} else {
ctx.moveTo(
Math.round(xx + globalScope.ox + newX - correction) + correction,
@@ -437,9 +442,9 @@ export function drawLine(ctx, x1, y1, x2, y2, color, width) {
// Checks if string color is a valid color using a hack
export function validColor(color) {
- var $div = $('
')
- $div.css('border', `1px solid ${color}`)
- return $div.css('border-color') !== ''
+ let newDiv = document.createElement('div')
+ newDiv.style.border = `1px solid ${color}`
+ return newDiv.style.borderColor !== ''
}
// Helper function to color "RED" to RGBA
diff --git a/v1/src/simulator/src/circuit.js b/v1/src/simulator/src/circuit.ts
similarity index 69%
rename from v1/src/simulator/src/circuit.js
rename to v1/src/simulator/src/circuit.ts
index f86429e3..cf04fc9e 100644
--- a/v1/src/simulator/src/circuit.js
+++ b/v1/src/simulator/src/circuit.ts
@@ -11,13 +11,10 @@
/* eslint-disable no-alert */
import CircuitElement from './circuitElement'
import plotArea from './plotArea'
-import simulationArea, { changeClockTime } from './simulationArea'
+import { simulationArea } from './simulationArea'
import {
stripTags,
uniq,
- showMessage,
- showError,
- truncateString,
} from './utils'
import { findDimensions, dots } from './canvasApi'
import { updateRestrictedElementsList } from './restrictedElementDiv'
@@ -32,28 +29,33 @@ import {
changeLightMode,
} from './engine'
import { toggleLayoutMode, layoutModeGet } from './layoutMode'
-import { setProjectName, getProjectName } from './data/save'
+import { setProjectName } from './data/save'
import { changeClockEnable } from './sequential'
import { changeInputSize } from './modules'
import { verilogModeGet, verilogModeSet } from './Verilog2CV'
-import { updateTestbenchUI } from './testbench'
import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
-import { toRef, toRefs } from 'vue'
+import { toRefs } from 'vue'
import { provideCircuitName } from '#/components/helpers/promptComponent/PromptComponent.vue'
import { deleteCurrentCircuit } from '#/components/helpers/deleteCircuit/DeleteCircuit.vue'
+import { useSimulatorMobileStore } from '#/store/simulatorMobileStore'
+import { inputList, moduleList } from './metadata'
export const circuitProperty = {
toggleLayoutMode,
setProjectName,
changeCircuitName,
- // changeClockTime,
deleteCurrentCircuit,
changeClockEnable,
changeInputSize,
changeLightMode,
+ changeClockTime
}
-export var scopeList = {}
+function changeClockTime(t: number) {
+ simulationArea.changeClockTime(t)
+}
+
+export let scopeList: { [key: string]: Scope } = {}
export function resetScopeList() {
const simulatorStore = SimulatorStore()
const { circuit_list } = toRefs(simulatorStore)
@@ -65,20 +67,20 @@ export function resetScopeList() {
* Disables layoutMode if enabled
* Changes UI tab etc
* Sets flags to make updates, resets most of the things
- * @param {string} id - identifier for circuit
- * @category circuit
*/
-export function switchCircuit(id) {
+export function switchCircuit(id: string) {
// TODO: fix tomorrow
const simulatorStore = SimulatorStore()
const { circuit_list } = toRefs(simulatorStore)
const { activeCircuit } = toRefs(simulatorStore)
+ const simulatorMobileStore = toRefs(useSimulatorMobileStore())
if (layoutModeGet()) {
toggleLayoutMode()
}
if (!scopeList[id].verilogMetadata.isVerilogCircuit) {
verilogModeSet(false)
+ simulatorMobileStore.isVerilog.value = false
}
// globalScope.fixLayout();
@@ -94,6 +96,7 @@ export function switchCircuit(id) {
globalScope = scopeList[id]
if (globalScope.verilogMetadata.isVerilogCircuit) {
verilogModeSet(true)
+ simulatorMobileStore.isVerilog.value = true
}
if (globalScope.isVisible()) {
// $(`#${id}`).addClass('current')
@@ -101,8 +104,10 @@ export function switchCircuit(id) {
(circuit) => circuit.id == id
) // TODO: add strict equality after typescript
circuit_list.value[index].focussed = true
- activeCircuit.value.id = globalScope.id
- activeCircuit.value.name = globalScope.name
+ if (activeCircuit.value) {
+ activeCircuit.value.id = globalScope.id
+ activeCircuit.value.name = globalScope.name
+ }
}
updateSimulationSet(true)
updateSubcircuitSet(true)
@@ -111,7 +116,6 @@ export function switchCircuit(id) {
simulationArea.lastSelected = globalScope.root
if (!embed) {
showProperties(simulationArea.lastSelected)
- updateTestbenchUI()
plotArea.reset()
}
updateCanvasSet(true)
@@ -121,13 +125,18 @@ export function switchCircuit(id) {
updateRestrictedElementsList()
}
-export function getDependenciesList(scopeId) {
+export function getDependenciesList(scopeId: string | number) {
let scope = scopeList[scopeId]
if (scope == undefined) scope = scopeList[globalScope.id]
let dependencies = ''
- for (id in scopeList) {
- if (id != scope.id && scopeList[id].checkDependency(scope.id)) {
+ for (let id in scopeList) {
+ let formattedId;
+ if (typeof scopeId === 'number')
+ formattedId = scopeId;
+ else
+ formattedId = parseInt(scopeId);
+ if (id != scope.id && scopeList[id].checkDependency(formattedId)) {
if (dependencies === '') {
dependencies = scopeList[id].name
} else {
@@ -171,8 +180,8 @@ export function getDependenciesList(scopeId) {
* Wrapper function around newCircuit to be called from + button on UI
*/
export async function createNewCircuitScope(
- name,
- id = undefined,
+ name: string | Error | undefined = undefined,
+ id: string | undefined = undefined,
isVerilog = false,
isVerilogMain = false
) {
@@ -185,28 +194,31 @@ export async function createNewCircuitScope(
newCircuit(name, id, isVerilog, isVerilogMain)
if (!embed) {
showProperties(simulationArea.lastSelected)
- updateTestbenchUI()
plotArea.reset()
}
return true
}
+export function circuitNameClicked() {
+ simulationArea.lastSelected = globalScope.root
+}
+
/**
* Function to create new circuit
* Function creates button in tab, creates scope and switches to this circuit
- * @param {string} name - name of the new circuit
- * @param {string} id - identifier for circuit
- * @category circuit
*/
-export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) {
+export function newCircuit(name: string | undefined, id: string | undefined, isVerilog = false, isVerilogMain = false) {
const simulatorStore = SimulatorStore()
const { circuit_list } = toRefs(simulatorStore)
const { activeCircuit } = toRefs(simulatorStore)
+ const { circuit_name_clickable } = toRefs(simulatorStore)
+ const simulatorMobileStore = toRefs(useSimulatorMobileStore())
if (layoutModeGet()) {
toggleLayoutMode()
}
if (verilogModeGet()) {
verilogModeSet(false)
+ simulatorMobileStore.isVerilog.value = false
}
name = name || 'Untitled-Circuit'
name = stripTags(name)
@@ -231,46 +243,26 @@ export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) {
// $('.circuits').removeClass('current')
circuit_list.value.forEach((circuit) => (circuit.focussed = false))
circuit_list.value[circuit_list.value.length - 1].focussed = true
- activeCircuit.value.id = scope.id
- activeCircuit.value.name = scope.name
+ if (activeCircuit.value) {
+ activeCircuit.value.id = scope.id
+ activeCircuit.value.name = scope.name
+ }
if (!isVerilog || isVerilogMain) {
- if (embed) {
- // added calss - embed-tab using vue logic
- // var html = `
${truncateString(
- // name,
- // 18
- // )}
`
- // $('#tabsBar').append(html)
- // $('#tabsBar').addClass('embed-tabs')
- } else {
- // logic implemented in vue
- }
-
+ circuit_name_clickable.value = false;
// Remove listeners
- //$('.circuits').off('click')
- $('.circuitName').off('click')
- //$('.tabsCloseButton').off('click')
-
+ // $('.circuitName').off('click')
// switch circuit function moved inside vue component
-
if (!embed) {
- $('.circuitName').on('click', () => {
- simulationArea.lastSelected = globalScope.root
- setTimeout(() => {
- // here link with the properties panel
- document.getElementById('circname').select()
- }, 100)
- })
+ // $('.circuitName').on('click', () => {
+ // simulationArea.lastSelected = globalScope.root
+ // setTimeout(() => {
+ // // here link with the properties panel
+ // document.getElementById('circname').select()
+ // }, 100)
+ // })
+ circuit_name_clickable.value = true;
}
- // moved inside vue - component
- // $('.tabsCloseButton').on('click', function (e) {
- // e.stopPropagation()
- // deleteCurrentCircuit(this.id)
- // })
-
if (!embed) {
showProperties(scope.root)
}
@@ -281,20 +273,15 @@ export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) {
/**
* Used to change name of a circuit
- * @param {string} name - new name
- * @param {string} id - id of the circuit
- * @category circuit
*/
-export function changeCircuitName(name, id = globalScope.id) {
+export function changeCircuitName(name: string, id = globalScope.id) {
const simulatorStore = SimulatorStore()
const { circuit_list } = toRefs(simulatorStore)
- // const { activeCircuit } = toRefs(simulatorStore)
name = name || 'Untitled'
name = stripTags(name)
scopeList[id].name = name
const index = circuit_list.value.findIndex((circuit) => circuit.id === id)
circuit_list.value[index].name = name
- // activeCircuit.value.name = name // add later if necessary at current stage not important handled by projectProperty on switching circuit
}
/**
@@ -305,6 +292,30 @@ export function changeCircuitName(name, id = globalScope.id) {
* @category circuit
*/
export default class Scope {
+ restrictedCircuitElementsUsed: any[];
+ id: number | string;
+ CircuitElement: any[];
+ name: string;
+ root: CircuitElement;
+ backups: string[];
+ history: string[];
+ timeStamp: number;
+ verilogMetadata: { isVerilogCircuit: boolean; isMainCircuit: boolean; code: string; subCircuitScopeIds: string[]; };
+ ox: number;
+ oy: number;
+ scale: number;
+ stack: any[];
+ layout: { width: number; height: number; title_x: number; title_y: number; titleEnabled: boolean; };
+ tunnelList?: {};
+ pending?: any[];
+ nodes?: any[];
+ allNodes?: any[];
+ wires?: any[];
+ Input?: any[];
+ Output?: any[];
+ Splitter?: any[];
+ SubCircuit?: any[];
+ Clock?: any[];
constructor(name = 'localScope', id = undefined) {
this.restrictedCircuitElementsUsed = []
this.id = id || Math.floor(Math.random() * 100000000000 + 1)
@@ -364,14 +375,20 @@ export default class Scope {
* Resets all nodes recursively
*/
reset() {
- for (let i = 0; i < this.allNodes.length; i++) {
- this.allNodes[i].reset()
+ if (this.allNodes) {
+ for (let i = 0; i < this.allNodes.length; i++) {
+ this.allNodes[i].reset()
+ }
}
- for (let i = 0; i < this.Splitter.length; i++) {
- this.Splitter[i].reset()
+ if (this.Splitter) {
+ for (let i = 0; i < this.Splitter.length; i++) {
+ this.Splitter[i].reset()
+ }
}
- for (let i = 0; i < this.SubCircuit.length; i++) {
- this.SubCircuit[i].reset()
+ if (this.SubCircuit) {
+ for (let i = 0; i < this.SubCircuit.length; i++) {
+ this.SubCircuit[i].reset()
+ }
}
}
@@ -381,12 +398,14 @@ export default class Scope {
addInputs() {
for (let i = 0; i < inputList.length; i++) {
for (var j = 0; j < this[inputList[i]].length; j++) {
- simulationArea.simulationQueue.add(this[inputList[i]][j], 0)
+ simulationArea.simulationQueue?.add(this[inputList[i]][j], 0)
}
}
- for (let i = 0; i < this.SubCircuit.length; i++) {
- this.SubCircuit[i].addInputs()
+ if (this.SubCircuit) {
+ for (let i = 0; i < this.SubCircuit.length; i++) {
+ this.SubCircuit[i].addInputs()
+ }
}
}
@@ -394,27 +413,34 @@ export default class Scope {
* Ticks clocks recursively -- needs to be deprecated and synchronize all clocks with a global clock
*/
clockTick() {
- for (let i = 0; i < this.Clock.length; i++) {
- this.Clock[i].toggleState()
- } // tick clock!
- for (let i = 0; i < this.SubCircuit.length; i++) {
- this.SubCircuit[i].localScope.clockTick()
- } // tick clock!
+ if (this.Clock) {
+ for (let i = 0; i < this.Clock.length; i++) {
+ this.Clock[i].toggleState()
+ } // tick clock!
+ }
+ if (this.SubCircuit) {
+ for (let i = 0; i < this.SubCircuit.length; i++) {
+ this.SubCircuit[i].localScope.clockTick()
+ } // tick clock!
+ }
}
/**
* Checks if this circuit contains directly or indirectly scope with id
* Recursive nature
*/
- checkDependency(id) {
+ checkDependency(id: number) {
if (id === this.id) return true
- for (let i = 0; i < this.SubCircuit.length; i++) {
- if (this.SubCircuit[i].id === id) return true
+ if (this.SubCircuit) {
+ for (let i = 0; i < this.SubCircuit.length; i++) {
+ if (this.SubCircuit[i].id === id) return true
+ }
}
-
- for (let i = 0; i < this.SubCircuit.length; i++) {
- if (scopeList[this.SubCircuit[i].id].checkDependency(id))
- return true
+ if (this.SubCircuit) {
+ for (let i = 0; i < this.SubCircuit.length; i++) {
+ if (scopeList[this.SubCircuit[i].id].checkDependency(id))
+ return true
+ }
}
return false
@@ -425,9 +451,11 @@ export default class Scope {
*/
getDependencies() {
var list = []
- for (let i = 0; i < this.SubCircuit.length; i++) {
- list.push(this.SubCircuit[i].id)
- list.extend(scopeList[this.SubCircuit[i].id].getDependencies())
+ if (this.SubCircuit) {
+ for (let i = 0; i < this.SubCircuit.length; i++) {
+ list.push(this.SubCircuit[i].id)
+ list.push(...scopeList[this.SubCircuit[i].id].getDependencies())
+ }
}
return uniq(list)
}
@@ -437,11 +465,15 @@ export default class Scope {
*/
fixLayout() {
var maxY = 20
- for (let i = 0; i < this.Input.length; i++) {
- maxY = Math.max(this.Input[i].layoutProperties.y, maxY)
+ if (this.Input) {
+ for (let i = 0; i < this.Input.length; i++) {
+ maxY = Math.max(this.Input[i].layoutProperties.y, maxY)
+ }
}
- for (let i = 0; i < this.Output.length; i++) {
- maxY = Math.max(this.Output[i].layoutProperties.y, maxY)
+ if (this.Output) {
+ for (let i = 0; i < this.Output.length; i++) {
+ maxY = Math.max(this.Output[i].layoutProperties.y, maxY)
+ }
}
if (maxY !== this.layout.height) {
this.layout.height = maxY + 10
diff --git a/v1/src/simulator/src/circuitElement.js b/v1/src/simulator/src/circuitElement.js
index cd368c4d..a7d5565e 100644
--- a/v1/src/simulator/src/circuitElement.js
+++ b/v1/src/simulator/src/circuitElement.js
@@ -1,7 +1,8 @@
/* eslint-disable no-multi-assign */
/* eslint-disable no-bitwise */
+/* eslint-disable */
import { scheduleUpdate } from './engine'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import {
fixDirection,
fillText,
@@ -154,7 +155,7 @@ export default class CircuitElement {
/**
* To generate JSON-safe data that can be loaded
* @memberof CircuitElement
- * @return {JSON} - the data to be saved
+ * @return {object} - the data to be saved
*/
saveObject() {
var data = {
@@ -176,7 +177,7 @@ export default class CircuitElement {
/**
* Always overriden
* @memberof CircuitElement
- * @return {JSON} - the data to be saved
+ * @return {object} - the data to be saved
*/
// eslint-disable-next-line class-methods-use-this
customSave() {
@@ -332,7 +333,7 @@ export default class CircuitElement {
this.drag()
if (
!simulationArea.shiftDown &&
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
for (
let i = 0;
@@ -348,7 +349,7 @@ export default class CircuitElement {
this.startDragging()
if (
!simulationArea.shiftDown &&
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
for (
let i = 0;
@@ -376,9 +377,9 @@ export default class CircuitElement {
if (simulationArea.shiftDown) {
simulationArea.lastSelected = undefined
if (
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
- simulationArea.multipleObjectSelections.clean(this)
+ simulationArea.multipleObjectSelections = simulationArea.multipleObjectSelections.filter(x => x !== this);
} else {
simulationArea.multipleObjectSelections.push(this)
}
@@ -479,8 +480,8 @@ export default class CircuitElement {
* NOT OVERRIDABLE
*/
isHover() {
- var mX = simulationArea.mouseXf - this.x
- var mY = this.y - simulationArea.mouseYf
+ var mX = simulationArea.touch ? simulationArea.mouseDownX - this.x : simulationArea.mouseXf - this.x;
+ var mY = simulationArea.touch ? this.y - simulationArea.mouseDownY : this.y - simulationArea.mouseYf;
var rX = this.rightDimensionX
var lX = this.leftDimensionX
@@ -578,7 +579,7 @@ export default class CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -646,7 +647,7 @@ export default class CircuitElement {
/**
Draws element in layout mode (inside the subcircuit)
@param {number} xOffset - x position of the subcircuit
- @param {number} yOffset - y position of the subcircuit
+ @param {number} yOffset - y position of the subcircuit
Called by subcirucit.js/customDraw() - for drawing as a part of another circuit
and layoutMode.js/renderLayout() - for drawing in layoutMode
@@ -734,7 +735,7 @@ export default class CircuitElement {
// OVERRIDE WITH CAUTION
delete() {
simulationArea.lastSelected = undefined
- this.scope[this.objectType].clean(this) // CHECK IF THIS IS VALID
+ this.scope[this.objectType] = this.scope[this.objectType].filter(x => x !== this)
if (this.deleteNodesWhenDeleted) {
this.deleteNodes()
} else {
@@ -852,7 +853,8 @@ export default class CircuitElement {
resolve() {}
/**
- * Helper Function to process verilog
+ * Helper Function to process Verilog
+ * @return {string}
*/
processVerilog() {
// Output count used to sanitize output
@@ -882,7 +884,7 @@ export default class CircuitElement {
if (
!this.scope.verilogWireList[
this.nodeList[i].bitWidth
- ].contains(this.nodeList[i].verilogLabel)
+ ].includes(this.nodeList[i].verilogLabel)
)
this.scope.verilogWireList[
this.nodeList[i].bitWidth
@@ -956,8 +958,8 @@ export default class CircuitElement {
}
/**
- * Helper Function to generate verilog
- * @return {JSON}
+ * Helper Function to generate Verilog.
+ * @return {string}
*/
generateVerilog() {
// Example: and and_1(_out, _out, _Q[0]);
diff --git a/v1/src/simulator/src/combinationalAnalysis.js b/v1/src/simulator/src/combinationalAnalysis.js
index e45cb1b8..7577dcc0 100644
--- a/v1/src/simulator/src/combinationalAnalysis.js
+++ b/v1/src/simulator/src/combinationalAnalysis.js
@@ -1,667 +1,333 @@
/* eslint-disable import/no-cycle */
/* eslint-disable guard-for-in */
/* eslint-disable no-restricted-syntax */
-import Node from './node'
-import { scheduleBackup } from './data/backupCircuit'
-import BooleanMinimize from './quinMcCluskey'
-import Input from './modules/Input'
-import ConstantVal from './modules/ConstantVal'
-import Output from './modules/Output'
-import AndGate from './modules/AndGate'
-import OrGate from './modules/OrGate'
-import NotGate from './modules/NotGate'
-import { stripTags } from './utils'
-import simulationArea from './simulationArea'
-import { findDimensions } from './canvasApi'
+import Node from './node';
+import { scheduleBackup } from './data/backupCircuit';
+import BooleanMinimize from './quinMcCluskey';
+import Input from './modules/Input';
+import ConstantVal from './modules/ConstantVal';
+import Output from './modules/Output';
+import AndGate from './modules/AndGate';
+import OrGate from './modules/OrGate';
+import NotGate from './modules/NotGate';
+import { stripTags } from './utils';
+import { simulationArea } from './simulationArea';
+import { findDimensions } from './canvasApi';
import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
-// var inputSample = 5
-// var dataSample = [
-// ['01---', '11110', '01---', '00000'],
-// ['01110', '1-1-1', '----0'],
-// ['01---', '11110', '01110', '1-1-1', '0---0'],
-// ['----1'],
-// ]
+export const performCombinationalAnalysis = (inputNameList, outputNameList, booleanNameExpression, scope = globalScope) => {
+ if(!inputNameList || !outputNameList || !booleanNameExpression) {
+ return;
+ }
+ var flag = 0;
+ var inputList = stripTags(inputNameList).split(',');
+ var outputList = stripTags(outputNameList).split(',');
+ var booleanExpression = booleanNameExpression;
+ inputList = inputList.map((x) => x.trim());
+ inputList = inputList.filter((e) => e);
+ outputList = outputList.map((x) => x.trim());
+ outputList = outputList.filter((e) => e);
+ booleanExpression = booleanExpression.replace(/ /g, '');
+ booleanExpression = booleanExpression.toUpperCase();
-// var sampleInputListNames = ['A', 'B']
-// var sampleOutputListNames = ['X']
+ var booleanInputVariables = [];
+ for (var i = 0; i < booleanExpression.length; i++) {
+ if ((booleanExpression[i] >= 'A' && booleanExpression[i] <= 'Z')) {
+ if (booleanExpression.indexOf(booleanExpression[i]) == i) {
+ booleanInputVariables.push(booleanExpression[i]);
+ }
+ }
+ }
+ booleanInputVariables.sort();
+ if (inputList.length > 0 && outputList.length > 0 && booleanInputVariables.length == 0) {
+ createBooleanPrompt(inputList, outputList, null, scope);
+ }
+ else if (booleanInputVariables.length > 0 && inputList.length == 0 && outputList.length == 0) {
+ var output = solveBooleanFunction(booleanInputVariables, booleanExpression);
+ if(output != null) {
+ createBooleanPrompt(booleanInputVariables, booleanExpression, output, scope);
+ }
+ }
+ else if ((inputList.length == 0 || outputList.length == 0) && booleanInputVariables == 0) {
+ alert('Enter Input / Output Variable(s) OR Boolean Function!');
+ }
+ else {
+ alert('Use Either Combinational Analysis Or Boolean Function To Generate Circuit!');
+ }
+};
-/**
- * The prompt for combinational analysis
- * @param {Scope=} - the circuit in which we want combinational analysis
- * @category combinationalAnalysis
- */
-export function createCombinationalAnalysisPrompt(scope = globalScope) {
- scheduleBackup()
- SimulatorStore().dialogBox.combinationalanalysis_dialog = true
- /*
- $('#combinationalAnalysis').empty()
- $('#combinationalAnalysis').append(
- "
Enter Input names separated by commas:
"
- )
- $('#combinationalAnalysis').append(
- "
Enter Output names separated by commas:
"
- )
- $('#combinationalAnalysis').append("
OR
")
- $('#combinationalAnalysis').append(
- "
Enter Boolean Function:
"
- )
- $('#combinationalAnalysis').append(
- "
"
- )
- $('#combinationalAnalysis').dialog({
- resizable: false,
- width: 'auto',
- buttons: [
- {
- style: 'padding: 5px',
- text: 'Next',
- click() {
- var inputList = stripTags($('#inputNameList').val()).split(
- ','
- )
- var outputList = stripTags(
- $('#outputNameList').val()
- ).split(',')
- var booleanExpression = $('#booleanExpression').val()
- inputList = inputList.map((x) => x.trim())
- inputList = inputList.filter((e) => e)
- outputList = outputList.map((x) => x.trim())
- outputList = outputList.filter((e) => e)
- booleanExpression = booleanExpression.replace(/ /g, '')
- booleanExpression = booleanExpression.toUpperCase()
- var booleanInputVariables = []
- for (var i = 0; i < booleanExpression.length; i++) {
- if (
- booleanExpression[i] >= 'A' &&
- booleanExpression[i] <= 'Z'
- ) {
- if (
- booleanExpression.indexOf(
- booleanExpression[i]
- ) == i
- ) {
- booleanInputVariables.push(booleanExpression[i])
- }
- }
- }
- booleanInputVariables.sort()
- if (
- inputList.length > 0 &&
- outputList.length > 0 &&
- booleanInputVariables.length == 0
- ) {
- $(this).dialog('close')
- createBooleanPrompt(inputList, outputList, null, scope)
- } else if (
- booleanInputVariables.length > 0 &&
- inputList.length == 0 &&
- outputList.length == 0
- ) {
- $(this).dialog('close')
- var output = solveBooleanFunction(
- booleanInputVariables,
- booleanExpression
- )
- if (output != null) {
- createBooleanPrompt(
- booleanInputVariables,
- booleanExpression,
- output,
- scope
- )
- }
- } else if (
- (inputList.length == 0 || outputList.length == 0) &&
- booleanInputVariables == 0
- ) {
- alert(
- 'Enter Input / Output Variable(s) OR Boolean Function!'
- )
- } else {
- alert(
- 'Use Either Combinational Analysis Or Boolean Function To Generate Circuit!'
- )
- }
- },
- },
- ],
- })
-
- $('#combinationalAnalysis').checkBo()
- */
-}
-// /**
-// * This funciton hashes the output array and makes required JSON using
-// * a BooleanMinimize class defined in Quin_Mcluskey.js var s which will
-// * be output table is also initialied here
-// * @param {Array} inputListNames - labels of input nodes
-// * @param {Array} outputListNames - labels of output nodes
-// * @param {Scope=} scope - h circuit
-// * @category combinationalAnalysis
-// */
-/*
- function createBooleanPrompt(
- inputListNames,
- outputListNames,
- output,
- scope = globalScope
- ) {
- var inputListNames =
- inputListNames || prompt('Enter inputs separated by commas').split(',')
- var outputListNames =
- outputListNames ||
- prompt('Enter outputs separated by commas').split(',')
- var outputListNamesInteger = []
- if (output == null) {
- for (var i = 0; i < outputListNames.length; i++) {
- outputListNamesInteger[i] = 7 * i + 13
- } // assigning an integer to the value, 7*i + 13 is random
- } else {
- outputListNamesInteger = [13]
- }
- var s = '
'
- s += ''
- s += ''
- if ($('#decimalColumnBox').is(':checked')) {
- s += '' + 'dec' + ' | '
- }
- for (var i = 0; i < inputListNames.length; i++) {
- s += `${inputListNames[i]} | `
- }
- if (output == null) {
- for (var i = 0; i < outputListNames.length; i++) {
- s += `${outputListNames[i]} | `
- }
- } else {
- s += `${outputListNames} | `
- }
- s += '
'
-
- var matrix = []
- for (var i = 0; i < inputListNames.length; i++) {
- matrix[i] = new Array(1 << inputListNames.length)
- }
-
- for (var i = 0; i < inputListNames.length; i++) {
- for (var j = 0; j < 1 << inputListNames.length; j++) {
- matrix[i][j] = +((j & (1 << (inputListNames.length - i - 1))) != 0)
- }
- }
-
- for (var j = 0; j < 1 << inputListNames.length; j++) {
- s += ''
- if ($('#decimalColumnBox').is(':checked')) {
- s += `${j} | `
- }
- for (var i = 0; i < inputListNames.length; i++) {
- s += `${matrix[i][j]} | `
- }
- for (var i = 0; i < outputListNamesInteger.length; i++) {
- if (output == null) {
- s +=
- `` +
- 'x' +
- ' | '
- // using hash values as they'll be used in the generateBooleanTableData function
- }
- }
- if (output != null) {
- s +=
- `` +
- `${output[j]}` +
- ' | '
- }
- s += '
'
- }
- s += ''
- s += '
'
- $('#combinationalAnalysis').empty()
- $('#combinationalAnalysis').append(s)
- $('#combinationalAnalysis').dialog({
- resizable: false,
- width: 'auto',
- buttons: [
- {
- style: 'padding: 6px',
- text: 'Generate Circuit',
- click() {
- $(this).dialog('close')
- var data = generateBooleanTableData(outputListNamesInteger)
- // passing the hash values to avoid spaces being passed which is causing a problem
- var minimizedCircuit = []
- let inputCount = inputListNames.length
- for (const output in data) {
- let oneCount = data[output][1].length // Number of ones
- let zeroCount = data[output][0].length // Number of zeroes
- if (oneCount == 0) {
- // Hardcode to 0 as output
- minimizedCircuit.push([
- '-'.repeat(inputCount) + '0',
- ])
- } else if (zeroCount == 0) {
- // Hardcode to 1 as output
- minimizedCircuit.push([
- '-'.repeat(inputCount) + '1',
- ])
- } else {
- // Perform KMap like minimzation
- const temp = new BooleanMinimize(
- inputListNames.length,
- data[output][1].map(Number),
- data[output].x.map(Number)
- )
- minimizedCircuit.push(temp.result)
- }
- }
- if (output == null) {
- drawCombinationalAnalysis(
- minimizedCircuit,
- inputListNames,
- outputListNames,
- scope
- )
- } else {
- drawCombinationalAnalysis(
- minimizedCircuit,
- inputListNames,
- [`${outputListNames}`],
- scope
- )
- }
- },
- },
- {
- style: 'padding: 6px',
- text: 'Print Truth Table',
- click() {
- var sTable = document.getElementById(
- 'combinationalAnalysis'
- ).innerHTML
- var style =
- ''
- var win = window.open('', '', 'height=700,width=700')
- var htmlBody = `
- \
-
Boolean Logic Table\
- ${style}\
- \
- \
-
${sTable}\
-
- `
- win.document.write(htmlBody)
- win.document.close()
- win.print()
- },
- },
- ],
- })
-
- $('.output').on('click', function () {
- var v = $(this).html()
- if (v == 0) v = $(this).html(1)
- else if (v == 1) v = $(this).html('x')
- else if (v == 'x') v = $(this).html(0)
- })
- }
-*/
-
-// function generateBooleanTableData(outputListNames) {
-// var data = {}
-// for (var i = 0; i < outputListNames.length; i++) {
-// data[outputListNames[i]] = {
-// x: [],
-// 1: [],
-// 0: [],
-// }
-// var rows = $(`.${outputListNames[i]}`)
-// for (let j = 0; j < rows.length; j++) {
-// data[outputListNames[i]][rows[j].innerHTML].push(rows[j].id)
-// }
-// }
-// return data
-// }
-
-// function drawCombinationalAnalysis(
-// combinationalData,
-// inputList,
-// outputListNames,
-// scope = globalScope
-// ) {
-// findDimensions(scope)
-// var inputCount = inputList.length
-// var maxTerms = 0
-// for (var i = 0; i < combinationalData.length; i++) {
-// maxTerms = Math.max(maxTerms, combinationalData[i].length)
-// }
+export const GenerateCircuit = (outputListNamesInteger, inputListNames, output, outputListNames, scope = globalScope) => {
+ var data = generateBooleanTableData(outputListNamesInteger);
+ // passing the hash values to avoid spaces being passed which is causing a problem
+ var minimizedCircuit = [];
+ let inputCount = inputListNames.length;
+ for (const output in data) {
+ let oneCount = data[output][1].length; // Number of ones
+ let zeroCount = data[output][0].length; // Number of zeroes
+ if(oneCount == 0) {
+ // Hardcode to 0 as output
+ minimizedCircuit.push(['-'.repeat(inputCount) + '0']);
+ }
+ else if(zeroCount == 0) {
+ // Hardcode to 1 as output
+ minimizedCircuit.push(['-'.repeat(inputCount) + '1']);
+ }
+ else {
+ // Perform KMap like minimzation
+ const temp = new BooleanMinimize(
+ inputListNames.length,
+ data[output][1].map(Number),
+ data[output].x.map(Number),
+ );
+ minimizedCircuit.push(temp.result);
+ }
+ }
+ if (output == null) {
+ drawCombinationalAnalysis(minimizedCircuit, inputListNames, outputListNames, scope);
+ }
+ else {
+ drawCombinationalAnalysis(minimizedCircuit, inputListNames, [`${outputListNames}`], scope);
+ }
+};
-// var startPosX = 200
-// var startPosY = 200
-
-// var currentPosY = 300
-
-// if (simulationArea.maxWidth && simulationArea.maxHeight) {
-// if (simulationArea.maxHeight + currentPosY > simulationArea.maxWidth) {
-// startPosX += simulationArea.maxWidth
-// } else {
-// startPosY += simulationArea.maxHeight
-// currentPosY += simulationArea.maxHeight
-// }
-// }
-// var andPosX = startPosX + inputCount * 40 + 40 + 40
-// var orPosX = andPosX + Math.floor(maxTerms / 2) * 10 + 80
-// var outputPosX = orPosX + 60
-// var inputObjects = []
+function generateBooleanTableData(outputListNames) {
+ var data = {};
+ for (var i = 0; i < outputListNames.length; i++) {
+ data[outputListNames[i]] = {
+ x: [],
+ 1: [],
+ 0: [],
+ };
+ var rows = $(`.${outputListNames[i]}`);
+ for (let j = 0; j < rows.length; j++) {
+ data[outputListNames[i]][rows[j].innerHTML].push(rows[j].id);
+ }
+ }
+ return data;
+}
-// var logixNodes = []
+function drawCombinationalAnalysis(combinationalData, inputList, outputListNames, scope = globalScope) {
+ findDimensions(scope);
+ var inputCount = inputList.length;
+ var maxTerms = 0;
+ for (var i = 0; i < combinationalData.length; i++) { maxTerms = Math.max(maxTerms, combinationalData[i].length); }
-// // Appending constant input to the end of inputObjects
-// for (var i = 0; i <= inputCount; i++) {
-// if (i < inputCount) {
-// // Regular Input
-// inputObjects.push(
-// new Input(startPosX + i * 40, startPosY, scope, 'DOWN', 1)
-// )
-// inputObjects[i].setLabel(inputList[i])
-// } else {
-// // Constant Input
-// inputObjects.push(
-// new ConstantVal(
-// startPosX + i * 40,
-// startPosY,
-// scope,
-// 'DOWN',
-// 1,
-// '1'
-// )
-// )
-// inputObjects[i].setLabel('_C_')
-// }
+ var startPosX = 200;
+ var startPosY = 200;
-// inputObjects[i].newLabelDirection('UP')
-// var v1 = new Node(startPosX + i * 40, startPosY + 20, 2, scope.root)
-// inputObjects[i].output1.connect(v1)
-// var v2 = new Node(
-// startPosX + i * 40 + 20,
-// startPosY + 20,
-// 2,
-// scope.root
-// )
-// v1.connect(v2)
-// var notG = new NotGate(
-// startPosX + i * 40 + 20,
-// startPosY + 40,
-// scope,
-// 'DOWN',
-// 1
-// )
-// notG.inp1.connect(v2)
-// logixNodes.push(v1)
-// logixNodes.push(notG.output1)
-// }
+ var currentPosY = 300;
-// function countTerm(s) {
-// var c = 0
-// for (var i = 0; i < s.length; i++) {
-// if (s[i] !== '-') c++
-// }
-// return c
-// }
+ if (simulationArea.maxWidth && simulationArea.maxHeight) {
+ if (simulationArea.maxHeight + currentPosY > simulationArea.maxWidth) {
+ startPosX += simulationArea.maxWidth;
+ } else {
+ startPosY += simulationArea.maxHeight;
+ currentPosY += simulationArea.maxHeight;
+ }
+ }
+ var andPosX = startPosX + inputCount * 40 + 40 + 40;
+ var orPosX = andPosX + Math.floor(maxTerms / 2) * 10 + 80;
+ var outputPosX = orPosX + 60;
+ var inputObjects = [];
-// for (var i = 0; i < combinationalData.length; i++) {
-// var andGateNodes = []
-// for (var j = 0; j < combinationalData[i].length; j++) {
-// var c = countTerm(combinationalData[i][j])
-// if (c > 1) {
-// var andGate = new AndGate(
-// andPosX,
-// currentPosY,
-// scope,
-// 'RIGHT',
-// c,
-// 1
-// )
-// andGateNodes.push(andGate.output1)
-// var misses = 0
-// for (var k = 0; k < combinationalData[i][j].length; k++) {
-// if (combinationalData[i][j][k] == '-') {
-// misses++
-// continue
-// }
-// var index = 2 * k + (combinationalData[i][j][k] == 0)
-// var v = new Node(
-// logixNodes[index].absX(),
-// andGate.inp[k - misses].absY(),
-// 2,
-// scope.root
-// )
-// logixNodes[index].connect(v)
-// logixNodes[index] = v
-// v.connect(andGate.inp[k - misses])
-// }
-// } else {
-// for (var k = 0; k < combinationalData[i][j].length; k++) {
-// if (combinationalData[i][j][k] == '-') continue
-// var index = 2 * k + (combinationalData[i][j][k] == 0)
-// var andGateSubstituteNode = new Node(
-// andPosX,
-// currentPosY,
-// 2,
-// scope.root
-// )
-// var v = new Node(
-// logixNodes[index].absX(),
-// andGateSubstituteNode.absY(),
-// 2,
-// scope.root
-// )
-// logixNodes[index].connect(v)
-// logixNodes[index] = v
-// v.connect(andGateSubstituteNode)
-// andGateNodes.push(andGateSubstituteNode)
-// }
-// }
-// currentPosY += c * 10 + 30
-// }
+ var logixNodes = [];
-// var andGateCount = andGateNodes.length
-// var midWay = Math.floor(andGateCount / 2)
-// var orGatePosY =
-// (andGateNodes[midWay].absY() +
-// andGateNodes[Math.floor((andGateCount - 1) / 2)].absY()) /
-// 2
-// if (orGatePosY % 10 == 5) {
-// orGatePosY += 5
-// } // To make or gate fall in grid
-// if (andGateCount > 1) {
-// var o = new OrGate(
-// orPosX,
-// orGatePosY,
-// scope,
-// 'RIGHT',
-// andGateCount,
-// 1
-// )
-// if (andGateCount % 2 == 1)
-// andGateNodes[midWay].connect(o.inp[midWay])
-// for (var j = 0; j < midWay; j++) {
-// var v = new Node(
-// andPosX + 30 + (midWay - j) * 10,
-// andGateNodes[j].absY(),
-// 2,
-// scope.root
-// )
-// v.connect(andGateNodes[j])
-// var v2 = new Node(
-// andPosX + 30 + (midWay - j) * 10,
-// o.inp[j].absY(),
-// 2,
-// scope.root
-// )
-// v2.connect(v)
-// o.inp[j].connect(v2)
+ // Appending constant input to the end of inputObjects
+ for (var i = 0; i <= inputCount; i++) {
+ if(i < inputCount) {
+ // Regular Input
+ inputObjects.push(new Input(startPosX + i * 40, startPosY, scope, 'DOWN', 1));
+ inputObjects[i].setLabel(inputList[i]);
+ }
+ else {
+ // Constant Input
+ inputObjects.push(new ConstantVal(startPosX + i * 40, startPosY, scope, 'DOWN', 1, '1'));
+ inputObjects[i].setLabel('_C_');
+ }
-// var v = new Node(
-// andPosX + 30 + (midWay - j) * 10,
-// andGateNodes[andGateCount - j - 1].absY(),
-// 2,
-// scope.root
-// )
-// v.connect(andGateNodes[andGateCount - j - 1])
-// var v2 = new Node(
-// andPosX + 30 + (midWay - j) * 10,
-// o.inp[andGateCount - j - 1].absY(),
-// 2,
-// scope.root
-// )
-// v2.connect(v)
-// o.inp[andGateCount - j - 1].connect(v2)
-// }
-// var out = new Output(outputPosX, o.y, scope, 'LEFT', 1)
-// out.inp1.connect(o.output1)
-// } else {
-// var out = new Output(
-// outputPosX,
-// andGateNodes[0].absY(),
-// scope,
-// 'LEFT',
-// 1
-// )
-// out.inp1.connect(andGateNodes[0])
-// }
-// out.setLabel(outputListNames[i])
-// out.newLabelDirection('RIGHT')
-// }
-// for (var i = 0; i < logixNodes.length; i++) {
-// if (logixNodes[i].absY() != currentPosY) {
-// var v = new Node(logixNodes[i].absX(), currentPosY, 2, scope.root)
-// logixNodes[i].connect(v)
-// }
-// }
-// globalScope.centerFocus()
-// }
+ inputObjects[i].newLabelDirection('UP');
+ var v1 = new Node(startPosX + i * 40, startPosY + 20, 2, scope.root);
+ inputObjects[i].output1.connect(v1);
+ var v2 = new Node(startPosX + i * 40 + 20, startPosY + 20, 2, scope.root);
+ v1.connect(v2);
+ var notG = new NotGate(startPosX + i * 40 + 20, startPosY + 40, scope, 'DOWN', 1);
+ notG.inp1.connect(v2);
+ logixNodes.push(v1);
+ logixNodes.push(notG.output1);
+ }
-// /**
-// * This function solves passed boolean expression and returns
-// * output array which contains solution of the truth table
-// * of given boolean expression
-// * @param {Array} inputListNames - labels for input nodes
-// * @param {String} booleanExpression - boolean expression which is to be solved
-// */
-// function solveBooleanFunction(inputListNames, booleanExpression) {
-// let i
-// let j
-// let output = []
+ function countTerm(s) {
+ var c = 0;
+ for (var i = 0; i < s.length; i++) { if (s[i] !== '-')c++; }
+ return c;
+ }
-// if (
-// booleanExpression.match(
-// /[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01+'() ]/g
-// ) != null
-// ) {
-// alert('One of the characters is not allowed.')
-// return
-// }
+ for (var i = 0; i < combinationalData.length; i++) {
+ var andGateNodes = [];
+ for (var j = 0; j < combinationalData[i].length; j++) {
+ var c = countTerm(combinationalData[i][j]);
+ if (c > 1) {
+ var andGate = new AndGate(andPosX, currentPosY, scope, 'RIGHT', c, 1);
+ andGateNodes.push(andGate.output1);
+ var misses = 0;
+ for (var k = 0; k < combinationalData[i][j].length; k++) {
+ if (combinationalData[i][j][k] == '-') { misses++; continue; }
+ var index = 2 * k + (combinationalData[i][j][k] == 0);
+ var v = new Node(logixNodes[index].absX(), andGate.inp[k - misses].absY(), 2, scope.root);
+ logixNodes[index].connect(v);
+ logixNodes[index] = v;
+ v.connect(andGate.inp[k - misses]);
+ }
+ } else {
+ for (var k = 0; k < combinationalData[i][j].length; k++) {
+ if (combinationalData[i][j][k] == '-') continue;
+ var index = 2 * k + (combinationalData[i][j][k] == 0);
+ var andGateSubstituteNode = new Node(andPosX, currentPosY, 2, scope.root);
+ var v = new Node(logixNodes[index].absX(), andGateSubstituteNode.absY(), 2, scope.root);
+ logixNodes[index].connect(v);
+ logixNodes[index] = v;
+ v.connect(andGateSubstituteNode);
+ andGateNodes.push(andGateSubstituteNode);
+ }
+ }
+ currentPosY += c * 10 + 30;
+ }
-// if (inputListNames.length > 8) {
-// alert('You can only have 8 variables at a time.')
-// return
-// }
+ var andGateCount = andGateNodes.length;
+ var midWay = Math.floor(andGateCount / 2);
+ var orGatePosY = (andGateNodes[midWay].absY() + andGateNodes[Math.floor((andGateCount - 1) / 2)].absY()) / 2;
+ if (orGatePosY % 10 == 5) { orGatePosY += 5; } // To make or gate fall in grid
+ if (andGateCount > 1) {
+ var o = new OrGate(orPosX, orGatePosY, scope, 'RIGHT', andGateCount, 1);
+ if (andGateCount % 2 == 1)andGateNodes[midWay].connect(o.inp[midWay]);
+ for (var j = 0; j < midWay; j++) {
+ var v = new Node(andPosX + 30 + (midWay - j) * 10, andGateNodes[j].absY(), 2, scope.root);
+ v.connect(andGateNodes[j]);
+ var v2 = new Node(andPosX + 30 + (midWay - j) * 10, o.inp[j].absY(), 2, scope.root);
+ v2.connect(v);
+ o.inp[j].connect(v2);
-// var s = '
'
-// s += ''
-// s += ''
-// if ($('#decimalColumnBox').is(':checked')) {
-// s += '' + 'dec' + ' | '
-// }
-// for (i = 0; i < inputListNames.length; i++) {
-// s += `${inputListNames[i]} | `
-// }
-// s += `${booleanExpression} | `
-// s += '
'
-// var matrix = []
-// for (i = 0; i < inputListNames.length; i++) {
-// matrix[i] = new Array(inputListNames.length)
-// }
+ var v = new Node(andPosX + 30 + (midWay - j) * 10, andGateNodes[andGateCount - j - 1].absY(), 2, scope.root);
+ v.connect(andGateNodes[andGateCount - j - 1]);
+ var v2 = new Node(andPosX + 30 + (midWay - j) * 10, o.inp[andGateCount - j - 1].absY(), 2, scope.root);
+ v2.connect(v);
+ o.inp[andGateCount - j - 1].connect(v2);
+ }
+ var out = new Output(outputPosX, o.y, scope, 'LEFT', 1);
+ out.inp1.connect(o.output1);
+ } else {
+ var out = new Output(outputPosX, andGateNodes[0].absY(), scope, 'LEFT', 1);
+ out.inp1.connect(andGateNodes[0]);
+ }
+ out.setLabel(outputListNames[i]);
+ out.newLabelDirection('RIGHT');
+ }
+ for (var i = 0; i < logixNodes.length; i++) {
+ if (logixNodes[i].absY() != currentPosY) {
+ var v = new Node(logixNodes[i].absX(), currentPosY, 2, scope.root);
+ logixNodes[i].connect(v);
+ }
+ }
+ globalScope.centerFocus();
+}
-// for (i = 0; i < inputListNames.length; i++) {
-// for (j = 0; j < 1 << inputListNames.length; j++) {
-// matrix[i][j] = +((j & (1 << (inputListNames.length - i - 1))) != 0)
-// }
-// }
-// // generate equivalent expression by replacing input vars with possible combinations of o and 1
-// for (i = 0; i < 2 ** inputListNames.length; i++) {
-// const data = []
-// for (j = 0; j < inputListNames.length; j++) {
-// data[j] =
-// Math.floor(i / Math.pow(2, inputListNames.length - j - 1)) % 2
-// }
-// let equation = booleanExpression
-// for (j = 0; j < inputListNames.length; j++) {
-// equation = equation.replace(
-// new RegExp(inputListNames[j], 'g'),
-// data[j]
-// )
-// }
+/**
+ * This function solves passed boolean expression and returns
+ * output array which contains solution of the truth table
+ * of given boolean expression
+ * @param {Array} inputListNames - labels for input nodes
+ * @param {String} booleanExpression - boolean expression which is to be solved
+ */
+export function solveBooleanFunction(inputListNames, booleanExpression) {
+ let i
+ let j
+ output.value = []
-// output[i] = solve(equation)
-// }
+ if (
+ booleanExpression.match(
+ /[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01+'() ]/g
+ ) != null
+ ) {
+ // alert('One of the characters is not allowed.')
+ confirmSingleOption('One of the characters is not allowed.')
+ return
+ }
-// for (j = 0; j < 1 << inputListNames.length; j++) {
-// s += ''
-// if ($('#decimalColumnBox').is(':checked')) {
-// s += `${j} | `
-// }
-// for (i = 0; i < inputListNames.length; i++) {
-// s += `${matrix[i][j]} | `
-// }
+ if (inputListNames.length > 8) {
+ // alert('You can only have 8 variables at a time.')
+ confirmSingleOption('You can only have 8 variables at a time.')
+ return
+ }
+ var matrix = []
+ for (i = 0; i < inputListNames.length; i++) {
+ matrix[i] = new Array(inputListNames.length)
+ }
-// s += `` + `${output[j]}` + ' | '
-// s += '
'
-// }
+ for (i = 0; i < inputListNames.length; i++) {
+ for (j = 0; j < 1 << inputListNames.length; j++) {
+ matrix[i][j] = +((j & (1 << (inputListNames.length - i - 1))) != 0)
+ }
+ }
+ // generate equivalent expression by replacing input vars with possible combinations of o and 1
+ for (i = 0; i < 2 ** inputListNames.length; i++) {
+ const data = []
+ for (j = 0; j < inputListNames.length; j++) {
+ data[j] =
+ Math.floor(i / Math.pow(2, inputListNames.length - j - 1)) % 2
+ }
+ let equation = booleanExpression
+ for (j = 0; j < inputListNames.length; j++) {
+ equation = equation.replace(
+ new RegExp(inputListNames[j], 'g'),
+ data[j]
+ )
+ }
-// s += ''
-// s += '
'
-// // generates solution for the truth table of booleanexpression
-// function solve(equation) {
-// while (equation.indexOf('(') != -1) {
-// const start = equation.lastIndexOf('(')
-// const end = equation.indexOf(')', start)
-// if (start != -1) {
-// equation =
-// equation.substring(0, start) +
-// solve(equation.substring(start + 1, end)) +
-// equation.substring(end + 1)
-// }
-// }
-// equation = equation.replace(/''/g, '')
-// equation = equation.replace(/0'/g, '1')
-// equation = equation.replace(/1'/g, '0')
-// for (let i = 0; i < equation.length - 1; i++) {
-// if (
-// (equation[i] == '0' || equation[i] == '1') &&
-// (equation[i + 1] == '0' || equation[i + 1] == '1')
-// ) {
-// equation =
-// equation.substring(0, i + 1) +
-// '*' +
-// equation.substring(i + 1, equation.length)
-// }
-// }
-// try {
-// const safeEval = eval
-// const answer = safeEval(equation)
-// if (answer == 0) {
-// return 0
-// }
-// if (answer > 0) {
-// return 1
-// }
-// return ''
-// } catch (e) {
-// return ''
-// }
-// }
+ output.value[i] = solve(equation)
+ }
+ // generates solution for the truth table of booleanexpression
+ function solve(equation) {
+ while (equation.indexOf('(') != -1) {
+ const start = equation.lastIndexOf('(')
+ const end = equation.indexOf(')', start)
+ if (start != -1) {
+ equation =
+ equation.substring(0, start) +
+ solve(equation.substring(start + 1, end)) +
+ equation.substring(end + 1)
+ }
+ }
+ equation = equation.replace(/''/g, '')
+ equation = equation.replace(/0'/g, '1')
+ equation = equation.replace(/1'/g, '0')
+ for (let i = 0; i < equation.length - 1; i++) {
+ if (
+ (equation[i] == '0' || equation[i] == '1') &&
+ (equation[i + 1] == '0' || equation[i + 1] == '1')
+ ) {
+ equation =
+ equation.substring(0, i + 1) +
+ '*' +
+ equation.substring(i + 1, equation.length)
+ }
+ }
+ try {
+ const safeEval = eval
+ const answer = safeEval(equation)
+ if (answer == 0) {
+ return 0
+ }
+ if (answer > 0) {
+ return 1
+ }
+ return ''
+ } catch (e) {
+ return ''
+ }
+ }
+}
-// return output
-// }
+export function createCombinationalAnalysisPrompt(scope = globalScope) {
+ scheduleBackup()
+ SimulatorStore().dialogBox.combinationalanalysis_dialog = true
+}
diff --git a/v1/src/simulator/src/contention.ts b/v1/src/simulator/src/contention.ts
new file mode 100644
index 00000000..23c5ee24
--- /dev/null
+++ b/v1/src/simulator/src/contention.ts
@@ -0,0 +1,123 @@
+/**
+ * Represents a node with bitWidth and value properties
+ */
+interface Node {
+ bitWidth: number;
+ value: number | undefined;
+ }
+
+ /**
+ * @class ContentionPendingData
+ *
+ * Data structure to store pending contentions in the circuit.
+ */
+ export default class ContentionPendingData {
+ private contentionPendingMap: Map
>;
+ private totalContentions: number;
+
+ constructor() {
+ this.contentionPendingMap = new Map>();
+ this.totalContentions = 0;
+ }
+
+ /**
+ * Adds a contention between two nodes
+ * @param ourNode The source node
+ * @param theirNode The target node
+ */
+ add(ourNode: Node, theirNode: Node): void {
+ if (this.contentionPendingMap.has(ourNode)) {
+ const existingSet = this.contentionPendingMap.get(ourNode)!;
+ if (!existingSet.has(theirNode)) this.totalContentions++;
+ existingSet.add(theirNode);
+ return;
+ }
+
+ this.totalContentions++;
+ this.contentionPendingMap.set(ourNode, new Set([theirNode]));
+ }
+
+ /**
+ * Checks if a node has any pending contentions
+ * @param ourNode The node to check
+ * @returns Whether the node has contentions
+ */
+ has(ourNode: Node): boolean {
+ return this.contentionPendingMap.has(ourNode);
+ }
+
+ /**
+ * Removes a specific contention entry
+ * @param ourNode The source node
+ * @param theirNode The target node
+ */
+ remove(ourNode: Node, theirNode: Node): void {
+ if (!this.contentionPendingMap.has(ourNode) ||
+ !this.contentionPendingMap.get(ourNode)!.has(theirNode)) return;
+
+ this.contentionPendingMap.get(ourNode)!.delete(theirNode);
+ if (this.contentionPendingMap.get(ourNode)!.size === 0) {
+ this.contentionPendingMap.delete(ourNode);
+ }
+ this.totalContentions--;
+ }
+
+ /**
+ * Removes all contentions for a specific node
+ * @param ourNode The node to remove contentions for
+ */
+ removeAllContentionsForNode(ourNode: Node): void {
+ if (!this.contentionPendingMap.has(ourNode)) return;
+
+ const contentionsForOurNode = this.contentionPendingMap.get(ourNode)!;
+ for (const theirNode of contentionsForOurNode) {
+ this.remove(ourNode, theirNode);
+ }
+ }
+
+ /**
+ * Removes a contention if the nodes are resolved
+ * @param ourNode The source node
+ * @param theirNode The target node
+ */
+ removeIfResolved(ourNode: Node, theirNode: Node): void {
+ if (ourNode.bitWidth === theirNode.bitWidth &&
+ (ourNode.value === theirNode.value || ourNode.value === undefined)) {
+ this.remove(ourNode, theirNode);
+ }
+ }
+
+ /**
+ * Removes resolved contentions for a specific node
+ * @param ourNode The node to check for resolved contentions
+ */
+ removeIfResolvedAllContentionsForNode(ourNode: Node): void {
+ if (!this.contentionPendingMap.has(ourNode)) return;
+
+ const contentionsForOurNode = this.contentionPendingMap.get(ourNode)!;
+ for (const theirNode of contentionsForOurNode) {
+ this.removeIfResolved(ourNode, theirNode);
+ }
+ }
+
+ /**
+ * @returns Total number of contentions
+ */
+ size(): number {
+ return this.totalContentions;
+ }
+
+ /**
+ * @returns List of all contention pairs
+ */
+ nodes(): [Node, Node][] {
+ const items: [Node, Node][] = [];
+ for (const [ourNode, contentionSet] of this.contentionPendingMap) {
+ for (const theirNode of contentionSet) {
+ items.push([ourNode, theirNode]);
+ }
+ }
+
+ return items;
+ }
+ }
\ No newline at end of file
diff --git a/v1/src/simulator/src/data.js b/v1/src/simulator/src/data.js
index 4e573c21..bb9df0e7 100644
--- a/v1/src/simulator/src/data.js
+++ b/v1/src/simulator/src/data.js
@@ -10,16 +10,11 @@ import {
openOffline,
recoverProject,
} from './data/project'
-import { newCircuit, createNewCircuitScope } from './circuit'
+import { createNewCircuitScope } from './circuit'
import { createCombinationalAnalysisPrompt } from './combinationalAnalysis'
import { colorThemes } from './themer/themer'
import { showTourGuide } from './tutorials'
-import {
- createVerilogCircuit,
- // saveVerilogCode,
- // resetVerilogCode,
- // applyVerilogTheme,
-} from './Verilog2CV'
+import { createVerilogCircuit } from './Verilog2CV'
import { generateVerilog } from './verilog'
import { bitConverterDialog } from './utils'
import { keyBinder } from '#/components/DialogBox/CustomShortcut.vue'
@@ -33,7 +28,6 @@ logixFunction.createSaveAsImgPrompt = createSaveAsImgPrompt
logixFunction.clearProject = clearProject
logixFunction.newProject = newProject
logixFunction.saveOffline = saveOffline
-// logixFunction.newCircuit = newCircuit
logixFunction.createOpenLocalPrompt = openOffline
logixFunction.recoverProject = recoverProject
logixFunction.createSubCircuitPrompt = createSubCircuitPrompt
@@ -43,12 +37,9 @@ logixFunction.fullViewOption = fullView
logixFunction.colorThemes = colorThemes
logixFunction.showTourGuide = showTourGuideHelper
logixFunction.newVerilogModule = createVerilogCircuit
-// logixFunction.saveVerilogCode = saveVerilogCode
-// logixFunction.resetVerilogCode = resetVerilogCode
logixFunction.generateVerilog = generateVerilog
-// logixFunction.applyVerilogTheme = applyVerilogTheme
logixFunction.bitconverter = bitConverterDialog
-logixFunction.createNewCircuitScope = createNewCircuitScope
+logixFunction.createNewCircuitScope = createNewCircuit
logixFunction.customShortcut = keyBinder
logixFunction.ExportProject = ExportProject
logixFunction.ImportProject = ImportProject
@@ -60,3 +51,8 @@ function showTourGuideHelper() {
showTourGuide()
}, 100)
}
+
+// Hack to call createNewCircuitScope with keyboard shortcut
+function createNewCircuit() {
+ createNewCircuitScope()
+}
diff --git a/v1/src/simulator/src/data/backupCircuit.js b/v1/src/simulator/src/data/backupCircuit.js
index c17a93c3..e15f5e44 100644
--- a/v1/src/simulator/src/data/backupCircuit.js
+++ b/v1/src/simulator/src/data/backupCircuit.js
@@ -1,4 +1,6 @@
import { projectSavedSet } from './project'
+import { moduleList, updateOrder } from '../metadata'
+
/* eslint-disable no-param-reassign */
function extract(obj) {
return obj.saveObject()
diff --git a/v1/src/simulator/src/data/load.js b/v1/src/simulator/src/data/load.js
index f9d7b89b..1bc51e65 100644
--- a/v1/src/simulator/src/data/load.js
+++ b/v1/src/simulator/src/data/load.js
@@ -8,7 +8,7 @@ import {
gridUpdateSet,
} from '../engine'
import { updateRestrictedElementsInScope } from '../restrictedElementDiv'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { loadSubCircuit } from '../subcircuit'
import { scheduleBackup } from './backupCircuit'
@@ -18,9 +18,11 @@ import { generateId } from '../utils'
import modules from '../modules'
import { oppositeDirection } from '../canvasApi'
import plotArea from '../plotArea'
-import { updateTestbenchUI, TestbenchData } from '../testbench'
+import { TestbenchData } from '#/simulator/src/testbench'
import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
import { toRefs } from 'vue'
+import { moduleList } from '../metadata'
+
/**
* Backward compatibility - needs to be deprecated
* @param {CircuitElement} obj - the object to be rectified
@@ -282,9 +284,6 @@ export default function load(data) {
// Switch to last focussedCircuit
if (data.focussedCircuit) switchCircuit(String(data.focussedCircuit))
- // Update the testbench UI
- updateTestbenchUI()
-
updateSimulationSet(true)
updateCanvasSet(true)
gridUpdateSet(true)
diff --git a/v1/src/simulator/src/data/project.js b/v1/src/simulator/src/data/project.ts
similarity index 86%
rename from v1/src/simulator/src/data/project.js
rename to v1/src/simulator/src/data/project.ts
index 5a88fdd5..71d244b7 100644
--- a/v1/src/simulator/src/data/project.js
+++ b/v1/src/simulator/src/data/project.ts
@@ -17,7 +17,8 @@ import { confirmOption } from '#/components/helpers/confirmComponent/ConfirmComp
*/
export async function recoverProject() {
if (localStorage.getItem('recover')) {
- var data = JSON.parse(localStorage.getItem('recover'))
+ const recover = localStorage.getItem('recover')
+ const data = recover ? JSON.parse(recover) : {}
if (await confirmOption(`Would you like to recover: ${data.name}`)) {
load(data)
}
@@ -78,11 +79,10 @@ export function openOffline() {
}
/**
* Flag for project saved or not
- * @type {boolean}
* @category data
*/
-var projectSaved = true
-export function projectSavedSet(param) {
+let projectSaved = true
+export function projectSavedSet(param: boolean) {
projectSaved = param
}
@@ -91,10 +91,11 @@ export function projectSavedSet(param) {
* @category data
*/
export async function saveOffline() {
- const data = await generateSaveData()
+ const data = await generateSaveData('')
if (data instanceof Error) return
localStorage.setItem(projectId, data)
- const temp = JSON.parse(localStorage.getItem('projectList')) || {}
+ const projectList = localStorage.getItem('projectList')
+ const temp = projectList ? JSON.parse(projectList) : {}
temp[projectId] = getProjectName()
localStorage.setItem('projectList', JSON.stringify(temp))
showMessage(
@@ -109,8 +110,8 @@ export async function saveOffline() {
function checkToSave() {
let saveFlag = false
// eslint-disable-next-line no-restricted-syntax
- for (id in scopeList) {
- saveFlag |= checkIfBackup(scopeList[id])
+ for (const id in scopeList) {
+ saveFlag = saveFlag || checkIfBackup(scopeList[id])
}
return saveFlag
}
@@ -131,14 +132,14 @@ window.onbeforeunload = async function () {
// 'You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?'
// )
const data = await generateSaveData('Untitled')
- localStorage.setItem('recover', await data)
+ const stringData = JSON.stringify(data)
+ localStorage.setItem('recover', stringData)
// eslint-disable-next-line consistent-return
return 'Are u sure u want to leave? Any unsaved changes may not be recoverable'
}
/**
* Function to clear project
- * @category data
*/
export async function clearProject() {
if (await confirmOption('Would you like to clear the project?')) {
@@ -152,10 +153,8 @@ export async function clearProject() {
/**
Function used to start a new project while prompting confirmation from the user
- * @param {boolean} verify - flag to verify a new project
- * @category data
*/
-export async function newProject(verify) {
+export async function newProject(verify: boolean) {
if (
verify ||
projectSaved ||
@@ -166,7 +165,8 @@ export async function newProject(verify) {
) {
clearProject()
localStorage.removeItem('recover')
- window.location = '/simulator'
+ const baseUrl = window.location.origin !== 'null' ? window.location.origin : 'http://localhost:4000';
+ window.location.assign(`${baseUrl}/simulatorvue/`);
setProjectName(undefined)
projectId = generateId()
diff --git a/v1/src/simulator/src/data/redo.js b/v1/src/simulator/src/data/redo.js
deleted file mode 100644
index bc252a98..00000000
--- a/v1/src/simulator/src/data/redo.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* eslint-disable import/no-cycle */
-/**
- * Function to restore copy from backup
- * @param {Scope=} scope - The circuit on which redo is called
- * @category data
- */
-import { layoutModeGet } from '../layoutMode'
-import Scope, { scopeList } from '../circuit'
-import { loadScope } from './load'
-import { updateRestrictedElementsInScope } from '../restrictedElementDiv'
-import { forceResetNodesSet } from '../engine'
-/**
- * Function called to generate a prompt to save an image
- * @param {Scope=} - the circuit in which we want to call redo
- * @category data
- * @exports redo
- */
-export default function redo(scope = globalScope) {
- if (layoutModeGet()) return
- if (scope.history.length === 0) return
- const backupOx = globalScope.ox
- const backupOy = globalScope.oy
- const backupScale = globalScope.scale
- globalScope.ox = 0
- globalScope.oy = 0
- const tempScope = new Scope(scope.name)
- loading = true
- const redoData = scope.history.pop()
- scope.backups.push(redoData)
- loadScope(tempScope, JSON.parse(redoData))
- tempScope.backups = scope.backups
- tempScope.history = scope.history
- tempScope.id = scope.id
- tempScope.name = scope.name
- tempScope.testbenchData = scope.testbenchData
- scopeList[scope.id] = tempScope
- globalScope = tempScope
- globalScope.ox = backupOx
- globalScope.oy = backupOy
- globalScope.scale = backupScale
- loading = false
- forceResetNodesSet(true)
-
- // Updated restricted elements
- updateRestrictedElementsInScope()
-}
-// for html file
diff --git a/v1/src/simulator/src/data/redo.ts b/v1/src/simulator/src/data/redo.ts
new file mode 100644
index 00000000..67753db0
--- /dev/null
+++ b/v1/src/simulator/src/data/redo.ts
@@ -0,0 +1,76 @@
+/* eslint-disable import/no-cycle */
+import { layoutModeGet } from '../layoutMode';
+import Scope, { scopeList } from '../circuit';
+import { loadScope } from './load';
+import { updateRestrictedElementsInScope } from '../restrictedElementDiv';
+import { forceResetNodesSet } from '../engine';
+
+// Extend the Scope type to include missing properties
+interface ExtendedScope extends Scope {
+ testbenchData: any;
+ ox: number;
+ oy: number;
+ scale: number;
+ history: string[];
+ backups: string[];
+ name: string;
+ id: string | number;
+}
+
+// Type declarations for global variables
+declare var globalScope: ExtendedScope;
+declare var loading: boolean;
+
+/**
+ * Function to restore copy from backup
+ * @param {ExtendedScope=} scope - The circuit on which redo is called
+ * @category data
+ */
+export default function redo(scope: ExtendedScope = globalScope): void {
+ if (layoutModeGet()) return;
+ if (scope.history.length === 0) return;
+
+ // Store the current view state
+ const backupOx: number = globalScope.ox;
+ const backupOy: number = globalScope.oy;
+ const backupScale: number = globalScope.scale;
+
+ // Reset the view position
+ globalScope.ox = 0;
+ globalScope.oy = 0;
+
+ // Create a temporary scope
+ const tempScope: ExtendedScope = new Scope(scope.name) as ExtendedScope;
+ loading = true;
+
+ // Get the redo data and update history
+ const redoData: string = scope.history.pop()!;
+ scope.backups.push(redoData);
+
+ // Load the scope data
+ loadScope(tempScope, JSON.parse(redoData));
+
+ // Transfer persistent properties
+ tempScope.backups = scope.backups;
+ tempScope.history = scope.history;
+ tempScope.id = scope.id;
+ tempScope.name = scope.name;
+ tempScope.testbenchData = scope.testbenchData;
+
+ // Update the scope list
+ scopeList[scope.id] = tempScope;
+
+ // Update global scope
+ globalScope = tempScope;
+
+ // Restore view state
+ globalScope.ox = backupOx;
+ globalScope.oy = backupOy;
+ globalScope.scale = backupScale;
+
+ loading = false;
+ forceResetNodesSet(true);
+
+ // Update restricted elements
+ updateRestrictedElementsInScope();
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/data/save.js b/v1/src/simulator/src/data/save.js
index 4695b312..3ca13ca0 100644
--- a/v1/src/simulator/src/data/save.js
+++ b/v1/src/simulator/src/data/save.js
@@ -1,22 +1,23 @@
import { scopeList } from '../circuit'
import { resetup } from '../setup'
-import { update } from '../engine'
+import { update, updateSubcircuitSet } from '../engine'
import { stripTags, showMessage } from '../utils'
import { backUp } from './backupCircuit'
-import simulationArea from '../simulationArea'
-import backgroundArea from '../backgroundArea'
+import { simulationArea } from '../simulationArea'
+import { backgroundArea } from '../backgroundArea'
import { findDimensions } from '../canvasApi'
import { projectSavedSet } from './project'
import { colors } from '../themer/themer'
import { layoutModeGet, toggleLayoutMode } from '../layoutMode'
import { verilogModeGet } from '../Verilog2CV'
import domtoimage from 'dom-to-image'
-import '../../vendor/canvas2svg'
+import canvasToSvg from "canvas-to-svg"
import { useProjectStore } from '#/store/projectStore'
import { provideProjectName } from '#/components/helpers/promptComponent/PromptComponent.vue'
import { UpdateProjectDetail } from '#/components/helpers/createNewProject/UpdateProjectDetail.vue'
import { confirmOption } from '#/components/helpers/confirmComponent/ConfirmComponent.vue'
import { getToken } from '#/pages/simulatorHandler.vue'
+import { renderOrder } from '../metadata'
// var projectName = undefined
@@ -68,7 +69,7 @@ function downloadAsImg(name, imgType) {
export function getTabsOrder() {
var tabs = document.getElementById('tabsBar').firstChild.children
var order = []
- for (let i = 0; i < tabs.length; i++) {
+ for (let i = 0; i < tabs?.length; i++) {
order.push(tabs[i].id)
}
return order
@@ -98,9 +99,9 @@ export async function generateSaveData(name, setName = true) {
data.timePeriod = simulationArea.timePeriod
data.clockEnabled = simulationArea.clockEnabled
data.projectId = projectId
- data.simulatorVersion = "v1"
data.focussedCircuit = globalScope.id
data.orderedTabs = getTabsOrder()
+ data.simulatorVersion = "v1" // Version of the simulator, used to identify the version of the simulator that created this project
// Project Circuits, each scope is one circuit
data.scopes = []
@@ -122,6 +123,13 @@ export async function generateSaveData(name, setName = true) {
}
completed[id] = true
+
+ // This update is very important.
+ // if a scope's input/output changes and the user saves without going
+ // to circuits where this circuit is used as a subcircuit. It will
+ // break the code since the Subcircuit will have different number of
+ // in/out nodes compared to the localscope input/output objects.
+ updateSubcircuitSet(true);
update(scopeList[id], true) // For any pending integrity checks on subcircuits
data.scopes.push(backUp(scopeList[id]))
}
@@ -186,7 +194,7 @@ export function generateImage(
// If SVG, create SVG context - using canvas2svg here
if (imgType === 'svg') {
- simulationArea.context = new C2S(width, height)
+ simulationArea.context = new canvasToSvg(width, height)
resolution = 1
} else if (imgType !== 'png') {
transparent = false
@@ -237,7 +245,7 @@ export function generateImage(
simulationArea.context.fill()
}
- // Draw circuits, why is it updateOrder and not renderOrder?
+ // Draw circuits
for (let i = 0; i < renderOrder.length; i++) {
for (let j = 0; j < scope[renderOrder[i]].length; j++) {
scope[renderOrder[i]][j].draw()
@@ -309,16 +317,16 @@ async function generateImageForOnline() {
if (verilogModeGet()) {
var node = document.getElementsByClassName('CodeMirror')[0]
// var node = document.getElementsByClassName('CodeMirror')[0];
- var prevHeight = $(node).css('height')
- var prevWidth = $(node).css('width')
+ var prevHeight = window.getComputedStyle(node).height
+ var prevWidth = window.getComputedStyle(node).width
var baseWidth = 500
var baseHeight = Math.round(baseWidth / ratio)
- $(node).css('height', baseHeight)
- $(node).css('width', baseWidth)
+ node.style.height = baseHeight + 'px'
+ node.style.width = baseWidth + 'px'
var data = await domtoimage.toJpeg(node)
- $(node).css('width', prevWidth)
- $(node).css('height', prevHeight)
+ node.style.width = prevWidth
+ node.style.height = prevHeight
data = await crop(data, baseWidth, baseHeight)
return data
}
@@ -359,14 +367,16 @@ export default async function save() {
const data = await generateSaveData()
if (data instanceof Error) return
- $('.loadingIcon').fadeIn()
+ let loadingIcon = document.querySelector('.loadingIcon');
+ loadingIcon.style.transition = 'opacity 0.5s linear';
+ loadingIcon.style.opacity = '1';
const projectName = getProjectName()
var imageData = await generateImageForOnline()
const headers = {
'Content-Type': 'application/json',
- 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
+ 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'),
Authorization: `Token ${getToken('cvt')}`,
}
@@ -380,7 +390,11 @@ export default async function save() {
)
)
window.location.href = '/users/sign_in'
- else $('.loadingIcon').fadeOut()
+ else {
+ let loadingIcon = document.querySelector('.loadingIcon')
+ loadingIcon.style.transition = 'opacity 0.2s';
+ loadingIcon.style.opacity = '0';
+ }
// eslint-disable-next-line camelcase
} else if ([0, undefined, null, '', '0'].includes(window.logixProjectId)) {
// Create new project - this part needs to be improved and optimised
@@ -433,7 +447,11 @@ export default async function save() {
showMessage(
`We have Created a new project: ${projectName} in our servers.`
)
- $('.loadingIcon').fadeOut()
+
+ let loadingIcon = document.querySelector('.loadingIcon')
+ loadingIcon.style.transition = 'opacity 0.2s';
+ loadingIcon.style.opacity = '0';
+
localStorage.removeItem('recover')
const responseJson = response.json()
responseJson.then((data) => {
@@ -503,7 +521,9 @@ export default async function save() {
"There was an error, we couldn't save to our servers"
)
}
- $('.loadingIcon').fadeOut()
+ let loadingIcon = document.querySelector('.loadingIcon')
+ loadingIcon.style.transition = 'opacity 0.2s';
+ loadingIcon.style.opacity = '0';
})
.catch((error) => {
console.error('Error:', error)
diff --git a/v1/src/simulator/src/data/saveImage.js b/v1/src/simulator/src/data/saveImage.js
deleted file mode 100644
index 8e2b813d..00000000
--- a/v1/src/simulator/src/data/saveImage.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Helper function to show prompt to save image
- * Options - resolution, image type, view
- * @param {Scope=} scope - useless though
- * @category data
- */
-import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
-
-/**
- * Function called to generate a prompt to save an image
- * @category data
- * @param {Scope=} - circuit whose image we want
- * @exports createSaveAsImgPrompt
- */
-export default function createSaveAsImgPrompt(scope = globalScope) {
- const simulatorStore = SimulatorStore()
- simulatorStore.dialogBox.saveimage_dialog = true
-}
diff --git a/v1/src/simulator/src/data/saveImage.ts b/v1/src/simulator/src/data/saveImage.ts
new file mode 100644
index 00000000..cce91367
--- /dev/null
+++ b/v1/src/simulator/src/data/saveImage.ts
@@ -0,0 +1,16 @@
+import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore';
+import Scope from '../circuit';
+
+// Type declaration for global variable
+declare var globalScope: Scope;
+
+/**
+ * Function called to generate a prompt to save an image
+ * @category data
+ * @param {Scope=} scope - circuit whose image we want
+ * @exports createSaveAsImgPrompt
+ */
+export default function createSaveAsImgPrompt(scope: Scope = globalScope): void {
+ const simulatorStore = SimulatorStore();
+ simulatorStore.dialogBox.saveimage_dialog = true;
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/data/undo.js b/v1/src/simulator/src/data/undo.js
deleted file mode 100644
index 67f22005..00000000
--- a/v1/src/simulator/src/data/undo.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/* eslint-disable import/no-cycle */
-/**
- * Function to restore copy from backup
- * @param {Scope=} scope - The circuit on which undo is called
- * @category data
- */
-import { layoutModeGet } from '../layoutMode'
-import Scope, { scopeList } from '../circuit'
-import { loadScope } from './load'
-import { updateRestrictedElementsInScope } from '../restrictedElementDiv'
-import { forceResetNodesSet } from '../engine'
-/**
- * Function called to generate a prompt to save an image
- * @param {Scope=} - the circuit in which we want to call undo
- * @category data
- * @exports undo
- */
-export default function undo(scope = globalScope) {
- if (layoutModeGet()) return
- if (scope.backups.length < 2) return
- const backupOx = globalScope.ox
- const backupOy = globalScope.oy
- const backupScale = globalScope.scale
- globalScope.ox = 0
- globalScope.oy = 0
- const tempScope = new Scope(scope.name)
- loading = true
- const undoData = scope.backups.pop()
- scope.history.push(undoData)
- scope.backups.length !== 0 &&
- loadScope(
- tempScope,
- JSON.parse(scope.backups[scope.backups.length - 1])
- )
- tempScope.backups = scope.backups
- tempScope.history = scope.history
- tempScope.id = scope.id
- tempScope.name = scope.name
- tempScope.testbenchData = scope.testbenchData
- scopeList[scope.id] = tempScope
- globalScope = tempScope
- globalScope.ox = backupOx
- globalScope.oy = backupOy
- globalScope.scale = backupScale
- loading = false
- forceResetNodesSet(true)
-
- // Updated restricted elements
- updateRestrictedElementsInScope()
-}
-// for html file
diff --git a/v1/src/simulator/src/data/undo.ts b/v1/src/simulator/src/data/undo.ts
new file mode 100644
index 00000000..c2bf64b2
--- /dev/null
+++ b/v1/src/simulator/src/data/undo.ts
@@ -0,0 +1,82 @@
+/* eslint-disable import/no-cycle */
+import { layoutModeGet } from '../layoutMode'
+import Scope, { scopeList } from '../circuit'
+import { loadScope } from './load'
+import { updateRestrictedElementsInScope } from '../restrictedElementDiv'
+import { forceResetNodesSet } from '../engine'
+
+// Declare global variables
+declare let globalScope: Scope
+declare let loading: boolean
+
+/**
+ * Function to restore copy from backup
+ * @param scope - The circuit on which undo is called
+ * @category data
+ */
+export default function undo(scope: Scope = globalScope): void {
+ if (layoutModeGet() || scope.backups.length < 2) return
+
+ const { ox, oy, scale } = saveGlobalScopePosition()
+ resetGlobalScopePosition()
+
+ loading = true
+ const undoData = popLastBackup(scope)
+ if (!undoData) return
+
+ scope.history.push(undoData)
+
+ const tempScope = createTempScope(scope)
+ if (!tempScope) return
+
+ updateGlobalScope(tempScope, ox, oy, scale)
+ forceResetNodesSet(true)
+ updateRestrictedElementsInScope()
+}
+
+function saveGlobalScopePosition() {
+ return {
+ ox: globalScope.ox,
+ oy: globalScope.oy,
+ scale: globalScope.scale,
+ }
+}
+
+function resetGlobalScopePosition() {
+ globalScope.ox = 0
+ globalScope.oy = 0
+}
+
+function popLastBackup(scope: Scope): string | undefined {
+ return scope.backups.pop()
+}
+
+function createTempScope(scope: Scope): Scope | undefined {
+ const tempScope = new Scope(scope.name)
+ if (scope.backups.length === 0) return tempScope
+
+ try {
+ loadScope(tempScope, JSON.parse(scope.backups[scope.backups.length - 1]))
+ } catch (error) {
+ console.error('Failed to parse backup data:', error)
+ loading = false
+ return undefined
+ }
+
+ tempScope.backups = scope.backups
+ tempScope.history = scope.history
+ tempScope.id = scope.id
+ tempScope.name = scope.name
+ tempScope.testbenchData = scope.testbenchData
+
+ return tempScope
+}
+
+function updateGlobalScope(tempScope: Scope, ox: number, oy: number, scale: number) {
+ scopeList[tempScope.id] = tempScope
+ globalScope = tempScope
+ globalScope.ox = ox
+ globalScope.oy = oy
+ globalScope.scale = scale
+ loading = false
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/embed.js b/v1/src/simulator/src/embed.js
index b17e82ba..f1a103ec 100644
--- a/v1/src/simulator/src/embed.js
+++ b/v1/src/simulator/src/embed.js
@@ -1,7 +1,7 @@
// /* eslint-disable import/no-cycle */
// // Helper functions for when circuit is embedded
// import { scopeList, circuitProperty } from './circuit'
-// import simulationArea from './simulationArea'
+// import { simulationArea } from './simulationArea'
// import {
// scheduleUpdate,
// wireToBeCheckedSet,
diff --git a/v1/src/simulator/src/embedListeners.js b/v1/src/simulator/src/embedListeners.js
index e7cb2d0a..6f7acece 100644
--- a/v1/src/simulator/src/embedListeners.js
+++ b/v1/src/simulator/src/embedListeners.js
@@ -1,7 +1,11 @@
/* eslint-disable import/no-cycle */
// Listeners when circuit is embedded
+/* eslint-disable no-plusplus */
+/* eslint-disable func-names */
+/* eslint-disable prefer-const */
+/* eslint-disable max-len */
// Refer listeners.js
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import {
scheduleUpdate,
update,
@@ -14,167 +18,191 @@ import {
errorDetectedSet,
} from './engine'
import { changeScale } from './canvasApi'
-import { copy, paste } from './events'
-import { ZoomIn, ZoomOut } from './listeners'
+import { ZoomIn, ZoomOut, pinchZoom, getCoordinate, } from './listeners';
-var unit = 10
+const unit = 10
+let embedCoordinate;
+/** *Function embedPanStart
+ *This function hepls to initialize mouse and touch
+ *For now variable name starts with mouse like mouseDown are used both
+ touch and mouse will change in future
+*/
+function embedPanStart(e) {
+ embedCoordinate = getCoordinate(e);
+ errorDetectedSet(false);
+ updateSimulationSet(true);
+ updatePositionSet(true);
+ updateCanvasSet(true);
-export default function startListeners() {
- window.addEventListener('keyup', (e) => {
- scheduleUpdate(1)
- if (e.keyCode == 16) {
- simulationArea.shiftDown = false
- }
- if (e.key == 'Meta' || e.key == 'Control') {
- simulationArea.controlDown = false
+ simulationArea.lastSelected = undefined;
+ simulationArea.selected = false;
+ simulationArea.hover = undefined;
+ const rect = simulationArea.canvas.getBoundingClientRect();
+ simulationArea.mouseDownRawX = (embedCoordinate.x - rect.left) * DPR;
+ simulationArea.mouseDownRawY = (embedCoordinate.y - rect.top) * DPR;
+ simulationArea.mouseDownX = Math.round(((simulationArea.mouseDownRawX - globalScope.ox) / globalScope.scale) / unit) * unit;
+ simulationArea.mouseDownY = Math.round(((simulationArea.mouseDownRawY - globalScope.oy) / globalScope.scale) / unit) * unit;
+ simulationArea.mouseDown = true;
+ simulationArea.oldx = globalScope.ox;
+ simulationArea.oldy = globalScope.oy;
+ e.preventDefault();
+ scheduleUpdate(1);
+}
+/** *Function embedPanMove
+ *This function hepls to move simulator and its elements using touch and mouse
+ *For now variable name starts with mouse like mouseDown are used both
+ touch and mouse will change in future
+*/
+function embedPanMove(e) {
+ embedCoordinate = getCoordinate(e);
+ if (!simulationArea.touch || e.touches.length === 1) {
+ const rect = simulationArea.canvas.getBoundingClientRect();
+ simulationArea.mouseRawX = (embedCoordinate.x - rect.left) * DPR;
+ simulationArea.mouseRawY = (embedCoordinate.y - rect.top) * DPR;
+ simulationArea.mouseXf = (simulationArea.mouseRawX - globalScope.ox) / globalScope.scale;
+ simulationArea.mouseYf = (simulationArea.mouseRawY - globalScope.oy) / globalScope.scale;
+ simulationArea.mouseX = Math.round(simulationArea.mouseXf / unit) * unit;
+ simulationArea.mouseY = Math.round(simulationArea.mouseYf / unit) * unit;
+ updateCanvasSet(true);
+ if (simulationArea.lastSelected == globalScope.root) {
+ updateCanvasSet(true);
+ let fn;
+ fn = function () {
+ updateSelectionsAndPane();
+ };
+ scheduleUpdate(0, 20, fn);
+ } else {
+ scheduleUpdate(0, 200);
}
- })
-
- document
- .getElementById('simulationArea')
- .addEventListener('mousedown', (e) => {
- errorDetectedSet(false)
- updateSimulationSet(true)
- updatePositionSet(true)
- updateCanvasSet(true)
-
- simulationArea.lastSelected = undefined
- simulationArea.selected = false
- simulationArea.hover = undefined
- var rect = simulationArea.canvas.getBoundingClientRect()
- simulationArea.mouseDownRawX = (e.clientX - rect.left) * DPR
- simulationArea.mouseDownRawY = (e.clientY - rect.top) * DPR
- simulationArea.mouseDownX =
- Math.round(
- (simulationArea.mouseDownRawX - globalScope.ox) /
- globalScope.scale /
- unit
- ) * unit
- simulationArea.mouseDownY =
- Math.round(
- (simulationArea.mouseDownRawY - globalScope.oy) /
- globalScope.scale /
- unit
- ) * unit
- simulationArea.mouseDown = true
- simulationArea.oldx = globalScope.ox
- simulationArea.oldy = globalScope.oy
-
- e.preventDefault()
- scheduleUpdate(1)
- })
-
- document
- .getElementById('simulationArea')
- .addEventListener('mousemove', () => {
- var ele = document.getElementById('elementName')
- if (globalScope && simulationArea && simulationArea.objectList) {
- var { objectList } = simulationArea
- objectList = objectList.filter((val) => val !== 'wires')
+ }
+ if (simulationArea.touch && e.touches.length === 2) {
+ pinchZoom(e);
+ }
+}
+/** *Function embedPanEnd
+ *This function update simulator after mouse and touch end
+ *For now variable name starts with mouse like mouseDown are used both
+ touch and mouse will change in future
+*/
+function embedPanEnd() {
+ simulationArea.mouseDown = false;
+ errorDetectedSet(false);
+ updateSimulationSet(true);
+ updatePositionSet(true);
+ updateCanvasSet(true);
+ gridUpdateSet(true);
+ wireToBeCheckedSet(1);
+ scheduleUpdate(1);
+}
+/** *Function BlockElementPan
+ *This function block the pan of elements since in embed simulator you can only view simulator NOT update
+*/
- for (var i = 0; i < objectList.length; i++) {
- for (
- var j = 0;
- j < globalScope[objectList[i]].length;
- j++
- ) {
- if (globalScope[objectList[i]][j].isHover()) {
- ele.style.display = 'block'
- if (objectList[i] === 'SubCircuit') {
- ele.innerHTML = `Subcircuit: ${globalScope.SubCircuit[j].data.name}`
- } else {
- ele.innerHTML = `CircuitElement: ${objectList[i]}`
- }
- return
- }
+function BlockElementPan() {
+ const ele = document.getElementById('elementName');
+ if (globalScope && simulationArea && simulationArea.objectList) {
+ let { objectList } = simulationArea;
+ objectList = objectList.filter((val) => val !== 'wires');
+ for (let i = 0; i < objectList.length; i++) {
+ for (let j = 0; j < globalScope[objectList[i]].length; j++) {
+ if (globalScope[objectList[i]][j].isHover()) {
+ ele.style.display = 'block';
+ if (objectList[i] === 'SubCircuit') {
+ ele.innerHTML = `Subcircuit: ${globalScope.SubCircuit[j].data.name}`;
+ } else {
+ ele.innerHTML = `CircuitElement: ${objectList[i]}`;
}
+ return;
}
}
+ }
+ }
+ ele.style.display = 'none';
+ document.getElementById('elementName').innerHTML = '';
+}
- ele.style.display = 'none'
- document.getElementById('elementName').innerHTML = ''
- })
-
+export default function startListeners() {
+ window.addEventListener('keyup', (e) => {
+ scheduleUpdate(1);
+ if (e.keyCode == 16) {
+ simulationArea.shiftDown = false;
+ }
+ if (e.key == 'Meta' || e.key == 'Control') {
+ simulationArea.controlDown = false;
+ }
+ });
+ // All event listeners starts from here
+ document.getElementById('simulationArea').addEventListener('mousedown', (e) => {
+ simulationArea.touch = false;
+ embedPanStart(e);
+ });
+ document.getElementById('simulationArea').addEventListener('mousemove', () => {
+ simulationArea.touch = false;
+ BlockElementPan();
+ });
+ document.getElementById('simulationArea').addEventListener('touchstart', (e) => {
+ simulationArea.touch = true;
+ embedPanStart(e);
+ });
+ document.getElementById('simulationArea').addEventListener('touchmove', () => {
+ simulationArea.touch = true;
+ BlockElementPan();
+ });
window.addEventListener('mousemove', (e) => {
- var rect = simulationArea.canvas.getBoundingClientRect()
- simulationArea.mouseRawX = (e.clientX - rect.left) * DPR
- simulationArea.mouseRawY = (e.clientY - rect.top) * DPR
- simulationArea.mouseXf =
- (simulationArea.mouseRawX - globalScope.ox) / globalScope.scale
- simulationArea.mouseYf =
- (simulationArea.mouseRawY - globalScope.oy) / globalScope.scale
- simulationArea.mouseX = Math.round(simulationArea.mouseXf / unit) * unit
- simulationArea.mouseY = Math.round(simulationArea.mouseYf / unit) * unit
+ embedPanMove(e);
+ });
+ window.addEventListener('touchmove', (e) => {
+ embedPanMove(e);
+ });
+ window.addEventListener('mouseup', () => {
+ embedPanEnd();
+ });
+ window.addEventListener('mousedown', function () {
+ this.focus();
+ });
+ window.addEventListener('touchend', () => {
+ embedPanEnd();
+ });
+ window.addEventListener('touchstart', function () {
+ this.focus();
+ });
+ document.getElementById('simulationArea').addEventListener('mousewheel', MouseScroll);
+ document.getElementById('simulationArea').addEventListener('DOMMouseScroll', MouseScroll);
- updateCanvasSet(true)
- if (simulationArea.lastSelected == globalScope.root) {
- updateCanvasSet(true)
- var fn
- fn = function () {
- updateSelectionsAndPane()
- }
- scheduleUpdate(0, 20, fn)
- } else {
- scheduleUpdate(0, 200)
- }
- })
window.addEventListener('keydown', (e) => {
- errorDetectedSet(false)
- updateSimulationSet(true)
- updatePositionSet(true)
+ errorDetectedSet(false);
+ updateSimulationSet(true);
+ updatePositionSet(true);
// zoom in (+)
if (e.key == 'Meta' || e.key == 'Control') {
- simulationArea.controlDown = true
+ simulationArea.controlDown = true;
}
-
- if (
- simulationArea.controlDown &&
- (e.keyCode == 187 || e.KeyCode == 171)
- ) {
- e.preventDefault()
- ZoomIn()
+ if (simulationArea.controlDown && (e.keyCode == 187 || e.KeyCode == 171)) {
+ e.preventDefault();
+ ZoomIn();
}
-
// zoom out (-)
- if (
- simulationArea.controlDown &&
- (e.keyCode == 189 || e.Keycode == 173)
- ) {
- e.preventDefault()
- ZoomOut()
+ if (simulationArea.controlDown && (e.keyCode == 189 || e.Keycode == 173)) {
+ e.preventDefault();
+ ZoomOut();
}
- if (
- simulationArea.mouseRawX < 0 ||
- simulationArea.mouseRawY < 0 ||
- simulationArea.mouseRawX > width ||
- simulationArea.mouseRawY > height
- )
- return
+ if (simulationArea.mouseRawX < 0 || simulationArea.mouseRawY < 0 || simulationArea.mouseRawX > width || simulationArea.mouseRawY > height) return;
- scheduleUpdate(1)
- updateCanvasSet(true)
+ scheduleUpdate(1);
+ updateCanvasSet(true);
- if (
- simulationArea.lastSelected &&
- simulationArea.lastSelected.keyDown
- ) {
- if (
- e.key.toString().length == 1 ||
- e.key.toString() == 'Backspace'
- ) {
- simulationArea.lastSelected.keyDown(e.key.toString())
- return
+ if (simulationArea.lastSelected && simulationArea.lastSelected.keyDown) {
+ if (e.key.toString().length == 1 || e.key.toString() == 'Backspace') {
+ simulationArea.lastSelected.keyDown(e.key.toString());
+ return;
}
}
- if (
- simulationArea.lastSelected &&
- simulationArea.lastSelected.keyDown2
- ) {
+ if (simulationArea.lastSelected && simulationArea.lastSelected.keyDown2) {
if (e.key.toString().length == 1) {
- simulationArea.lastSelected.keyDown2(e.key.toString())
- return
+ simulationArea.lastSelected.keyDown2(e.key.toString());
+ return;
}
}
@@ -187,73 +215,46 @@ export default function startListeners() {
// }
if (e.key == 'T' || e.key == 't') {
- simulationArea.changeClockTime(prompt('Enter Time:'))
+ simulationArea.changeClockTime(prompt('Enter Time:'));
}
- })
- document
- .getElementById('simulationArea')
- .addEventListener('dblclick', (e) => {
- scheduleUpdate(2)
- if (
- simulationArea.lastSelected &&
- simulationArea.lastSelected.dblclick !== undefined
- ) {
- simulationArea.lastSelected.dblclick()
- }
- })
-
- window.addEventListener('mouseup', (e) => {
- simulationArea.mouseDown = false
- errorDetectedSet(false)
- updateSimulationSet(true)
- updatePositionSet(true)
- updateCanvasSet(true)
- gridUpdateSet(true)
- wireToBeCheckedSet(1)
-
- scheduleUpdate(1)
- })
- window.addEventListener('mousedown', function (e) {
- this.focus()
- })
-
- document
- .getElementById('simulationArea')
- .addEventListener('mousewheel', MouseScroll)
- document
- .getElementById('simulationArea')
- .addEventListener('DOMMouseScroll', MouseScroll)
-
+ });
+ document.getElementById('simulationArea').addEventListener('dblclick', () => {
+ scheduleUpdate(2);
+ if (simulationArea.lastSelected && simulationArea.lastSelected.dblclick !== undefined) {
+ simulationArea.lastSelected.dblclick();
+ }
+ });
function MouseScroll(event) {
- updateCanvasSet(true)
+ updateCanvasSet(true);
- event.preventDefault()
- var deltaY = event.wheelDelta ? event.wheelDelta : -event.detail
- var scrolledUp = deltaY < 0
- var scrolledDown = deltaY > 0
+ event.preventDefault();
+ const deltaY = event.wheelDelta ? event.wheelDelta : -event.detail;
+ const scrolledUp = deltaY < 0;
+ const scrolledDown = deltaY > 0;
if (event.ctrlKey) {
if (scrolledUp && globalScope.scale > 0.5 * DPR) {
- changeScale(-0.1 * DPR)
+ changeScale(-0.1 * DPR);
}
if (scrolledDown && globalScope.scale < 4 * DPR) {
- changeScale(0.1 * DPR)
+ changeScale(0.1 * DPR);
}
} else {
if (scrolledUp && globalScope.scale < 4 * DPR) {
- changeScale(0.1 * DPR)
+ changeScale(0.1 * DPR);
}
if (scrolledDown && globalScope.scale > 0.5 * DPR) {
- changeScale(-0.1 * DPR)
+ changeScale(-0.1 * DPR);
}
}
- updateCanvasSet(true)
- gridUpdateSet(true)
- update() // Schedule update not working, this is INEFFICENT
+ updateCanvasSet(true);
+ gridUpdateSet(true);
+ update(); // Schedule update not working, this is INEFFICENT
}
}
+// eslint-disable-next-line no-unused-vars
var isIe =
navigator.userAgent.toLowerCase().indexOf('msie') != -1 ||
navigator.userAgent.toLowerCase().indexOf('trident') != -1
diff --git a/v1/src/simulator/src/engine.js b/v1/src/simulator/src/engine.js
index 2f74df6e..5227eb76 100644
--- a/v1/src/simulator/src/engine.js
+++ b/v1/src/simulator/src/engine.js
@@ -5,13 +5,15 @@
/* eslint-disable no-bitwise */
import { layoutModeGet, layoutUpdate } from './layoutMode'
import plotArea from './plotArea'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import { dots, canvasMessage, findDimensions, rect2 } from './canvasApi'
import { showProperties, prevPropertyObjGet } from './ux'
import { showError } from './utils'
import miniMapArea from './minimap'
import { resetup } from './setup'
import { verilogModeGet } from './Verilog2CV'
+import { renderOrder, updateOrder } from './metadata'
+import ContentionPendingData from './contention';
/**
* Core of the simulation and rendering algorithm.
@@ -368,7 +370,7 @@ export function updateSelectionsAndPane(scope = globalScope) {
for (let i = 0; i < updateOrder.length; i++) {
for (var j = 0; j < scope[updateOrder[i]].length; j++) {
var obj = scope[updateOrder[i]][j]
- if (simulationArea.multipleObjectSelections.contains(obj))
+ if (simulationArea.multipleObjectSelections.includes(obj))
continue
var x
var y
@@ -404,6 +406,7 @@ export function play(scope = globalScope, resetNodes = false) {
simulationArea.simulationQueue.reset()
plotArea.setExecutionTime() // Waveform thing
+ resetNodeHighlights(scope);
// Reset Nodes if required
if (resetNodes || forceResetNodes) {
scope.reset()
@@ -411,9 +414,8 @@ export function play(scope = globalScope, resetNodes = false) {
forceResetNodesSet(false)
}
- // To store list of circuitselements that have shown contention but kept temporarily
- // Mainly to resolve tristate bus issues
- simulationArea.contentionPending = []
+ // To store set of Nodes that have shown contention but kept temporarily
+ simulationArea.contentionPending = new ContentionPendingData();
// add inputs to the simulation queue
scope.addInputs()
// to check if we have infinite loop in circuit
@@ -425,25 +427,34 @@ export function play(scope = globalScope, resetNodes = false) {
return
}
elem = simulationArea.simulationQueue.pop()
+
elem.resolve()
+
stepCount++
if (stepCount > 1000000) {
// Cyclic or infinite Circuit Detection
showError(
'Simulation Stack limit exceeded: maybe due to cyclic paths or contention'
)
- errorDetectedSet(true)
forceResetNodesSet(true)
}
}
- // Check for TriState Contentions
- if (simulationArea.contentionPending.length) {
- showError('Contention at TriState')
- forceResetNodesSet(true)
- errorDetectedSet(true)
+ // Check for Contentions
+ if (simulationArea.contentionPending.size() > 0) {
+ for (const [ourNode, theirNode] of simulationArea.contentionPending.nodes()) {
+ ourNode.highlighted = true;
+ theirNode.highlighted = true;
+ }
+
+ forceResetNodesSet(true);
+ showError('Contention Error: One or more bus contentions in the circuit (check highlighted nodes)');
}
}
+export function resetNodeHighlights(scope) {
+ for (const node of scope.allNodes) node.highlighted = false;
+}
+
/**
* Function to check for any UI update, it is throttled by time
* @param {number=} count - this is used to force update
@@ -451,7 +462,7 @@ export function play(scope = globalScope, resetNodes = false) {
* @param {function} fn - function to run before updating UI
* @category engine
*/
-export function scheduleUpdate(count = 0, time = 100, fn) {
+export function scheduleUpdate(count = 0, time = 100, fn = undefined) {
if (lightMode) time *= 5
var updateFn = layoutModeGet() ? layoutUpdate : update
if (count) {
diff --git a/v0/src/simulator/src/eventQueue.js b/v1/src/simulator/src/eventQueue.ts
similarity index 87%
rename from v0/src/simulator/src/eventQueue.js
rename to v1/src/simulator/src/eventQueue.ts
index f40110e1..349f137c 100644
--- a/v0/src/simulator/src/eventQueue.js
+++ b/v1/src/simulator/src/eventQueue.ts
@@ -2,19 +2,29 @@
* Event Queue is simply a priority Queue, basic implementation O(n^2).
* @category eventQueue
*/
-export default class EventQueue {
- constructor(size) {
+
+interface QueueObject {
+ queueProperties: {
+ inQueue: boolean
+ time: number
+ index: number
+ }
+ propagationDelay: number
+}
+
+export class EventQueue {
+ size: number
+ queue: Array
+ frontIndex: number
+ time: number
+ constructor(size: number) {
this.size = size
this.queue = new Array(size)
this.frontIndex = 0
this.time = 0
}
- /**
- * @param {CircuitElement} obj - the elemnt to be added
- * @param {number} delay - the delay in adding an object to queue
- */
- add(obj, delay) {
+ add(obj: QueueObject, delay: number) {
if (obj.queueProperties.inQueue) {
obj.queueProperties.time =
this.time + (delay || obj.propagationDelay)
@@ -41,7 +51,6 @@ export default class EventQueue {
if (this.frontIndex == this.size) throw 'EventQueue size exceeded'
this.queue[this.frontIndex] = obj
- // obj.queueProperties.time=obj.propagationDelay;
obj.queueProperties.time = this.time + (delay || obj.propagationDelay)
obj.queueProperties.index = this.frontIndex
this.frontIndex++
@@ -60,7 +69,7 @@ export default class EventQueue {
* To add without any delay.
* @param {CircuitElement} obj - the object to be added
*/
- addImmediate(obj) {
+ addImmediate(obj: QueueObject) {
this.queue[this.frontIndex] = obj
obj.queueProperties.time = this.time
obj.queueProperties.index = this.frontIndex
@@ -70,10 +79,8 @@ export default class EventQueue {
/**
* Function to swap two objects in queue.
- * @param {number} v1
- * @param {number} v2
*/
- swap(v1, v2) {
+ swap(v1: number, v2: number) {
const obj1 = this.queue[v1]
obj1.queueProperties.index = v2
diff --git a/v1/src/simulator/src/events.js b/v1/src/simulator/src/events.js
index c3c0edca..07de4275 100644
--- a/v1/src/simulator/src/events.js
+++ b/v1/src/simulator/src/events.js
@@ -11,16 +11,16 @@ import {
import { backUp } from './data/backupCircuit'
import { getNextPosition } from './modules'
import { generateId } from './utils'
-import simulationArea from './simulationArea'
-import { TestbenchData } from './testbench'
+import { simulationArea } from './simulationArea'
+import { TestbenchData } from '#/simulator/src/testbench'
+import { moduleList, updateOrder } from './metadata'
/**
* Helper function to paste
- * @param {JSON} copyData - the data to be pasted
* @category events
*/
export function paste(copyData) {
- if (copyData === undefined) return
+ if (copyData === 'undefined') return
var data = JSON.parse(copyData)
if (!data.logixClipBoardData) return
@@ -104,7 +104,7 @@ export function paste(copyData) {
l !== 'objects' &&
l !== 'CircuitElement'
) {
- globalScope[l].extend(tempScope[l])
+ globalScope[l].push(...tempScope[l])
}
})
for (let i = 0; i < tempScope.Input.length; i++) {
@@ -119,7 +119,6 @@ export function paste(copyData) {
globalScope
)
}
- var canvasUpdate = true
updateSimulationSet(true)
updateSubcircuitSet(true)
scheduleUpdate()
@@ -165,7 +164,7 @@ export function cut(copyList) {
const obj = globalScope[updateOrder[i]][j]
if (obj.objectType != 'Wire') {
// }&&obj.objectType!='CircuitElement'){//}&&(obj.objectType!='Node'||obj.type==2)){
- if (!copyList.contains(globalScope[updateOrder[i]][j])) {
+ if (!copyList.includes(globalScope[updateOrder[i]][j])) {
globalScope[updateOrder[i]][j].cleanDelete()
}
}
@@ -198,9 +197,8 @@ export function cut(copyList) {
data.logixClipBoardData = true
data = JSON.stringify(data)
- simulationArea.multipleObjectSelections = [] // copyList.slice();
- simulationArea.copyList = [] // copyList.slice();
- var canvasUpdate = true
+ simulationArea.multipleObjectSelections = []
+ simulationArea.copyList = []
updateSimulationSet(true)
globalScope = tempScope
scheduleUpdate()
@@ -252,7 +250,7 @@ export function copy(copyList, cutflag = false) {
const obj = globalScope[updateOrder[i]][j]
if (obj.objectType != 'Wire') {
// }&&obj.objectType!='CircuitElement'){//}&&(obj.objectType!='Node'||obj.type==2)){
- if (!copyList.contains(globalScope[updateOrder[i]][j])) {
+ if (!copyList.includes(globalScope[updateOrder[i]][j])) {
globalScope[updateOrder[i]][j].cleanDelete()
}
}
@@ -297,9 +295,8 @@ export function copy(copyList, cutflag = false) {
data.logixClipBoardData = true
data.testbenchData = undefined // Don't copy testbench data
data = JSON.stringify(data)
- simulationArea.multipleObjectSelections = [] // copyList.slice();
- simulationArea.copyList = [] // copyList.slice();
- var canvasUpdate = true
+ simulationArea.multipleObjectSelections = []
+ simulationArea.copyList = []
updateSimulationSet(true)
globalScope = tempScope
scheduleUpdate()
diff --git a/v0/src/simulator/src/hotkey_binder/defaultKeys.js b/v1/src/simulator/src/hotkey_binder/defaultKeys.ts
similarity index 89%
rename from v0/src/simulator/src/hotkey_binder/defaultKeys.js
rename to v1/src/simulator/src/hotkey_binder/defaultKeys.ts
index 0529ce5f..42afbbf6 100644
--- a/v0/src/simulator/src/hotkey_binder/defaultKeys.js
+++ b/v1/src/simulator/src/hotkey_binder/defaultKeys.ts
@@ -1,8 +1,11 @@
/**Add more elements here, along with a valid value for key
* Elements keys must have the same name as their ID
**/
+export interface DefaultKeysType {
+ [key: string]: string;
+}
-export const defaultKeys = {
+export const defaultKeys: DefaultKeysType = {
'New Circuit': 'Shift + N',
'Save Online': 'Ctrl + S',
'Save Offline': 'Ctrl + Alt + S',
diff --git a/v1/src/simulator/src/hotkey_binder/model/actions.js b/v1/src/simulator/src/hotkey_binder/model/actions.js
deleted file mode 100644
index 102209ee..00000000
--- a/v1/src/simulator/src/hotkey_binder/model/actions.js
+++ /dev/null
@@ -1,205 +0,0 @@
-import { defaultKeys } from '../defaultKeys'
-import { addShortcut } from './addShortcut'
-import { updateHTML } from '../view/panel.ui'
-import simulationArea from '../../simulationArea'
-import {
- scheduleUpdate,
- update,
- updateSelectionsAndPane,
- wireToBeCheckedSet,
- updatePositionSet,
- updateSimulationSet,
- updateCanvasSet,
- gridUpdateSet,
- errorDetectedSet,
-} from '../../engine'
-
-import { getOS } from './utils.js'
-import { shortcut } from './shortcuts.plugin.js'
-/**
- * Function used to add or change keys user or default
- * grabs the keycombo from localstorage &
- * calls the addShortcut function in a loop to bind them
- * @param {string} mode - user custom keys or default keys
- */
-export const addKeys = (mode) => {
- shortcut.removeAll()
- if (mode === 'user') {
- localStorage.removeItem('defaultKeys')
- let userKeys = localStorage.get('userKeys')
- for (let pref in userKeys) {
- let key = userKeys[pref]
- key = key.split(' ').join('')
- addShortcut(key, pref)
- }
- updateHTML('user')
- } else if (mode == 'default') {
- if (localStorage.userKeys) localStorage.removeItem('userKeys')
- let defaultKeys = localStorage.get('defaultKeys')
- for (let pref in defaultKeys) {
- let key = defaultKeys[pref]
- key = key.split(' ').join('')
- addShortcut(key, pref)
- }
- updateHTML('default')
- }
-}
-/**
- * Function used to check if new keys are added, adds missing keys if added
- */
-export const checkUpdate = () => {
- const userK = localStorage.get('userKeys')
- if (Object.size(userK) !== Object.size(defaultKeys)) {
- for (const [key, value] of Object.entries(defaultKeys)) {
- if (!Object.keys(userK).includes(key)) {
- userK[key] = value
- }
- }
- localStorage.set('userKeys', userK)
- } else {
- return
- }
-}
-/**
- * Function used to set userKeys, grabs the keycombo from the panel UI
- * sets it to the localStorage & cals addKeys
- * removes the defaultkeys from localStorage
- */
-export const setUserKeys = () => {
- if (localStorage.defaultKeys) localStorage.removeItem('defaultKeys')
- let userKeys = {}
- let x = 0
- while ($('#preference').children()[x]) {
- userKeys[
- $('#preference').children()[x].children[1].children[0].innerText
- ] = $('#preference').children()[x].children[1].children[1].innerText
- x++
- }
- localStorage.set('userKeys', userKeys)
- addKeys('user')
-}
-/**
- * Function used to set defaultKeys, grabs the keycombo from the defaultkeys metadata
- * sets it to the localStorage & cals addKeys
- * removes the userkeys from localStorage if present
- * also checks for OS type
- */
-export const setDefault = () => {
- if (localStorage.userKeys) localStorage.removeItem('userKeys')
- if (getOS() === 'MacOS') {
- const macDefaultKeys = {}
- for (let [key, value] of Object.entries(defaultKeys)) {
- if (value.split(' + ')[0] == 'Ctrl');
- macDefaultKeys[key] =
- value.split(' + ')[0] == 'Ctrl'
- ? value.replace('Ctrl', 'Meta')
- : value
- localStorage.set('defaultKeys', macDefaultKeys)
- }
- } else {
- localStorage.set('defaultKeys', defaultKeys) //TODO add a confirmation alert
- }
- addKeys('default')
-}
-/**
- * function to check if user entered keys are already assigned to other key
- * gives a warning message if keys already assigned
- * @param {string} combo the key combo
- * @param {string} target the target option of the panel
- */
-export const warnOverride = (combo, target, warning) => {
- let x = 0
- while ($('#preference').children()[x]) {
- if (
- $('#preference').children()[x].children[1].children[1].innerText ===
- combo &&
- $('#preference').children()[x].children[1].children[0].innerText !==
- target.previousElementSibling.innerText
- ) {
- const assignee =
- $('#preference').children()[x].children[1].children[0].innerText
- // $('#warning').text(
- // `This key(s) is already assigned to: ${assignee}, press Enter to override.`
- // )
- warning.value = `This key(s) is already assigned to: ${assignee}, press Enter to override.`
- $('#edit').css('border', '1.5px solid #dc5656')
- return
- } else {
- $('#edit').css('border', 'none')
- }
- x++
- }
-}
-
-export const elementDirection = (direct) => () => {
- if (simulationArea.lastSelected) {
- simulationArea.lastSelected.newDirection(direct.toUpperCase())
- $("select[name |= 'newDirection']").val(direct.toUpperCase())
- updateSystem()
- }
-}
-
-export const labelDirection = (direct) => () => {
- if (
- simulationArea.lastSelected &&
- !simulationArea.lastSelected.labelDirectionFixed
- ) {
- simulationArea.lastSelected.labelDirection = direct.toUpperCase()
- $("select[name |= 'newLabelDirection']").val(direct.toUpperCase())
- updateSystem()
- }
-}
-
-export const insertLabel = () => {
- if (simulationArea.lastSelected) {
- $("input[name |= 'setLabel']").focus()
- $("input[name |= 'setLabel']").val().length
- ? null
- : $("input[name |= 'setLabel']").val('Untitled')
- $("input[name |= 'setLabel']").select()
- updateSystem()
- }
-}
-
-export const moveElement = (direct) => () => {
- if (simulationArea.lastSelected) {
- switch (direct) {
- case 'up':
- simulationArea.lastSelected.y -= 10
- break
- case 'down':
- simulationArea.lastSelected.y += 10
- break
- case 'left':
- simulationArea.lastSelected.x -= 10
- break
- case 'right':
- simulationArea.lastSelected.x += 10
- break
- }
- updateSystem()
- }
-}
-
-export const openHotkey = () => $('#customShortcut').trigger('click')
-
-export const createNewCircuitScopeCall = () =>
- $('#createNewCircuitScope').trigger('click') // TODO: remove later
-
-export const openDocumentation = () => {
- if (
- simulationArea.lastSelected == undefined ||
- simulationArea.lastSelected.helplink == undefined
- ) {
- // didn't select any element or documentation not found
- window.open('https://docs.circuitverse.org/', '_blank')
- } else {
- window.open(simulationArea.lastSelected.helplink, '_blank')
- }
-}
-
-function updateSystem() {
- updateCanvasSet(true)
- wireToBeCheckedSet(1)
- scheduleUpdate(1)
-}
diff --git a/v1/src/simulator/src/hotkey_binder/model/actions.ts b/v1/src/simulator/src/hotkey_binder/model/actions.ts
new file mode 100644
index 00000000..33452764
--- /dev/null
+++ b/v1/src/simulator/src/hotkey_binder/model/actions.ts
@@ -0,0 +1,340 @@
+/* eslint-disable import/no-cycle */
+import { defaultKeys } from '../defaultKeys'
+import { addShortcut } from './addShortcut'
+import { updateHTML } from '../view/panel.ui'
+import { simulationArea } from '../../simulationArea'
+import {
+ scheduleUpdate,
+ wireToBeCheckedSet,
+ updateCanvasSet,
+} from '../../engine'
+
+import { getOS } from './utils'
+import { shortcut } from './shortcuts.plugin'
+
+import { KeyMap } from './model.types'
+
+type DirectionType = 'up' | 'down' | 'left' | 'right'
+
+/**
+ * Function used to add or change keys user or default
+ * grabs the keycombo from localstorage &
+ * calls the addShortcut function in a loop to bind them
+ * @param {string} mode - user custom keys or default keys
+ */
+export const addKeys = (mode: 'user' | 'default'): void => {
+ shortcut.removeAll()
+ const keys = mode === 'user' ? getUserKeys() : getDefaultKeys()
+ bindKeys(keys, mode)
+}
+
+/**
+ * Get user keys from localStorage
+ */
+const getUserKeys = (): KeyMap => {
+ localStorage.removeItem('defaultKeys')
+ return JSON.parse(localStorage.getItem('userKeys') || '{}')
+}
+
+/**
+ * Get default keys from localStorage
+ */
+const getDefaultKeys = (): KeyMap => {
+ if (localStorage.userKeys) localStorage.removeItem('userKeys')
+ return JSON.parse(localStorage.getItem('defaultKeys') || '{}')
+}
+
+/**
+ * Bind keys to shortcuts
+ */
+const bindKeys = (keys: KeyMap, mode: 'user' | 'default'): void => {
+ Object.entries(keys).forEach(([pref, key]) => {
+ const normalizedKey = key.split(' ').join('')
+ addShortcut(normalizedKey, pref)
+ })
+ updateHTML(mode)
+}
+
+/**
+ * Function used to check if new keys are added, adds missing keys if added
+ */
+export const checkUpdate = (): void => {
+ const userK: KeyMap = JSON.parse(localStorage.getItem('userKeys') || '{}');
+ const defaultK: KeyMap = defaultKeys;
+
+ const hasChanges = syncKeys(userK, defaultK);
+
+ if (hasChanges) {
+ localStorage.setItem('userKeys', JSON.stringify(userK));
+ }
+};
+
+const syncKeys = (userK: KeyMap, defaultK: KeyMap): boolean => {
+ const hasAddedOrUpdated = addOrUpdateKeys(userK, defaultK);
+ const hasRemoved = removeObsoleteKeys(userK, defaultK);
+
+ return hasAddedOrUpdated || hasRemoved;
+};
+
+const addOrUpdateKeys = (userK: KeyMap, defaultK: KeyMap): boolean => {
+ let hasChanges = false;
+
+ for (const key of Object.keys(defaultK)) {
+ if (!Object.hasOwn(userK, key) || userK[key] !== defaultK[key]) {
+ userK[key] = defaultK[key];
+ hasChanges = true;
+ }
+ }
+
+ return hasChanges;
+};
+
+const removeObsoleteKeys = (userK: KeyMap, defaultK: KeyMap): boolean => {
+ let hasChanges = false;
+
+ for (const key of Object.keys(userK)) {
+ if (!Object.hasOwn(defaultK, key)) {
+ delete userK[key];
+ hasChanges = true;
+ }
+ }
+
+ return hasChanges;
+};
+
+/**
+ * Add missing keys to user keys
+ */
+const addMissingKeys = (userK: KeyMap): void => {
+ Object.entries(defaultKeys).forEach(([key, value]) => {
+ if (!userK[key]) {
+ userK[key] = value
+ }
+ })
+}
+
+/**
+ * Function used to set userKeys, grabs the keycombo from the panel UI
+ * sets it to the localStorage & calls addKeys
+ * removes the defaultkeys from localStorage
+ */
+export const setUserKeys = (): void => {
+ if (localStorage.defaultKeys) localStorage.removeItem('defaultKeys')
+ const userKeys = getUserKeysFromUI()
+ localStorage.setItem('userKeys', JSON.stringify(userKeys))
+ addKeys('user')
+}
+
+/**
+ * Get user keys from the UI
+ */
+const getUserKeysFromUI = (): KeyMap => {
+ const userKeys: KeyMap = {}
+ const preferenceChildren = document.getElementById('preference')?.children
+ if (!preferenceChildren) return userKeys
+
+ Array.from(preferenceChildren).forEach((child) => {
+ const keyChild = child?.children[1]?.children[0]
+ const valueChild = child?.children[1]?.children[1]
+
+ if (keyChild instanceof HTMLElement && valueChild instanceof HTMLElement) {
+ userKeys[keyChild.innerText] = valueChild.innerText
+ }
+ })
+ return userKeys
+}
+
+/**
+ * Function used to set defaultKeys, grabs the keycombo from the defaultkeys metadata
+ * sets it to the localStorage & calls addKeys
+ * removes the userkeys from localStorage if present
+ * also checks for OS type
+ */
+export const setDefault = (): void => {
+ if (localStorage.getItem('userKeys')) localStorage.removeItem('userKeys')
+ const keys = getOS() === 'MacOS' ? getMacDefaultKeys() : defaultKeys
+ localStorage.setItem('defaultKeys', JSON.stringify(keys))
+ addKeys('default')
+}
+
+/**
+ * Get default keys for MacOS
+ */
+const getMacDefaultKeys = (): KeyMap => {
+ const macDefaultKeys: KeyMap = {}
+ Object.entries(defaultKeys).forEach(([key, value]) => {
+ macDefaultKeys[key] = value.split(' + ')[0] === 'Ctrl' ? value.replace('Ctrl', 'Meta') : value
+ })
+ return macDefaultKeys
+}
+
+/**
+ * Function to check if user entered keys are already assigned to other key
+ * gives a warning message if keys already assigned
+ */
+export const warnOverride = (
+ combo: string,
+ target: HTMLElement,
+ warning: HTMLInputElement
+): void => {
+ const preferenceChildren = document.getElementById('preference')?.children
+ if (!preferenceChildren) return
+
+ const isComboAssigned = checkIfComboIsAssigned(combo, target, preferenceChildren)
+ if (isComboAssigned) {
+ warning.value = `This key(s) is already assigned to: ${isComboAssigned}, press Enter to override.`
+ setEditElementBorder('#dc5656')
+ } else {
+ setEditElementBorder('none')
+ }
+}
+
+/**
+ * Check if the key combo is already assigned to another key
+ */
+const checkIfComboIsAssigned = (
+ combo: string,
+ target: HTMLElement,
+ preferenceChildren: HTMLCollection
+): string | undefined => {
+ return Array.from(preferenceChildren).reduce((acc, child) => {
+ if (acc) return acc
+ return getAssigneeFromPreference(child, combo, target)
+ }, undefined)
+}
+
+/**
+ * Get the assignee from a preference element if the combo matches
+ */
+const getAssigneeFromPreference = (
+ preferenceElement: Element | null,
+ combo: string,
+ target: HTMLElement
+): string | undefined => {
+ const keyChild = preferenceElement?.children[1]?.children[0]
+ const valueChild = preferenceElement?.children[1]?.children[1]
+
+ if (keyChild instanceof HTMLElement && valueChild instanceof HTMLElement) {
+ const assignee = keyChild.innerText
+ if (valueChild.innerText === combo &&
+ assignee !== (target.previousElementSibling as HTMLElement)?.innerText) {
+ return assignee
+ }
+ }
+ return undefined
+}
+
+/**
+ * Set border style for edit element
+ */
+const setEditElementBorder = (color: string): void => {
+ const editElement = document.getElementById('edit')
+ if (editElement) {
+ editElement.style.border = color === 'none' ? 'none' : `1.5px solid ${color}`
+ }
+}
+
+/**
+ * Update element direction
+ */
+export const elementDirection = (direct: string) => (): void => {
+ if (simulationArea.lastSelected) {
+ simulationArea.lastSelected.newDirection(direct.toUpperCase())
+ updateSelectElement("select[name^='newDirection']", direct.toUpperCase())
+ updateSystem()
+ }
+}
+
+/**
+ * Update label direction
+ */
+export const labelDirection = (direct: string) => (): void => {
+ if (simulationArea.lastSelected && !simulationArea.lastSelected.labelDirectionFixed) {
+ simulationArea.lastSelected.labelDirection = direct.toUpperCase()
+ updateSelectElement("select[name^='newLabelDirection']", direct.toUpperCase())
+ updateSystem()
+ }
+}
+
+/**
+ * Update select element value
+ */
+const updateSelectElement = (selector: string, value: string): void => {
+ const selectElement = document.querySelector(selector)
+ if (selectElement) {
+ selectElement.value = value
+ }
+}
+
+/**
+ * Insert label into input field
+ */
+export const insertLabel = (): void => {
+ if (!simulationArea.lastSelected) return
+
+ const labelInput = document.querySelector("input[name^='setLabel']")
+ if (!labelInput) return
+
+ focusAndSetLabel(labelInput)
+ updateSystem()
+}
+
+/**
+ * Focus on the label input and set a default value if empty
+ */
+const focusAndSetLabel = (labelInput: HTMLInputElement): void => {
+ labelInput.focus()
+ if (!labelInput.value) {
+ labelInput.value = 'Untitled'
+ }
+ labelInput.select()
+}
+
+/**
+ * Move element in a specific direction
+ */
+export const moveElement = (direct: DirectionType) => (): void => {
+ if (simulationArea.lastSelected) {
+ const { x, y } = simulationArea.lastSelected
+ const newPosition = calculateNewPosition(direct, x, y)
+ simulationArea.lastSelected.x = newPosition.x
+ simulationArea.lastSelected.y = newPosition.y
+ updateSystem()
+ }
+}
+
+/**
+ * Calculate new position based on direction
+ */
+const calculateNewPosition = (direct: DirectionType, x: number, y: number): { x: number; y: number } => {
+ switch (direct) {
+ case 'up': return { x, y: y - 10 }
+ case 'down': return { x, y: y + 10 }
+ case 'left': return { x: x - 10, y }
+ case 'right': return { x: x + 10, y }
+ }
+}
+
+/**
+ * Open hotkey settings
+ */
+export const openHotkey = (): void => {
+ document.getElementById('customShortcut')?.click()
+}
+
+/**
+ * Open documentation
+ */
+export const openDocumentation = (): void => {
+ const url = simulationArea.lastSelected?.helplink || 'https://docs.circuitverse.org/'
+ window.open(url, '_blank')
+}
+
+/**
+ * Update system state
+ */
+function updateSystem(): void {
+ updateCanvasSet(true)
+ wireToBeCheckedSet(1)
+ scheduleUpdate(1)
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/hotkey_binder/model/addShortcut.js b/v1/src/simulator/src/hotkey_binder/model/addShortcut.ts
similarity index 69%
rename from v1/src/simulator/src/hotkey_binder/model/addShortcut.js
rename to v1/src/simulator/src/hotkey_binder/model/addShortcut.ts
index 27834ab1..c5e0b4dd 100644
--- a/v1/src/simulator/src/hotkey_binder/model/addShortcut.js
+++ b/v1/src/simulator/src/hotkey_binder/model/addShortcut.ts
@@ -1,8 +1,4 @@
-// import { shortcut } from './Shortcuts.plugin';
-// import createSaveAsImgPrompt from '../../data/saveImage';
-//Assign the callback func for the keymap here
import {
- createNewCircuitScopeCall,
elementDirection,
insertLabel,
labelDirection,
@@ -15,13 +11,44 @@ import { saveOffline, openOffline } from '../../data/project'
import createSaveAsImgPrompt from '../../data/saveImage'
import { createSubCircuitPrompt } from '../../subcircuit'
import { createCombinationalAnalysisPrompt } from '../../combinationalAnalysis'
-import { shortcut } from './shortcuts.plugin.js'
+import { shortcut } from './shortcuts.plugin'
+import logixFunction from '../../data'
+import { ShortcutOptions } from './model.types'
+
+export type ActionType =
+ | 'New Circuit'
+ | 'Save Online'
+ | 'Save Offline'
+ | 'Download as Image'
+ | 'Open Offline'
+ | 'Insert Sub-circuit'
+ | 'Combinational Analysis'
+ | 'Direction Up'
+ | 'Direction Down'
+ | 'Direction Left'
+ | 'Direction Right'
+ | 'Insert Label'
+ | 'Label Direction Up'
+ | 'Label Direction Down'
+ | 'Label Direction Left'
+ | 'Label Direction Right'
+ | 'Move Element Up'
+ | 'Move Element Down'
+ | 'Move Element Left'
+ | 'Move Element Right'
+ | 'Hotkey Preference'
+ | 'Open Documentation'
+
+export const addShortcut = (
+ keys: string,
+ action: ActionType,
+ customOptions?: Partial
+): void => {
+ let callback: (() => void) | (() => Promise)
-export const addShortcut = (keys, action) => {
- let callback
switch (action) {
case 'New Circuit':
- callback = createNewCircuitScopeCall // TODO: directly call rather than using dom click
+ callback = logixFunction.createNewCircuitScope
break
case 'Save Online':
callback = save
@@ -40,10 +67,7 @@ export const addShortcut = (keys, action) => {
break
case 'Combinational Analysis':
callback = createCombinationalAnalysisPrompt
- break //bug
- // case "Start Plot":
- // callback = startPlot;
- // break;
+ break
case 'Direction Up':
callback = elementDirection('up')
break
@@ -90,13 +114,16 @@ export const addShortcut = (keys, action) => {
callback = openDocumentation
break
default:
- callback = () => console.log('No shortcut found..')
- break
+ callback = () => console.error('No shortcut found..')
}
- shortcut.add(keys, callback, {
+
+ const options: ShortcutOptions = {
type: 'keydown',
propagate: false,
target: document,
disable_in_input: true,
- })
-}
+ ...customOptions
+ }
+
+ shortcut.add(keys, callback, options)
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/hotkey_binder/model/model.types.ts b/v1/src/simulator/src/hotkey_binder/model/model.types.ts
new file mode 100644
index 00000000..271cbf01
--- /dev/null
+++ b/v1/src/simulator/src/hotkey_binder/model/model.types.ts
@@ -0,0 +1,25 @@
+//This file holds the interfaces required for src/simulator/src/hotkey_binder/model
+//to be continued for storing interfaces of the parent folder
+
+export interface ShortcutOptions {
+ type?: string
+ propagate?: boolean
+ disable_in_input?: boolean
+ target?: Document | string
+ keycode?: number | false
+}
+
+export interface ShortcutBinding {
+ callback: EventListener
+ target: Document | HTMLElement
+ event: string
+}
+
+export interface ModifierState {
+ wanted: boolean
+ pressed: boolean
+}
+
+export interface KeyMap {
+ [key: string]: string
+}
diff --git a/v1/src/simulator/src/hotkey_binder/model/shortcuts.plugin.js b/v1/src/simulator/src/hotkey_binder/model/shortcuts.plugin.js
deleted file mode 100644
index f80d37bd..00000000
--- a/v1/src/simulator/src/hotkey_binder/model/shortcuts.plugin.js
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * http://www.openjs.com/scripts/events/keyboard_shortcuts/
- * Version : 2.01.B
- * By Binny V A
- * License : BSD
- */
-
-/**
- * Restrictions:
- * The shortcut key combination should be specified in this format ... Modifier[+Modifier..]+Key.
- * Can have a single key without Modifier .. Key, not Key + Key
- * These restrictions must be be hardcoded to not let users input invalid key combo
- * There is no way to override Ctrl+N, Ctrl+T, or Ctrl+W in Google Chrome since version 4 of Chrome (shipped in 2010).
- *
- **/
-
-//*! This plugin has been modified
-
-export const shortcut = {
- all_shortcuts: {}, //All the shortcuts are stored in this array ex. download : keycombo;
- add: function (shortcut_combination, callback, opt) {
- //Provide a set of default options
- var default_options = {
- type: 'keydown',
- propagate: false,
- disable_in_input: true,
- target: document,
- keycode: false,
- }
-
- if (!opt) opt = default_options
- else {
- for (var dfo in default_options) {
- if (typeof opt[dfo] == 'undefined')
- opt[dfo] = default_options[dfo]
- }
- }
-
- var ele = opt.target
- if (typeof opt.target == 'string')
- ele = document.getElementById(opt.target)
- var ths = this
- shortcut_combination = shortcut_combination.toLowerCase()
-
- //The function to be called at keypress
- var func = function (e) {
- e = e || window.event
- if (opt['disable_in_input']) {
- //Don't enable shortcut keys in Input, Textarea fields
- var element
- if (e.target) element = e.target
- else if (e.srcElement) element = e.srcElement
- if (element.nodeType == 3) element = element.parentNode
-
- if (element.tagName == 'INPUT' || element.tagName == 'TEXTAREA')
- return
- }
-
- let code = ''
- //Find Which key is pressed
- if (e.keyCode) code = e.keyCode
- else if (e.which) code = e.which
- var character = String.fromCharCode(code).toLowerCase()
- // e.preventDefault();
-
- if (code == 188) character = ',' //If the user presses , when the type is onkeydown
- if (code == 190) character = '.' //If the user presses , when the type is onkeydown
-
- var keys = shortcut_combination.split('+')
- //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
- var kp = 0
-
- //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
- var shift_nums = {
- '`': '~',
- 1: '!',
- 2: '@',
- 3: '#',
- 4: '$',
- 5: '%',
- 6: '^',
- 7: '&',
- 8: '*',
- 9: '(',
- 0: ')',
- '-': '_',
- '=': '+',
- ';': ':',
- "'": '"',
- ',': '<',
- '.': '>',
- '/': '?',
- '\\': '|',
- }
- //Special Keys - and their codes
- var special_keys = {
- esc: 27,
- escape: 27,
- tab: 9,
- space: 32,
- return: 13,
- enter: 13,
- backspace: 8,
-
- scrolllock: 145,
- scroll_lock: 145,
- scroll: 145,
- capslock: 20,
- caps_lock: 20,
- caps: 20,
- numlock: 144,
- num_lock: 144,
- num: 144,
-
- pause: 19,
- break: 19,
-
- insert: 45,
- home: 36,
- delete: 46,
- end: 35,
-
- pageup: 33,
- page_up: 33,
- pu: 33,
-
- pagedown: 34,
- page_down: 34,
- pd: 34,
-
- left: 37,
- up: 38,
- right: 39,
- down: 40,
-
- f1: 112,
- f2: 113,
- f3: 114,
- f4: 115,
- f5: 116,
- f6: 117,
- f7: 118,
- f8: 119,
- f9: 120,
- f10: 121,
- f11: 122,
- f12: 123,
- }
-
- var modifiers = {
- shift: { wanted: false, pressed: false },
- ctrl: { wanted: false, pressed: false },
- alt: { wanted: false, pressed: false },
- meta: { wanted: false, pressed: false }, //Meta is Mac specific
- }
-
- if (e.ctrlKey) modifiers.ctrl.pressed = true
- if (e.shiftKey) modifiers.shift.pressed = true
- if (e.altKey) modifiers.alt.pressed = true
- if (e.metaKey) modifiers.meta.pressed = true
-
- let k
- for (var i = 0; (k = keys[i]), i < keys.length; i++) {
- //Modifiers
- if (k == 'ctrl' || k == 'control') {
- kp++
- modifiers.ctrl.wanted = true
- } else if (k == 'shift') {
- kp++
- modifiers.shift.wanted = true
- } else if (k == 'alt') {
- kp++
- modifiers.alt.wanted = true
- } else if (k == 'meta') {
- kp++
- modifiers.meta.wanted = true
- } else if (k.length > 1) {
- //If it is a special key
- if (special_keys[k] == code) kp++
- } else if (opt['keycode']) {
- if (opt['keycode'] == code) kp++
- } else {
- //The special keys did not match
- if (character == k) kp++
- else {
- if (shift_nums[character] && e.shiftKey) {
- //Stupid Shift key bug created by using lowercase
- character = shift_nums[character]
- if (character == k) kp++
- }
- }
- }
- }
-
- if (
- kp == keys.length &&
- modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
- modifiers.shift.pressed == modifiers.shift.wanted &&
- modifiers.alt.pressed == modifiers.alt.wanted &&
- modifiers.meta.pressed == modifiers.meta.wanted
- ) {
- callback(e)
-
- if (!opt['propagate']) {
- //Stop the event
- //e.cancelBubble is supported by IE - this will kill the bubbling process.
- e.cancelBubble = true
- e.returnValue = false
-
- //e.stopPropagation works in Firefox.
- if (e.stopPropagation) {
- e.stopPropagation()
- e.preventDefault()
- }
- return false
- }
- }
- }
- this.all_shortcuts[shortcut_combination] = {
- callback: func,
- target: ele,
- event: opt['type'],
- }
- //Attach the function with the event
- if (ele.addEventListener) ele.addEventListener(opt['type'], func, false)
- else if (ele.attachEvent) ele.attachEvent('on' + opt['type'], func)
- else ele['on' + opt['type']] = func
- },
-
- //Remove the shortcut - just specify the shortcut and I will remove the binding
- remove: function (shortcut_combination) {
- shortcut_combination = shortcut_combination.toLowerCase()
- var binding = this.all_shortcuts[shortcut_combination]
- delete this.all_shortcuts[shortcut_combination]
- if (!binding) return
- var type = binding['event']
- var ele = binding['target']
- var callback = binding['callback']
-
- if (ele.detachEvent) ele.detachEvent('on' + type, callback)
- else if (ele.removeEventListener)
- ele.removeEventListener(type, callback, false)
- else ele['on' + type] = false
- },
- removeAll: function () {
- for (let x in this.all_shortcuts) {
- this.remove(x)
- }
- },
-}
diff --git a/v1/src/simulator/src/hotkey_binder/model/shortcuts.plugin.ts b/v1/src/simulator/src/hotkey_binder/model/shortcuts.plugin.ts
new file mode 100644
index 00000000..f34d25b3
--- /dev/null
+++ b/v1/src/simulator/src/hotkey_binder/model/shortcuts.plugin.ts
@@ -0,0 +1,232 @@
+import { ShortcutOptions,ShortcutBinding,ModifierState } from './model.types'
+
+export const shortcut = {
+ all_shortcuts: {} as Record,
+
+ add: function (shortcut_combination: string, callback: (e: KeyboardEvent) => void, opt?: ShortcutOptions): void {
+ if (!shortcut_combination || typeof shortcut_combination !== 'string') {
+ throw new Error('Shortcut combination must be a non-empty string');
+ }
+ if (!callback || typeof callback !== 'function') {
+ throw new Error('Callback must be a function');
+ }
+
+ const options = this.getOptions(opt);
+ const ele = this.getTargetElement(options.target);
+ shortcut_combination = shortcut_combination.toLowerCase();
+
+ const func = this.createEventListener(shortcut_combination, callback, options);
+ this.registerShortcut(shortcut_combination, func, ele, options.type || 'keydown');
+ },
+
+ remove: function (shortcut_combination: string): void {
+ shortcut_combination = shortcut_combination.toLowerCase();
+ const binding = this.all_shortcuts[shortcut_combination];
+
+ if (binding) {
+ this.unregisterShortcut(binding);
+ delete this.all_shortcuts[shortcut_combination];
+ } else {
+ console.warn(`No binding found for shortcut: ${shortcut_combination}`);
+ }
+ },
+
+ removeAll: function (): void {
+ const failures: string[] = [];
+ Object.keys(this.all_shortcuts).forEach(shortcut => {
+ try {
+ this.remove(shortcut);
+ } catch (error) {
+ failures.push(shortcut);
+ console.error(`Failed to remove shortcut ${shortcut}: ${error}`);
+ }
+ });
+ if (failures.length > 0) {
+ console.warn(`Failed to remove ${failures.length} shortcuts: ${failures.join(', ')}`);
+ }
+ },
+
+ getOptions: function (opt?: ShortcutOptions): ShortcutOptions {
+ const default_options: ShortcutOptions = {
+ type: 'keydown',
+ propagate: false,
+ disable_in_input: true,
+ target: document,
+ keycode: false,
+ };
+ return opt ? { ...default_options, ...opt } : default_options;
+ },
+
+ getTargetElement: function (target: Document | string | undefined): Document | HTMLElement {
+ if (typeof target === 'string') {
+ return document.getElementById(target) || document;
+ }
+ return target || document;
+ },
+
+ createEventListener: function (shortcut_combination: string, callback: (e: KeyboardEvent) => void, options: ShortcutOptions): EventListener {
+ return (evt: Event): void => {
+ const e = evt as KeyboardEvent;
+
+ if (this.shouldIgnoreEvent(e, options)) {
+ return;
+ }
+
+ if (this.isShortcutMatch(shortcut_combination, e, options)) {
+ this.handleShortcutMatch(e, callback, options);
+ }
+ };
+ },
+
+ shouldIgnoreEvent: function (e: KeyboardEvent, options: ShortcutOptions): boolean {
+ return (options.disable_in_input ?? true) && this.isInputElement(e.target as HTMLElement);
+ },
+
+ handleShortcutMatch: function (e: KeyboardEvent, callback: (e: KeyboardEvent) => void, options: ShortcutOptions): void {
+ callback(e);
+
+ if (!options.propagate) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ },
+
+ isInputElement: function (element: HTMLElement): boolean {
+ if (element.nodeType === 3 && element.parentNode) {
+ element = element.parentNode as HTMLElement;
+ } else if (element.nodeType === 3) {
+ return true;
+ }
+ return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA';
+ },
+
+ isShortcutMatch: function (shortcut_combination: string, e: KeyboardEvent, options: ShortcutOptions): boolean {
+ const keys = shortcut_combination.split('+');
+ const modifiers = this.getModifiersState(keys, e);
+ const character = this.getCharacterFromKeyCode(e);
+
+ return this.checkKeysMatch(keys, character, e, options) &&
+ this.checkModifiersMatch(modifiers);
+ },
+
+ getModifiersState: function (keys: string[], e: KeyboardEvent): Record {
+ const modifiers: Record = {
+ shift: { wanted: false, pressed: e.shiftKey },
+ ctrl: { wanted: false, pressed: e.ctrlKey },
+ alt: { wanted: false, pressed: e.altKey },
+ meta: { wanted: false, pressed: e.metaKey }
+ };
+
+ keys.forEach(k => {
+ if (k === 'ctrl' || k === 'control') modifiers.ctrl.wanted = true;
+ else if (k === 'shift') modifiers.shift.wanted = true;
+ else if (k === 'alt') modifiers.alt.wanted = true;
+ else if (k === 'meta') modifiers.meta.wanted = true;
+ });
+
+ return modifiers;
+ },
+
+ getCharacterFromKeyCode: function (e: KeyboardEvent): string {
+ const code = e.keyCode || e.which;
+ let character = String.fromCharCode(code).toLowerCase();
+
+ if (code === 188) character = ',';
+ if (code === 190) character = '.';
+
+ return character;
+ },
+
+ checkKeysMatch: function (keys: string[], character: string, e: KeyboardEvent, options: ShortcutOptions): boolean {
+ let kp = 0;
+
+ keys.forEach(k => {
+ if (this.isModifierKey(k)) {
+ kp++;
+ } else if (this.isSpecialKeyMatch(k, e)) {
+ kp++;
+ } else if (options.keycode && this.isKeyCodeMatch(options.keycode, e)) {
+ kp++;
+ } else if (this.isCharacterMatch(k, character, e)) {
+ kp++;
+ }
+ });
+
+ return kp === keys.length;
+ },
+
+ isModifierKey: function (key: string): boolean {
+ return key === 'ctrl' || key === 'control' || key === 'shift' || key === 'alt' || key === 'meta';
+ },
+
+ isSpecialKeyMatch: function (key: string, e: KeyboardEvent): boolean {
+ const special_keys: Record = {
+ esc: 27, escape: 27, tab: 9, space: 32, return: 13, enter: 13, backspace: 8,
+ scrolllock: 145, scroll_lock: 145, scroll: 145, capslock: 20, caps_lock: 20, caps: 20,
+ numlock: 144, num_lock: 144, num: 144, pause: 19, break: 19, insert: 45, home: 36,
+ delete: 46, end: 35, pageup: 33, page_up: 33, pu: 33, pagedown: 34, page_down: 34, pd: 34,
+ left: 37, up: 38, right: 39, down: 40, f1: 112, f2: 113, f3: 114, f4: 115, f5: 116,
+ f6: 117, f7: 118, f8: 119, f9: 120, f10: 121, f11: 122, f12: 123
+ };
+
+ return special_keys[key] === (e.keyCode || e.which);
+ },
+
+ isKeyCodeMatch: function (keycode: number | false, e: KeyboardEvent): boolean {
+ return keycode === (e.keyCode || e.which);
+ },
+
+ isCharacterMatch: function (key: string, character: string, e: KeyboardEvent): boolean {
+ const shift_nums: Record = {
+ '`': '~', 1: '!', 2: '@', 3: '#', 4: '$', 5: '%', 6: '^', 7: '&', 8: '*', 9: '(', 0: ')',
+ '-': '_', '=': '+', ';': ':', "'": '"', ',': '<', '.': '>', '/': '?', '\\': '|'
+ };
+
+ if (character === key) {
+ return true;
+ } else if (shift_nums[character] && e.shiftKey) {
+ return shift_nums[character] === key;
+ }
+
+ return false;
+ },
+
+ checkModifiersMatch: function (modifiers: Record): boolean {
+ return modifiers.ctrl.pressed === modifiers.ctrl.wanted &&
+ modifiers.shift.pressed === modifiers.shift.wanted &&
+ modifiers.alt.pressed === modifiers.alt.wanted &&
+ modifiers.meta.pressed === modifiers.meta.wanted;
+ },
+
+ registerShortcut: function (shortcut_combination: string, func: EventListener, ele: Document | HTMLElement, event: string): void {
+ this.all_shortcuts[shortcut_combination] = {
+ callback: func,
+ target: ele,
+ event: event
+ };
+
+ if (ele.addEventListener) {
+ ele.addEventListener(event, func, false);
+ } else if ((ele as any).attachEvent) {
+ (ele as any).attachEvent('on' + event, func);
+ } else {
+ (ele as any)['on' + event] = func;
+ }
+ },
+
+ unregisterShortcut: function (binding: ShortcutBinding): void {
+ const { target, callback, event } = binding;
+
+ try {
+ if (target.removeEventListener) {
+ target.removeEventListener(event, callback);
+ } else if ((target as any).detachEvent) {
+ (target as any).detachEvent('on' + event, callback);
+ } else {
+ (target as any)['on' + event] = null;
+ }
+ } catch (error) {
+ console.warn(`Failed to remove event Listener: ${error}`);
+ }
+ }
+};
\ No newline at end of file
diff --git a/v1/src/simulator/src/hotkey_binder/model/utils.js b/v1/src/simulator/src/hotkey_binder/model/utils.js
deleted file mode 100644
index 8a2a8a8b..00000000
--- a/v1/src/simulator/src/hotkey_binder/model/utils.js
+++ /dev/null
@@ -1,67 +0,0 @@
-Storage.prototype.set = function (key, obj) {
- return this.setItem(key, JSON.stringify(obj))
-}
-
-Storage.prototype.get = function (key) {
- return JSON.parse(this.getItem(key))
-}
-
-Object.size = function (obj) {
- var size = 0,
- key
- for (key in obj) {
- if (obj.hasOwnProperty(key)) size++
- }
- return size
-}
-
-export const getKey = (obj, val) =>
- Object.keys(obj).find((key) => obj[key] === val)
-
-export const getOS = () => {
- let OSName = ''
- if (navigator.appVersion.indexOf('Win') != -1) OSName = 'Windows'
- if (navigator.appVersion.indexOf('Mac') != -1) OSName = 'MacOS'
- if (navigator.appVersion.indexOf('X11') != -1) OSName = 'UNIX'
- if (navigator.appVersion.indexOf('Linux') != -1) OSName = 'Linux'
- return OSName
-}
-
-export const checkRestricted = (key) => {
- const restrictedKeys = [
- 'Ctrl + N',
- 'Ctrl + W',
- 'Ctrl + T',
- 'Ctrl + C',
- 'Ctrl + V',
- 'Ctrl + Delete',
- 'Ctrl + Backspace',
- 'Ctrl + /',
- 'Ctrl + \\',
- 'Ctrl + ]',
- "Ctrl + '",
- 'Ctrl + `',
- 'Ctrl + [',
- 'Ctrl + ~',
- 'Ctrl + Num1',
- 'Ctrl + Num2',
- 'Ctrl + Num3',
- 'Ctrl + Num4',
- 'Ctrl + Num5',
- 'Ctrl + Num6',
- 'Ctrl + Num*',
- 'Ctrl + Num/',
- 'Ctrl + Num.',
- 'Ctrl + Num0',
- ]
- if (getOS == 'macOS') {
- restrictedKeys.forEach((value, i) => {
- if (value.split(' + ')[0] == 'Ctrl');
- restrictedKeys[i] =
- value.split(' + ')[0] == 'Ctrl'
- ? value.replace('Ctrl', 'Meta')
- : value
- })
- }
- return restrictedKeys.includes(key)
-}
diff --git a/v1/src/simulator/src/hotkey_binder/model/utils.ts b/v1/src/simulator/src/hotkey_binder/model/utils.ts
new file mode 100644
index 00000000..8e51b981
--- /dev/null
+++ b/v1/src/simulator/src/hotkey_binder/model/utils.ts
@@ -0,0 +1,74 @@
+// Add type-safe set method to Storage Prototype
+Storage.prototype.set = function(key: string, obj: T): void {
+ this.setItem(key, JSON.stringify(obj));
+}
+
+// Add type-safe get method to Storage prototype
+Storage.prototype.get = function(key: string): T | null {
+ const item = this.getItem(key);
+ if (!item) return null;
+ try {
+ return JSON.parse(item) as T;
+ } catch (e) {
+ console.error(`Failed to parse stored item ${key}:`, e);
+ return null;
+ }
+
+}
+
+// Type-safe object size function
+export function objectSize(obj: Record): number {
+ return Object.keys(obj).length;
+}
+
+// Find key by value in an object
+export function getKey>(obj: T, val: any): string | undefined {
+ return Object.keys(obj).find(key => {
+ const value = obj[key];
+ if (typeof value === 'object' && value !== null) {
+ return JSON.stringify(value) === JSON.stringify(val);
+ }
+ return value === val;
+ });
+}
+
+// OS detection patterns
+const OS_PATTERNS: Record = {
+ 'Windows': /windows/i,
+ 'MacOS': /mac/i,
+ 'Linux': /linux/i,
+ 'UNIX': /x11/i
+};
+export function getOS(): string {
+ const userInput = `${navigator.platform} ${navigator.userAgent}`.toLowerCase();
+
+ for (const [os, pattern] of Object.entries(OS_PATTERNS)) {
+ if (pattern.test(userInput)) {
+ return os;
+ }
+ }
+
+ return '';
+}
+// Check for restricted key combinations
+export function checkRestricted(key: string): boolean {
+ const restrictedKeys: string[] = [
+ 'Ctrl + N', 'Ctrl + W', 'Ctrl + T', 'Ctrl + C', 'Ctrl + V',
+ 'Ctrl + Delete', 'Ctrl + Backspace', 'Ctrl + /', 'Ctrl + \\',
+ 'Ctrl + ]', "Ctrl + '", 'Ctrl + `', 'Ctrl + [', 'Ctrl + ~',
+ 'Ctrl + Num1', 'Ctrl + Num2', 'Ctrl + Num3', 'Ctrl + Num4',
+ 'Ctrl + Num5', 'Ctrl + Num6', 'Ctrl + Num*', 'Ctrl + Num/',
+ 'Ctrl + Num.', 'Ctrl + Num0'
+ ];
+
+ // Adjust for MacOS if needed
+ const modifiedKeys = getOS() === 'MacOS'
+ ? restrictedKeys.map(value =>
+ value.startsWith('Ctrl')
+ ? value.replace('Ctrl', 'Meta')
+ : value
+ )
+ : restrictedKeys;
+
+ return modifiedKeys.includes(key);
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/interface/backgroundArea.ts b/v1/src/simulator/src/interface/backgroundArea.ts
new file mode 100644
index 00000000..e4d08e13
--- /dev/null
+++ b/v1/src/simulator/src/interface/backgroundArea.ts
@@ -0,0 +1,6 @@
+export interface BackgroundArea {
+ canvas: HTMLCanvasElement | null;
+ context: CanvasRenderingContext2D | null;
+ setup(): void;
+ clear(): void;
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/interface/simulationArea.ts b/v1/src/simulator/src/interface/simulationArea.ts
new file mode 100644
index 00000000..de181800
--- /dev/null
+++ b/v1/src/simulator/src/interface/simulationArea.ts
@@ -0,0 +1,39 @@
+import { EventQueue } from '../eventQueue'
+export interface SimulationArea {
+ canvas: HTMLCanvasElement;
+ context: CanvasRenderingContext2D|null;
+ selected: boolean;
+ hover: boolean;
+ clockState: number;
+ clockEnabled: boolean;
+ // TODO: make this CircuitElement|null once converted to typescript
+ lastSelected: any|null;
+ stack: any[];
+ prevScale: number;
+ oldx: number;
+ oldy: number;
+ objectList: any[];
+ maxHeight: number;
+ maxWidth: number;
+ minHeight: number;
+ minWidth: number;
+ multipleObjectSelections: any[];
+ copyList: any[];
+ shiftDown: boolean;
+ controlDown: boolean;
+ timePeriod: number;
+ mouseX: number;
+ mouseY: number;
+ mouseDownX: number;
+ mouseDownY: number;
+ simulationQueue: EventQueue;
+ clickCount: number;
+ lock: string;
+ mouseDown: boolean;
+ ClockInterval: NodeJS.Timeout|null;
+ touch: boolean;
+ timer: () => void;
+ setup: () => void;
+ changeClockTime: (t: number) => void;
+ clear: () => void;
+}
\ No newline at end of file
diff --git a/v0/src/simulator/src/layout/layoutBuffer.js b/v1/src/simulator/src/layout/layoutBuffer.ts
similarity index 87%
rename from v0/src/simulator/src/layout/layoutBuffer.js
rename to v1/src/simulator/src/layout/layoutBuffer.ts
index 1c339d28..c5705b77 100644
--- a/v0/src/simulator/src/layout/layoutBuffer.js
+++ b/v1/src/simulator/src/layout/layoutBuffer.ts
@@ -1,3 +1,4 @@
+import CircuitElement from '../circuitElement'
import LayoutNode from './layoutNode'
/**
* Buffer object to store changes so that you can reset changes
@@ -6,6 +7,18 @@ import LayoutNode from './layoutNode'
* @category layout
*/
export default class LayoutBuffer {
+ layout: {
+ width: number
+ height: number
+ x: number
+ y: number
+ title_x: number
+ title_y: number
+ titleEnabled: boolean
+ }
+ Input: LayoutNode[]
+ Output: LayoutNode[]
+ subElements: CircuitElement[]
constructor(scope = globalScope) {
var w = 300 * DPR
var h = 50 * DPR
@@ -53,7 +66,7 @@ export default class LayoutBuffer {
* Check if position is on the boundaries of subcircuit
* if the desired width and heiht is allowed
*/
- isAllowed(x, y) {
+ isAllowed(x: number, y: number) {
if (x < 0 || x > this.layout.width || y < 0 || y > this.layout.height)
return false
if (x > 0 && x < this.layout.width && y > 0 && y < this.layout.height)
@@ -76,7 +89,7 @@ export default class LayoutBuffer {
* Function is called while decreasing height to
* check if it is possible without moving other node
*/
- isNodeAt(x, y) {
+ isNodeAt(x: number, y: number) {
for (let i = 0; i < this.Input.length; i++) {
if (this.Input[i].x === x && this.Input[i].y === y) return true
}
diff --git a/v0/src/simulator/src/layout/layoutNode.js b/v1/src/simulator/src/layout/layoutNode.ts
similarity index 85%
rename from v0/src/simulator/src/layout/layoutNode.js
rename to v1/src/simulator/src/layout/layoutNode.ts
index ddf199b3..33d55d4f 100644
--- a/v0/src/simulator/src/layout/layoutNode.js
+++ b/v1/src/simulator/src/layout/layoutNode.ts
@@ -1,21 +1,28 @@
import { drawCircle } from '../canvasApi'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { tempBuffer } from '../layoutMode'
+import CircuitElement from '../circuitElement'
/**
- * @class
- * @param {number} x - x coord of node
- * @param {number} y - y coord of node
- * @param {strng} id - id for node
- * @param {string=} label - label for the node
- * @param {number} xx - parent x
- * @param {number} yy - parent y
- * @param {number} type - input or output node
- * @param {CircuitElement} parent parent of the node
* @category layout
*/
export default class LayoutNode {
- constructor(x, y, id, label = '', type, parent) {
+ x: number
+ y: number
+ prevx: number | undefined
+ prevy: number | undefined
+ radius: number
+ clicked: boolean
+ hover: boolean
+ wasClicked: boolean
+ prev: string
+ count: number
+ objectType: string
+ type: number
+ id: string
+ label: string
+ parent: CircuitElement
+ constructor(x: number, y: number, id: string, label = '', type: number, parent: CircuitElement) {
this.type = type
this.id = id
diff --git a/v1/src/simulator/src/layoutMode.js b/v1/src/simulator/src/layoutMode.ts
similarity index 83%
rename from v1/src/simulator/src/layoutMode.js
rename to v1/src/simulator/src/layoutMode.ts
index c400cb71..5c548db6 100644
--- a/v1/src/simulator/src/layoutMode.js
+++ b/v1/src/simulator/src/layoutMode.ts
@@ -2,9 +2,8 @@
/* eslint-disable no-continue */
import { dots, correctWidth, fillText, rect2 } from './canvasApi'
import LayoutBuffer from './layout/layoutBuffer'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import {
- hideProperties,
fillSubcircuitElements,
prevPropertyObjGet,
prevPropertyObjSet,
@@ -19,8 +18,11 @@ import {
} from './engine'
import miniMapArea from './minimap'
import { showMessage } from './utils'
-import * as metadata from './metadata.json'
-import { verilogModeGet, verilogModeSet } from './Verilog2CV'
+import { verilogModeSet } from './Verilog2CV'
+import { useLayoutStore } from '#/store/layoutStore'
+import { useSimulatorMobileStore } from '#/store/simulatorMobileStore'
+import { toRefs } from 'vue'
+import { circuitElementList } from './metadata'
/**
* Layout.js - all subcircuit layout related code is here
@@ -31,11 +33,11 @@ import { verilogModeGet, verilogModeSet } from './Verilog2CV'
var layoutMode = false
-export function layoutModeSet(param) {
+export function layoutModeSet(param: boolean) {
layoutMode = param
}
-export function layoutModeGet(param) {
+export function layoutModeGet() {
return layoutMode
}
@@ -43,15 +45,13 @@ export function layoutModeGet(param) {
* @type {LayoutBuffer} - used to temporartily store all changes.
* @category layoutMode
*/
-export var tempBuffer
+export var tempBuffer: LayoutBuffer
/**
* Helper function to determine alignment and position of nodes for rendering
- * @param {number} x - width of label
- * @param {number} y - height of label
* @category layoutMode
*/
-export function determineLabel(x, y) {
+export function determineLabel(x: number, y: number) {
if (x === 0) return ['left', 5, 5]
if (x === tempBuffer.layout.width) return ['right', -5, 5]
if (y === 0) return ['center', 0, 13]
@@ -148,8 +148,8 @@ export function renderLayout(scope = globalScope) {
fillText(
ctx,
tempBuffer.Input[i].label,
- tempBuffer.Input[i].x + info[1],
- tempBuffer.Input[i].y + info[2],
+ tempBuffer.Input[i].x + typeof info[1] === 'number' ? info[1] : parseInt(info[1] as string),
+ tempBuffer.Input[i].y + typeof info[2] === 'number' ? info[2] : parseInt(info[2] as string),
12
)
}
@@ -164,8 +164,8 @@ export function renderLayout(scope = globalScope) {
fillText(
ctx,
tempBuffer.Output[i].label,
- tempBuffer.Output[i].x + info[1],
- tempBuffer.Output[i].y + info[2],
+ tempBuffer.Output[i].x + typeof info[1] === 'number' ? info[1] : parseInt(info[1] as string),
+ tempBuffer.Output[i].y + typeof info[2] === 'number' ? info[2] : parseInt(info[2] as string),
12
)
}
@@ -446,29 +446,25 @@ export function saveLayout() {
* @category layoutMode
*/
export function toggleLayoutMode() {
- // hideProperties()
- // lines from hideProperty function() <---
+ const layoutStore = toRefs(useLayoutStore())
+ const simulatorMobileStore = toRefs(useSimulatorMobileStore())
prevPropertyObjSet(undefined)
$('.objectPropertyAttribute').unbind('change keyup paste click')
if (layoutModeGet()) {
layoutModeSet(false)
- $('#layoutDialog').fadeOut()
- $('.layoutElementPanel').fadeOut()
- $('.elementPanel').fadeIn()
- $('.timing-diagram-panel').fadeIn()
- $('.testbench-manual-panel').fadeIn()
+ layoutStore.layoutMode.value = false
globalScope.centerFocus(false)
- if (globalScope.verilogMetadata.isVerilogCircuit) verilogModeSet(true)
+ if (globalScope.verilogMetadata.isVerilogCircuit) {
+ verilogModeSet(true)
+ simulatorMobileStore.isVerilog.value = true
+ }
dots()
} else {
layoutModeSet(true)
verilogModeSet(false)
- $('#layoutDialog').fadeIn()
- $('.layoutElementPanel').fadeIn()
- $('.elementPanel').fadeOut()
- $('.timing-diagram-panel').fadeOut()
- $('.testbench-manual-panel').fadeOut()
+ layoutStore.layoutMode.value = true
+ simulatorMobileStore.isVerilog.value = false
fillSubcircuitElements()
globalScope.ox = 0
@@ -476,7 +472,6 @@ export function toggleLayoutMode() {
globalScope.scale = DPR * 1.3
dots()
tempBuffer = new LayoutBuffer()
- // $('#toggleLayoutTitle')[0].checked = tempBuffer.layout.titleEnabled
}
update(globalScope, true)
scheduleUpdate()
@@ -497,48 +492,3 @@ export const layoutFunctions = {
saveLayout,
toggleLayoutMode,
}
-
-// export function setupLayoutModePanelListeners() {
-// $('#decreaseLayoutWidth').on('click', () => {
-// decreaseLayoutWidth()
-// })
-// $('#increaseLayoutWidth').on('click', () => {
-// increaseLayoutWidth()
-// })
-// $('#decreaseLayoutHeight').on('click', () => {
-// decreaseLayoutHeight()
-// })
-// $('#increaseLayoutHeight').on('click', () => {
-// increaseLayoutHeight()
-// })
-// $('#layoutResetNodes').on('click', () => {
-// layoutResetNodes()
-// })
-// $('#layoutTitleUp').on('click', () => {
-// layoutTitleUp()
-// })
-// $('#layoutTitleDown').on('click', () => {
-// layoutTitleDown()
-// })
-// $('#layoutTitleLeft').on('click', () => {
-// layoutTitleLeft()
-// })
-// $('#layoutTitleRight').on('click', () => {
-// layoutTitleRight()
-// })
-// $('#toggleLayoutTitle').on('click', () => {
-// toggleLayoutTitle()
-// })
-// $('#saveLayout').on('click', () => {
-// saveLayout()
-// })
-// $('#cancelLayout').on('click', () => {
-// cancelLayout()
-// })
-// $('#layoutDialog button').on('click', () => {
-// scheduleUpdate()
-// })
-// $('#layoutDialog input').on('click', () => {
-// scheduleUpdate()
-// })
-// }
diff --git a/v1/src/simulator/src/listeners.js b/v1/src/simulator/src/listeners.js
index 460be076..6db5661a 100644
--- a/v1/src/simulator/src/listeners.js
+++ b/v1/src/simulator/src/listeners.js
@@ -1,11 +1,18 @@
+/* eslint-disable no-shadow */
+/* eslint-disable no-negated-condition */
+/* eslint-disable no-alert */
+/* eslint-disable new-cap */
+/* eslint-disable no-undef */
+/* eslint-disable eqeqeq */
+/* eslint-disable prefer-template */
+/* eslint-disable no-param-reassign */
// Most Listeners are stored here
import {
layoutModeGet,
tempBuffer,
layoutUpdate,
- // setupLayoutModePanelListeners,
} from './layoutMode'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import {
scheduleUpdate,
update,
@@ -17,127 +24,298 @@ import {
gridUpdateSet,
errorDetectedSet,
} from './engine'
-import { changeScale } from './canvasApi'
+import { changeScale, findDimensions } from './canvasApi'
import { scheduleBackup } from './data/backupCircuit'
-import {
- hideProperties,
- deleteSelected,
- uxvar,
- fullView,
- exitFullView,
-} from './ux'
-import {
- updateRestrictedElementsList,
- updateRestrictedElementsInScope,
- hideRestricted,
- showRestricted,
-} from './restrictedElementDiv'
+import { hideProperties, deleteSelected, uxvar, exitFullView } from './ux';
+import { updateRestrictedElementsList, updateRestrictedElementsInScope, hideRestricted, showRestricted } from './restrictedElementDiv';
import { removeMiniMap, updatelastMinimapShown } from './minimap'
import undo from './data/undo'
import redo from './data/redo'
import { copy, paste, selectAll } from './events'
-import save from './data/save'
import { verilogModeGet } from './Verilog2CV'
import { setupTimingListeners } from './plotArea'
+import logixFunction from './data'
+import { listen } from '@tauri-apps/api/event'
+import { useSimulatorMobileStore } from '#/store/simulatorMobileStore'
+import { toRefs } from 'vue'
+
+const unit = 10
+let listenToSimulator = true
+let coordinate;
+const returnCoordinate = {
+ x: 0,
+ y: 0
+}
-var unit = 10
-var listenToSimulator = true
+let currDistance = 0;
+let distance = 0;
+let pinchZ = 0;
+let centreX;
+let centreY;
+let timeout;
+let lastTap = 0;
+
+/**
+ *
+ * @param {event} e
+ * function for double click or double tap
+ */
+function onDoubleClickorTap(e) {
+ updateCanvasSet(true);
+ if (simulationArea.lastSelected && simulationArea.lastSelected.dblclick !== undefined) {
+ simulationArea.lastSelected.dblclick();
+ } else if (!simulationArea.shiftDown) {
+ simulationArea.multipleObjectSelections = [];
+ }
+ scheduleUpdate(2);
+ e.preventDefault();
+}
-export default function startListeners() {
- // added the below functionalities in QuickButton.vue component local script tag part
-
- // $('#deleteSelected').on('click', () => {
- // deleteSelected()
- // })
-
- // $('#zoomIn').on('click', () => {
- // changeScale(0.2, 'zoomButton', 'zoomButton', 2)
- // })
-
- // $('#zoomOut').on('click', () => {
- // changeScale(-0.2, 'zoomButton', 'zoomButton', 2)
- // })
-
- // $('#undoButton').on('click', () => {
- // undo()
- // })
- // $('#redoButton').on('click', () => {
- // redo()
- // })
- // $('#viewButton').on('click', () => {
- // fullView()
- // })
+/**
+ *
+ * @param {event} e
+ * function to detect tap and double tap
+ */
+function getTap(e) {
+ const currentTime = new Date().getTime();
+ const tapLength = currentTime - lastTap;
+ clearTimeout(timeout);
+ if (tapLength < 500 && tapLength > 0) {
+ onDoubleClickorTap(e);
+ } else {
+ // Single tap
+ }
+ lastTap = currentTime;
+ e.preventDefault();
+}
+
+const isIe = (navigator.userAgent.toLowerCase().indexOf('msie') != -1 || navigator.userAgent.toLowerCase().indexOf('trident') != -1);
+
+// Function to getCoordinate
+// *If touch is enable then it will return touch coordinate
+// *else it will return mouse coordinate
+//
+export function getCoordinate(e) {
+ if (simulationArea.touch) {
+ returnCoordinate.x = e.touches[0].clientX;
+ returnCoordinate.y = e.touches[0].clientY;
+ return returnCoordinate;
+ }
+
+ if (!simulationArea.touch) {
+ returnCoordinate.x = e.clientX;
+ returnCoordinate.y = e.clientY;
+ return returnCoordinate;
+ }
+
+ return returnCoordinate;
+}
+
+/* Function for Panstop on simulator
+ *For now variable name starts with mouse like mouseDown are used both
+ touch and mouse will change in future
+*/
+export function pinchZoom(e, globalScope) {
+ e.preventDefault();
+ gridUpdateSet(true);
+ scheduleUpdate();
+ updateSimulationSet(true);
+ updatePositionSet(true);
+ updateCanvasSet(true);
+ // Calculating distance between touch to see if its pinchIN or pinchOut
+ distance = Math.sqrt((e.touches[1].clientX - e.touches[0].clientX) ** 2, (e.touches[1].clientY - e.touches[0].clientY) ** 2);
+ if (distance >= currDistance) {
+ pinchZ += 0.02;
+ currDistance = distance;
+ } else if (currDistance >= distance) {
+ pinchZ -= 0.02;
+ currDistance = distance;
+ }
+ if (pinchZ >= 2) {
+ pinchZ = 2;
+ }
+ else if (pinchZ <= 0.5) {
+ pinchZ = 0.5;
+ }
+ const oldScale = globalScope.scale;
+ globalScope.scale = Math.max(0.5, Math.min(4 * DPR, pinchZ * 3));
+ globalScope.scale = Math.round(globalScope.scale * 10) / 10;
+ // This is not working as expected
+ centreX = (e.touches[0].clientX + e.touches[1].clientX) / 2;
+ centreY = (e.touches[0].clientY + e.touches[1].clientY) / 2;
+ const rect = simulationArea.canvas.getBoundingClientRect();
+ const RawX = (centreX - rect.left) * DPR;
+ const RawY = (centreY - rect.top) * DPR;
+ const Xf = Math.round(((RawX - globalScope.ox) / globalScope.scale) / unit);
+ const Yf = Math.round(((RawY - globalScope.ox) / globalScope.scale) / unit);
+ const currCentreX = Math.round(Xf / unit) * unit;
+ const currCentreY = Math.round(Yf / unit) * unit;
+ globalScope.ox = Math.round(currCentreX * (globalScope.scale - oldScale));
+ globalScope.oy = Math.round(currCentreY * (globalScope.scale - oldScale));
+ gridUpdateSet(true);
+ scheduleUpdate(1);
+}
+
+/*
+ *Function to start the pan in simulator
+ *Works for both touch and Mouse
+ *For now variable name starts from mouse like mouseDown are used both
+ touch and mouse will change in future
+ */
+export function panStart(e) {
+ coordinate = getCoordinate(e);
+ simulationArea.mouseDown = true;
+ // Deselect Input
+ if (document.activeElement instanceof HTMLElement) {
+ document.activeElement.blur();
+ }
+
+ errorDetectedSet(false);
+ updateSimulationSet(true);
+ updatePositionSet(true);
+ updateCanvasSet(true);
+ simulationArea.lastSelected = undefined;
+ simulationArea.selected = false;
+ simulationArea.hover = undefined;
+ const rect = simulationArea.canvas.getBoundingClientRect();
+ simulationArea.mouseDownRawX = (coordinate.x - rect.left) * DPR;
+ simulationArea.mouseDownRawY = (coordinate.y - rect.top) * DPR;
+ simulationArea.mouseDownX = Math.round(((simulationArea.mouseDownRawX - globalScope.ox) / globalScope.scale) / unit) * unit;
+ simulationArea.mouseDownY = Math.round(((simulationArea.mouseDownRawY - globalScope.oy) / globalScope.scale) / unit) * unit;
+ if (simulationArea.touch) {
+ simulationArea.mouseX = simulationArea.mouseDownX;
+ simulationArea.mouseY = simulationArea.mouseDownY;
+ }
+
+ simulationArea.oldx = globalScope.ox;
+ simulationArea.oldy = globalScope.oy;
+ e.preventDefault();
+ scheduleBackup();
+ scheduleUpdate(1);
+ $('.dropdown.open').removeClass('open');
+}
+
+/*
+ * Function to pan in simulator
+ * Works for both touch and Mouse
+ * Pinch to zoom also implemented in the same
+ * For now variable name starts from mouse like mouseDown are used both
+ touch and mouse will change in future
+ */
+
+export function panMove(e) {
+ // If only one it touched
+ // pan left or right
+ if (!simulationArea.touch || e.touches.length === 1) {
+ coordinate = getCoordinate(e);
+ const rect = simulationArea.canvas.getBoundingClientRect();
+ simulationArea.mouseRawX = (coordinate.x - rect.left) * DPR;
+ simulationArea.mouseRawY = (coordinate.y - rect.top) * DPR;
+ simulationArea.mouseXf = (simulationArea.mouseRawX - globalScope.ox) / globalScope.scale;
+ simulationArea.mouseYf = (simulationArea.mouseRawY - globalScope.oy) / globalScope.scale;
+ simulationArea.mouseX = Math.round(simulationArea.mouseXf / unit) * unit;
+ simulationArea.mouseY = Math.round(simulationArea.mouseYf / unit) * unit;
+ updateCanvasSet(true);
+ if (simulationArea.lastSelected && (simulationArea.mouseDown || simulationArea.lastSelected.newElement)) {
+ updateCanvasSet(true);
+ let fn;
+
+ if (simulationArea.lastSelected == globalScope.root) {
+ fn = function () {
+ updateSelectionsAndPane();
+ };
+ } else {
+ fn = function () {
+ if (simulationArea.lastSelected) {
+ simulationArea.lastSelected.update();
+ }
+ };
+ }
+
+ scheduleUpdate(0, 20, fn);
+ } else {
+ scheduleUpdate(0, 200);
+ }
+ }
+ // If two fingures are touched
+ // pinchZoom
+ if (simulationArea.touch && e.touches.length === 2) {
+ pinchZoom(e, globalScope);
+ }
+}
+
+export function panStop(e) {
+ const simulatorMobileStore = useSimulatorMobileStore()
+ simulationArea.mouseDown = false;
+ if (!lightMode) {
+ updatelastMinimapShown();
+ setTimeout(removeMiniMap, 2000);
+ }
+
+ errorDetectedSet(false);
+ updateSimulationSet(true);
+ updatePositionSet(true);
+ updateCanvasSet(true);
+ gridUpdateSet(true);
+ wireToBeCheckedSet(1);
+
+ scheduleUpdate(1);
+ simulationArea.mouseDown = false;
+
+ // eslint-disable-next-line no-plusplus
+ for (let i = 0; i < 2; i++) {
+ updatePositionSet(true);
+ wireToBeCheckedSet(1);
+ update();
+ }
+
+ errorDetectedSet(false);
+ updateSimulationSet(true);
+ updatePositionSet(true);
+ updateCanvasSet(true);
+ gridUpdateSet(true);
+ wireToBeCheckedSet(1);
+
+ scheduleUpdate(1);
+ // Var rect = simulationArea.canvas.getBoundingClientRect();
+
+ if (!(simulationArea.mouseRawX < 0 || simulationArea.mouseRawY < 0 || simulationArea.mouseRawX > width || simulationArea.mouseRawY > height)) {
+ uxvar.smartDropXX = simulationArea.mouseX + 100; // Math.round(((simulationArea.mouseRawX - globalScope.ox+100) / globalScope.scale) / unit) * unit;
+ uxvar.smartDropYY = simulationArea.mouseY - 50; // Math.round(((simulationArea.mouseRawY - globalScope.oy+100) / globalScope.scale) / unit) * unit;
+ }
+
+ if (simulationArea.touch) {
+ const { isCopy } = toRefs(simulatorMobileStore)
+ // small hack so Current circuit element should not spwan above last circuit element
+ if (!isCopy.value) {
+ findDimensions(globalScope);
+ simulationArea.mouseX = 100 + simulationArea.maxWidth || 0;
+ simulationArea.mouseY = simulationArea.minHeight || 0;
+ getTap(e);
+ }
+ }
+}
+
+export default function startListeners() {
$(document).on('keyup', (e) => {
if (e.key === 'Escape') exitFullView()
})
$('#projectName').on('click', () => {
- simulationArea.lastSelected = globalScope.root
- setTimeout(() => {
- document.getElementById('projname').select()
- }, 100)
- })
- /* Makes tabs reordering possible by making them sortable */
- // $("#tabsBar").sortable({
- // containment: 'parent',
- // items: '> div',
- // revert: false,
- // opacity: 0.5,
- // tolerance: 'pointer',
- // placeholder: 'placeholder',
- // forcePlaceholderSize: true,
- // });
+ simulationArea.lastSelected = globalScope.root;
+ setTimeout(() => {
+ document.getElementById("projname").select();
+ }, 100);
+ });
- document
- .getElementById('simulationArea')
- .addEventListener('mousedown', (e) => {
- simulationArea.mouseDown = true
-
- // Deselect Input
- if (document.activeElement instanceof HTMLElement)
- document.activeElement.blur()
-
- errorDetectedSet(false)
- updateSimulationSet(true)
- updatePositionSet(true)
- updateCanvasSet(true)
-
- simulationArea.lastSelected = undefined
- simulationArea.selected = false
- simulationArea.hover = undefined
- var rect = simulationArea.canvas.getBoundingClientRect()
- simulationArea.mouseDownRawX = (e.clientX - rect.left) * DPR
- simulationArea.mouseDownRawY = (e.clientY - rect.top) * DPR
- simulationArea.mouseDownX =
- Math.round(
- (simulationArea.mouseDownRawX - globalScope.ox) /
- globalScope.scale /
- unit
- ) * unit
- simulationArea.mouseDownY =
- Math.round(
- (simulationArea.mouseDownRawY - globalScope.oy) /
- globalScope.scale /
- unit
- ) * unit
- simulationArea.oldx = globalScope.ox
- simulationArea.oldy = globalScope.oy
-
- e.preventDefault()
- scheduleBackup()
- scheduleUpdate(1)
- $('.dropdown.open').removeClass('open')
- })
document
.getElementById('simulationArea')
.addEventListener('mouseup', (e) => {
- if (simulationArea.lastSelected)
+ if (simulationArea.lastSelected) {
simulationArea.lastSelected.newElement = false
- /*
- handling restricted circuit elements
- */
-
+ }
+ // handling restricted circuit elements
if (
simulationArea.lastSelected &&
restrictedElements.includes(
@@ -153,7 +331,7 @@ export default function startListeners() {
updateRestrictedElementsList()
}
- // deselect multible elements with click
+ // deselect multible elements with click
if (
!simulationArea.shiftDown &&
simulationArea.multipleObjectSelections.length > 0
@@ -167,9 +345,6 @@ export default function startListeners() {
}
}
})
- document
- .getElementById('simulationArea')
- .addEventListener('mousemove', onMouseMove)
window.addEventListener('keyup', (e) => {
scheduleUpdate(1)
@@ -220,10 +395,6 @@ export default function startListeners() {
if (listenToSimulator) {
// If mouse is focusing on input element, then override any action
- // if($(':focus').length){
- // return;
- // }
-
if (
document.activeElement.tagName == 'INPUT' ||
simulationArea.mouseRawX < 0 ||
@@ -279,18 +450,6 @@ export default function startListeners() {
updateCanvasSet(true)
wireToBeCheckedSet(1)
- // Needs to be deprecated, moved to more recent listeners
- if (
- simulationArea.controlDown &&
- (e.key == 'C' || e.key == 'c')
- ) {
- // simulationArea.copyList=simulationArea.multipleObjectSelections.slice();
- // if(simulationArea.lastSelected&&simulationArea.lastSelected!==simulationArea.root&&!simulationArea.copyList.contains(simulationArea.lastSelected)){
- // simulationArea.copyList.push(simulationArea.lastSelected);
- // }
- // copy(simulationArea.copyList);
- }
-
if (
simulationArea.lastSelected &&
simulationArea.lastSelected.keyDown
@@ -344,7 +503,7 @@ export default function startListeners() {
simulationArea.lastSelected.objectType != 'Wire' &&
simulationArea.lastSelected.objectType !=
'CircuitElement' &&
- !simulationArea.multipleObjectSelections.contains(
+ !simulationArea.multipleObjectSelections.includes(
simulationArea.lastSelected
)
) {
@@ -407,31 +566,9 @@ export default function startListeners() {
true
)
- document
- .getElementById('simulationArea')
- .addEventListener('dblclick', (e) => {
- updateCanvasSet(true)
- if (
- simulationArea.lastSelected &&
- simulationArea.lastSelected.dblclick !== undefined
- ) {
- simulationArea.lastSelected.dblclick()
- } else if (!simulationArea.shiftDown) {
- simulationArea.multipleObjectSelections = []
- }
- scheduleUpdate(2)
- })
-
- document
- .getElementById('simulationArea')
- .addEventListener('mouseup', onMouseUp)
-
- document
- .getElementById('simulationArea')
- .addEventListener('mousewheel', MouseScroll)
- document
- .getElementById('simulationArea')
- .addEventListener('DOMMouseScroll', MouseScroll)
+ document.getElementById('simulationArea').addEventListener('dblclick', e => {
+ onDoubleClickorTap(e);
+ });
function MouseScroll(event) {
updateCanvasSet(true)
@@ -448,6 +585,13 @@ export default function startListeners() {
else update() // Schedule update not working, this is INEFFICIENT
}
+ document
+ .getElementById('simulationArea')
+ .addEventListener('mousewheel', MouseScroll)
+ document
+ .getElementById('simulationArea')
+ .addEventListener('DOMMouseScroll', MouseScroll)
+
document.addEventListener('cut', (e) => {
if (verilogModeGet()) return
if (document.activeElement.tagName == 'INPUT') return
@@ -459,12 +603,12 @@ export default function startListeners() {
if (
simulationArea.lastSelected &&
simulationArea.lastSelected !== simulationArea.root &&
- !simulationArea.copyList.contains(simulationArea.lastSelected)
+ !simulationArea.copyList.includes(simulationArea.lastSelected)
) {
simulationArea.copyList.push(simulationArea.lastSelected)
}
- var textToPutOnClipboard = copy(simulationArea.copyList, true)
+ const textToPutOnClipboard = copy(simulationArea.copyList, true)
// Updated restricted elements
updateRestrictedElementsInScope()
@@ -490,12 +634,12 @@ export default function startListeners() {
if (
simulationArea.lastSelected &&
simulationArea.lastSelected !== simulationArea.root &&
- !simulationArea.copyList.contains(simulationArea.lastSelected)
+ !simulationArea.copyList.includes(simulationArea.lastSelected)
) {
simulationArea.copyList.push(simulationArea.lastSelected)
}
- var textToPutOnClipboard = copy(simulationArea.copyList)
+ const textToPutOnClipboard = copy(simulationArea.copyList)
// Updated restricted elements
updateRestrictedElementsInScope()
@@ -532,33 +676,25 @@ export default function startListeners() {
})
// 'drag and drop' event listener for subcircuit elements in layout mode
- $('#subcircuitMenu').on(
- 'dragstop',
- '.draggableSubcircuitElement',
- function (event, ui) {
- const sideBarWidth = $('#guide_1')[0].clientWidth
- let tempElement
-
- if (ui.position.top > 10 && ui.position.left > sideBarWidth) {
- // make a shallow copy of the element with the new coordinates
- tempElement =
- globalScope[this.dataset.elementName][
- this.dataset.elementId
- ]
-
- // Changing the coordinate doesn't work yet, nodes get far from element
- tempElement.x = ui.position.left - sideBarWidth
- tempElement.y = ui.position.top
- for (let node of tempElement.nodeList) {
- node.x = ui.position.left - sideBarWidth
- node.y = ui.position.top
- }
-
- tempBuffer.subElements.push(tempElement)
- this.parentElement.removeChild(this)
+ $('#subcircuitMenu').on('dragstop', '.draggableSubcircuitElement', function (event, ui) {
+ const sideBarWidth = $('#guide_1')[0].clientWidth;
+ let tempElement;
+
+ if (ui.position.top > 10 && ui.position.left > sideBarWidth) {
+ // Make a shallow copy of the element with the new coordinates
+ tempElement = globalScope[this.dataset.elementName][this.dataset.elementId];
+ // Changing the coordinate doesn't work yet, nodes get far from element
+ tempElement.x = ui.position.left - sideBarWidth;
+ tempElement.y = ui.position.top;
+ for (const node of tempElement.nodeList) {
+ node.x = ui.position.left - sideBarWidth;
+ node.y = ui.position.top;
}
+
+ tempBuffer.subElements.push(tempElement);
+ this.parentElement.removeChild(this);
}
- )
+ });
restrictedElements.forEach((element) => {
$(`#${element}`).mouseover(() => {
@@ -571,102 +707,15 @@ export default function startListeners() {
})
zoomSliderListeners()
- // setupLayoutModePanelListeners()
if (!embed) {
setupTimingListeners()
}
}
-var isIe =
- navigator.userAgent.toLowerCase().indexOf('msie') != -1 ||
- navigator.userAgent.toLowerCase().indexOf('trident') != -1
-
-function onMouseMove(e) {
- var rect = simulationArea.canvas.getBoundingClientRect()
- simulationArea.mouseRawX = (e.clientX - rect.left) * DPR
- simulationArea.mouseRawY = (e.clientY - rect.top) * DPR
- simulationArea.mouseXf =
- (simulationArea.mouseRawX - globalScope.ox) / globalScope.scale
- simulationArea.mouseYf =
- (simulationArea.mouseRawY - globalScope.oy) / globalScope.scale
- simulationArea.mouseX = Math.round(simulationArea.mouseXf / unit) * unit
- simulationArea.mouseY = Math.round(simulationArea.mouseYf / unit) * unit
-
- updateCanvasSet(true)
-
- if (
- simulationArea.lastSelected &&
- (simulationArea.mouseDown || simulationArea.lastSelected.newElement)
- ) {
- updateCanvasSet(true)
- var fn
-
- if (simulationArea.lastSelected == globalScope.root) {
- fn = function () {
- updateSelectionsAndPane()
- }
- } else {
- fn = function () {
- if (simulationArea.lastSelected) {
- simulationArea.lastSelected.update()
- }
- }
- }
- scheduleUpdate(0, 20, fn)
- } else {
- scheduleUpdate(0, 200)
- }
-}
-
-function onMouseUp(e) {
- simulationArea.mouseDown = false
- if (!lightMode) {
- updatelastMinimapShown()
- setTimeout(removeMiniMap, 2000)
- }
-
- errorDetectedSet(false)
- updateSimulationSet(true)
- updatePositionSet(true)
- updateCanvasSet(true)
- gridUpdateSet(true)
- wireToBeCheckedSet(1)
-
- scheduleUpdate(1)
- simulationArea.mouseDown = false
-
- for (var i = 0; i < 2; i++) {
- updatePositionSet(true)
- wireToBeCheckedSet(1)
- update()
- }
- errorDetectedSet(false)
- updateSimulationSet(true)
- updatePositionSet(true)
- updateCanvasSet(true)
- gridUpdateSet(true)
- wireToBeCheckedSet(1)
-
- scheduleUpdate(1)
- var rect = simulationArea.canvas.getBoundingClientRect()
-
- if (
- !(
- simulationArea.mouseRawX < 0 ||
- simulationArea.mouseRawY < 0 ||
- simulationArea.mouseRawX > width ||
- simulationArea.mouseRawY > height
- )
- ) {
- uxvar.smartDropXX = simulationArea.mouseX + 100 // Math.round(((simulationArea.mouseRawX - globalScope.ox+100) / globalScope.scale) / unit) * unit;
- uxvar.smartDropYY = simulationArea.mouseY - 50 // Math.round(((simulationArea.mouseRawY - globalScope.oy+100) / globalScope.scale) / unit) * unit;
- }
-}
-
function resizeTabs() {
- var $windowsize = $('body').width()
- var $sideBarsize = $('.side').width()
- var $maxwidth = $windowsize - $sideBarsize
+ const $windowsize = $('body').width()
+ const $sideBarsize = $('.side').width()
+ const $maxwidth = $windowsize - $sideBarsize
$('#tabsBar div').each(function (e) {
$(this).css({ 'max-width': $maxwidth - 30 })
})
@@ -675,87 +724,156 @@ function resizeTabs() {
window.addEventListener('resize', resizeTabs)
resizeTabs()
-// $(() => {
-// $('[data-toggle="tooltip"]').tooltip()
-// })
-
// direction is only 1 or -1
-function handleZoom(direction) {
- var zoomSlider = $('#customRange1')
- var currentSliderValue = parseInt(zoomSlider.val(), 10)
- currentSliderValue += direction
-
+function handleZoom (direction) {
if (globalScope.scale > 0.5 * DPR) {
- zoomSlider.val(currentSliderValue).change()
+ changeScale(direction * 0.1 * DPR);
} else if (globalScope.scale < 4 * DPR) {
- zoomSlider.val(currentSliderValue).change()
+ changeScale(direction * 0.1 * DPR);
}
-
- gridUpdateSet(true)
- scheduleUpdate()
-}
-
-export function ZoomIn() {
- handleZoom(1)
-}
-
-export function ZoomOut() {
- handleZoom(-1)
-}
-
-function zoomSliderListeners() {
- document.getElementById('customRange1').value = 5
- document
- .getElementById('simulationArea')
- .addEventListener('DOMMouseScroll', zoomSliderScroll)
- document
- .getElementById('simulationArea')
- .addEventListener('mousewheel', zoomSliderScroll)
- let curLevel = document.getElementById('customRange1').value
+ gridUpdateSet(true);
+ scheduleUpdate();
+ }
+ export function ZoomIn () {
+ handleZoom(1);
+ }
+ export function ZoomOut () {
+ handleZoom(-1);
+ }
+ function zoomSliderListeners () {
+ document.getElementById("customRange1").value = 5;
+ document.getElementById('simulationArea').addEventListener('DOMMouseScroll', zoomSliderScroll);
+ document.getElementById('simulationArea').addEventListener('mousewheel', zoomSliderScroll);
+ let curLevel = document.getElementById("customRange1").value;
$(document).on('input change', '#customRange1', function (e) {
- let newValue = $(this).val()
- let changeInScale = newValue - curLevel
- updateCanvasSet(true)
- changeScale(changeInScale * 0.1, 'zoomButton', 'zoomButton', 3)
- gridUpdateSet(true)
- curLevel = newValue
- })
- function zoomSliderScroll(e) {
- let zoomLevel = document.getElementById('customRange1').value
- let deltaY = e.wheelDelta ? e.wheelDelta : -e.detail
- const directionY = deltaY > 0 ? 1 : -1
- if (directionY > 0) zoomLevel++
- else zoomLevel--
- if (zoomLevel >= 45) {
- zoomLevel = 45
- document.getElementById('customRange1').value = 45
- } else if (zoomLevel <= 0) {
- zoomLevel = 0
- document.getElementById('customRange1').value = 0
- } else {
- document.getElementById('customRange1').value = zoomLevel
- curLevel = zoomLevel
- }
+ const newValue = $(this).val();
+ const changeInScale = newValue - curLevel;
+ updateCanvasSet(true);
+ changeScale(changeInScale * 0.1, 'zoomButton', 'zoomButton', 3)
+ gridUpdateSet(true);
+ curLevel = newValue;
+ });
+ function zoomSliderScroll (e) {
+ let zoomLevel = document.getElementById("customRange1").value;
+ const deltaY = e.wheelDelta ? e.wheelDelta : -e.detail;
+ const directionY = deltaY > 0 ? 1 : -1;
+ if (directionY > 0) zoomLevel++
+ else zoomLevel--
+ if (zoomLevel >= 45) {
+ zoomLevel = 45;
+ document.getElementById("customRange1").value = 45;
+ } else if (zoomLevel <= 0) {
+ zoomLevel = 0;
+ document.getElementById("customRange1").value = 0;
+ } else {
+ document.getElementById("customRange1").value = zoomLevel;
+ curLevel = zoomLevel;
+ }
}
-
- // previously used for the + and - zoom buttons in quickButtons
-
- // function sliderZoomButton(direction) {
- // var zoomSlider = $('#customRange1')
- // var currentSliderValue = parseInt(zoomSlider.val(), 10)
- // if (direction === -1) {
- // currentSliderValue--
- // } else {
- // currentSliderValue++
- // }
- // zoomSlider.val(currentSliderValue).change()
- // }
-
- // $('#decrement').click(() => {
- // sliderZoomButton(-1)
- // })
-
- // $('#increment').click(() => {
- // sliderZoomButton(1)
- // })
-}
+ function sliderZoomButton (direction) {
+ const zoomSlider = $('#customRange1');
+ let currentSliderValue = parseInt(zoomSlider.val(), 10);
+ if (direction === -1) {
+ currentSliderValue--;
+ } else {
+ currentSliderValue++;
+ }
+ zoomSlider.val(currentSliderValue).change();
+ }
+ $('#decrement').click(() => {
+ sliderZoomButton(-1);
+ });
+ $('#increment').click(() => {
+ sliderZoomButton(1);
+ });
+ }
+
+// Desktop App Listeners
+
+listen('new-project', () => {
+ logixFunction.newProject();
+});
+
+listen('save-online', () => {
+ logixFunction.save();
+});
+
+listen('save-offline', () => {
+ logixFunction.saveOffline();
+});
+
+listen('open-offline', () => {
+ logixFunction.createOpenLocalPrompt();
+});
+
+listen('export', () => {
+ logixFunction.ExportProject();
+});
+
+listen('import', () => {
+ logixFunction.ImportProject();
+});
+
+listen('recover', () => {
+ logixFunction.recoverProject();
+});
+
+listen('clear', () => {
+ logixFunction.clearProject();
+});
+
+listen('preview-circuit', () => {
+ logixFunction.fullViewOption();
+});
+
+listen('new-circuit', () => {
+ logixFunction.createNewCircuitScope();
+});
+
+listen('new-verilog-module', () => {
+ logixFunction.newVerilogModule();
+});
+
+listen('insert-sub-circuit', () => {
+ logixFunction.createSubCircuitPrompt();
+});
+
+listen('combinational-analysis', () => {
+ logixFunction.createCombinationalAnalysisPrompt();
+});
+
+listen('hex-bin-dec', () => {
+ logixFunction.bitconverter();
+});
+
+listen('download-image', () => {
+ logixFunction.createSaveAsImgPrompt();
+});
+
+listen('themes', () => {
+ logixFunction.colorThemes();
+});
+
+listen('custom-shortcut', () => {
+ logixFunction.customShortcut();
+});
+
+listen('export-verilog', () => {
+ logixFunction.generateVerilog();
+});
+
+listen('tutorial', () => {
+ logixFunction.showTourGuide();
+});
+
+listen('user-manual', () => {
+ logixFunction.showUserManual();
+});
+
+listen('learn-digital-circuit', () => {
+ logixFunction.showDigitalCircuit();
+});
+
+listen('discussion-forum', () => {
+ logixFunction.showDiscussionForum();
+});
diff --git a/v1/src/simulator/src/metadata.json b/v1/src/simulator/src/metadata.json
deleted file mode 100644
index 8ed4f225..00000000
--- a/v1/src/simulator/src/metadata.json
+++ /dev/null
@@ -1,179 +0,0 @@
-{
- "circuitElementList": [
- "Input",
- "Output",
- "NotGate",
- "OrGate",
- "AndGate",
- "NorGate",
- "NandGate",
- "XorGate",
- "XnorGate",
- "SevenSegDisplay",
- "SixteenSegDisplay",
- "HexDisplay",
- "Multiplexer",
- "BitSelector",
- "Splitter",
- "Power",
- "Ground",
- "ConstantVal",
- "ControlledInverter",
- "TriState",
- "Adder",
- "verilogMultiplier",
- "verilogDivider",
- "verilogPower",
- "verilogShiftLeft",
- "TwoComplement",
- "verilogShiftRight",
- "Rom",
- "RAM",
- "verilogRAM",
- "EEPROM",
- "TflipFlop",
- "JKflipFlop",
- "SRflipFlop",
- "DflipFlop",
- "TTY",
- "Keyboard",
- "Clock",
- "DigitalLed",
- "Stepper",
- "VariableLed",
- "RGBLed",
- "SquareRGBLed",
- "RGBLedMatrix",
- "Button",
- "Demultiplexer",
- "Buffer",
- "SubCircuit",
- "Flag",
- "MSB",
- "LSB",
- "PriorityEncoder",
- "Tunnel",
- "ALU",
- "Decoder",
- "Random",
- "Counter",
- "Dlatch",
- "TB_Input",
- "TB_Output",
- "ForceGate"
- ],
- "annotationList": ["Text", "Rectangle", "Arrow", "ImageAnnotation"],
- "inputList": [
- "Random",
- "Dlatch",
- "JKflipFlop",
- "TflipFlop",
- "SRflipFlop",
- "DflipFlop",
- "Buffer",
- "Stepper",
- "Ground",
- "Power",
- "ConstantVal",
- "Input",
- "Clock",
- "Button",
- "Counter"
- ],
- "subCircuitInputList": [
- "Random",
- "Dlatch",
- "JKflipFlop",
- "TflipFlop",
- "SRflipFlop",
- "DflipFlop",
- "Buffer",
- "Stepper",
- "Ground",
- "Power",
- "ConstantVal",
- "Clock",
- "Button",
- "Counter"
- ],
- "elementHierarchy": {
- "Input": [
- { "name": "Input", "label": "Input" },
- { "name": "Button", "label": "Button" },
- { "name": "Power", "label": "Power" },
- { "name": "Ground", "label": "Ground" },
- { "name": "ConstantVal", "label": "Constant Value" },
- { "name": "Stepper", "label": "Stepper" },
- { "name": "Random", "label": "Random" },
- { "name": "Counter", "label": "Counter" }
- ],
- "Output": [
- { "name": "Output", "label": "Output" },
- { "name": "RGBLed", "label": "RGB Led" },
- { "name": "DigitalLed", "label": "Digital Led" },
- { "name": "VariableLed", "label": "Variable Led" },
- { "name": "HexDisplay", "label": "Hex Display" },
- { "name": "SevenSegDisplay", "label": "Seven Segment Display" },
- { "name": "SixteenSegDisplay", "label": "Sixteen Segment Display" },
- { "name": "SquareRGBLed", "label": "Square RGB Led" },
- { "name": "RGBLedMatrix", "label": "RGB Led Matrix" }
- ],
- "Gates": [
- { "name": "AndGate", "label": "And Gate" },
- { "name": "OrGate", "label": "Or Gate" },
- { "name": "NotGate", "label": "Not Gate" },
- { "name": "XorGate", "label": "Xor Gate" },
- { "name": "NandGate", "label": "Nand Gate" },
- { "name": "NorGate", "label": "Nor Gate" },
- { "name": "XnorGate", "label": "Xnor Gate" }
- ],
- "Decoders & Plexers": [
- { "name": "Multiplexer", "label": "Multiplexer" },
- { "name": "Demultiplexer", "label": "Demultiplexer" },
- { "name": "BitSelector", "label": "Bit Selector" },
- { "name": "MSB", "label": "MSB(Most Significant Bit)" },
- { "name": "LSB", "label": "LSB(Least Significant Bit)" },
- { "name": "PriorityEncoder", "label": "Priority Encoder" },
- { "name": "Decoder", "label": "Decoder" }
- ],
- "Sequential Elements": [
- { "name": "DflipFlop", "label": "D flip Flop" },
- { "name": "Dlatch", "label": "D latch" },
- { "name": "TflipFlop", "label": "T flip Flop" },
- { "name": "JKflipFlop", "label": "JK flip Flop" },
- { "name": "SRflipFlop", "label": "SR flip Flop" },
- { "name": "TTY", "label": "TTY" },
- { "name": "Keyboard", "label": "Keyboard" },
- { "name": "Clock", "label": "Clock" },
- { "name": "Rom", "label": "ROM" },
- { "name": "RAM", "label": "RAM" },
- { "name": "verilogRAM", "label": "Verilog RAM" },
- { "name": "EEPROM", "label": "EEPROM" }
- ],
- "Annotation": [
- { "name": "Rectangle", "label": "Rectangle" },
- { "name": "Arrow", "label": "Arrow" },
- { "name": "ImageAnnotation", "label": "Image Annotation" },
- { "name": "Text", "label": "Text" }
- ],
- "Misc": [
- { "name": "TwoComplement", "label": "Two Complement" },
- { "name": "Flag", "label": "Flag" },
- { "name": "Splitter", "label": "Splitter" },
- { "name": "Adder", "label": "Adder" },
- { "name": "ALU", "label": "ALU(Arithmetic and Logical Unit)" },
- { "name": "TriState", "label": "TriState Flip Flop" },
- { "name": "Tunnel", "label": "Tunnel" },
- { "name": "verilogMultiplier", "label": "Verilog Multiplier" },
- { "name": "verilogDivider", "label": "Verilog Divider" },
- { "name": "verilogPower", "label": "Verilog Power" },
- { "name": "verilogShiftLeft", "label": "Verilog Shift Left" },
- { "name": "verilogShiftRight", "label": "Verilog Shift Right" },
- { "name": "Buffer", "label": "Buffer" },
- { "name": "ControlledInverter", "label": "Controlled Inverter" },
- { "name": "TB_Input", "label": "TB Input" },
- { "name": "TB_Output", "label": "TB Output" },
- { "name": "ForceGate", "label": "Force Gate" }
- ]
- }
-}
diff --git a/v1/src/simulator/src/metadata.ts b/v1/src/simulator/src/metadata.ts
new file mode 100644
index 00000000..5d99084c
--- /dev/null
+++ b/v1/src/simulator/src/metadata.ts
@@ -0,0 +1,191 @@
+
+export const circuitElementList = [
+ "Input",
+ "Output",
+ "NotGate",
+ "OrGate",
+ "AndGate",
+ "NorGate",
+ "NandGate",
+ "XorGate",
+ "XnorGate",
+ "SevenSegDisplay",
+ "SixteenSegDisplay",
+ "HexDisplay",
+ "Multiplexer",
+ "BitSelector",
+ "Splitter",
+ "Power",
+ "Ground",
+ "ConstantVal",
+ "ControlledInverter",
+ "TriState",
+ "Adder",
+ "verilogMultiplier",
+ "verilogDivider",
+ "verilogPower",
+ "verilogShiftLeft",
+ "TwoComplement",
+ "verilogShiftRight",
+ "Rom",
+ "RAM",
+ "verilogRAM",
+ "EEPROM",
+ "TflipFlop",
+ "JKflipFlop",
+ "SRflipFlop",
+ "DflipFlop",
+ "TTY",
+ "Keyboard",
+ "Clock",
+ "DigitalLed",
+ "Stepper",
+ "VariableLed",
+ "RGBLed",
+ "SquareRGBLed",
+ "RGBLedMatrix",
+ "Button",
+ "Demultiplexer",
+ "Buffer",
+ "SubCircuit",
+ "Flag",
+ "MSB",
+ "LSB",
+ "PriorityEncoder",
+ "Tunnel",
+ "ALU",
+ "Decoder",
+ "Random",
+ "Counter",
+ "Dlatch",
+ "TB_Input",
+ "TB_Output",
+ "ForceGate"
+]
+const annotationList = ["Text", "Rectangle", "Arrow", "ImageAnnotation"]
+export const moduleList = [...circuitElementList, ...annotationList]
+export const updateOrder = [
+ 'wires',
+ ...circuitElementList,
+ 'nodes',
+ ...annotationList,
+] // Order of update
+export const renderOrder = [...moduleList.slice().reverse(), 'wires', 'allNodes'] // Order of render
+export const inputList = [
+ "Random",
+ "Dlatch",
+ "JKflipFlop",
+ "TflipFlop",
+ "SRflipFlop",
+ "DflipFlop",
+ "Buffer",
+ "Stepper",
+ "Ground",
+ "Power",
+ "ConstantVal",
+ "Input",
+ "Clock",
+ "Button",
+ "Counter"
+]
+export const subCircuitInputList = [
+ "Random",
+ "Dlatch",
+ "JKflipFlop",
+ "TflipFlop",
+ "SRflipFlop",
+ "DflipFlop",
+ "Buffer",
+ "Stepper",
+ "Ground",
+ "Power",
+ "ConstantVal",
+ "Clock",
+ "Button",
+ "Counter"
+]
+interface NameLabel {
+ name: string;
+ label: string;
+}
+
+export const elementHierarchy: Record = {
+ "Input": [
+ { name: "Input", label: "Input" },
+ { name: "Button", label: "Button" },
+ { name: "Power", label: "Power" },
+ { name: "Ground", label: "Ground" },
+ { name: "ConstantVal", label: "Constant Value" },
+ { name: "Stepper", label: "Stepper" },
+ { name: "Random", label: "Random" },
+ { name: "Counter", label: "Counter" }
+ ],
+ "Output": [
+ { name: "Output", label: "Output" },
+ { name: "RGBLed", label: "RGB Led" },
+ { name: "DigitalLed", label: "Digital Led" },
+ { name: "VariableLed", label: "Variable Led" },
+ { name: "HexDisplay", label: "Hex Display" },
+ { name: "SevenSegDisplay", label: "Seven Segment Display" },
+ { name: "SixteenSegDisplay", label: "Sixteen Segment Display" },
+ { name: "SquareRGBLed", label: "Square RGB Led" },
+ { name: "RGBLedMatrix", label: "RGB Led Matrix" }
+ ],
+ "Gates": [
+ { name: "AndGate", label: "And Gate" },
+ { name: "OrGate", label: "Or Gate" },
+ { name: "NotGate", label: "Not Gate" },
+ { name: "XorGate", label: "Xor Gate" },
+ { name: "NandGate", label: "Nand Gate" },
+ { name: "NorGate", label: "Nor Gate" },
+ { name: "XnorGate", label: "Xnor Gate" }
+ ],
+ "Decoders & Plexers": [
+ { name: "Multiplexer", label: "Multiplexer" },
+ { name: "Demultiplexer", label: "Demultiplexer" },
+ { name: "BitSelector", label: "Bit Selector" },
+ { name: "MSB", label: "MSB(Most Significant Bit)" },
+ { name: "LSB", label: "LSB(Least Significant Bit)" },
+ { name: "PriorityEncoder", label: "Priority Encoder" },
+ { name: "Decoder", label: "Decoder" }
+ ],
+ "Sequential Elements": [
+ { name: "DflipFlop", label: "D flip Flop" },
+ { name: "Dlatch", label: "D latch" },
+ { name: "TflipFlop", label: "T flip Flop" },
+ { name: "JKflipFlop", label: "JK flip Flop" },
+ { name: "SRflipFlop", label: "SR flip Flop" },
+ { name: "TTY", label: "TTY" },
+ { name: "Keyboard", label: "Keyboard" },
+ { name: "Clock", label: "Clock" },
+ { name: "Rom", label: "ROM" },
+ { name: "RAM", label: "RAM" },
+ { name: "verilogRAM", label: "Verilog RAM" },
+ { name: "EEPROM", label: "EEPROM" }
+ ],
+ "Annotation": [
+ { name: "Rectangle", label: "Rectangle" },
+ { name: "Arrow", label: "Arrow" },
+ { name: "ImageAnnotation", label: "Image Annotation" },
+ { name: "Text", label: "Text" }
+ ],
+ "Misc": [
+ { name: "TwoComplement", label: "Two Complement" },
+ { name: "Flag", label: "Flag" },
+ { name: "Splitter", label: "Splitter" },
+ { name: "Adder", label: "Adder" },
+ { name: "ALU", label: "ALU(Arithmetic and Logical Unit)" },
+ { name: "TriState", label: "TriState Flip Flop" },
+ { name: "Tunnel", label: "Tunnel" },
+ { name: "verilogMultiplier", label: "Verilog Multiplier" },
+ { name: "verilogDivider", label: "Verilog Divider" },
+ { name: "verilogPower", label: "Verilog Power" },
+ { name: "verilogShiftLeft", label: "Verilog Shift Left" },
+ { name: "verilogShiftRight", label: "Verilog Shift Right" },
+ { name: "Buffer", label: "Buffer" },
+ { name: "ControlledInverter", label: "Controlled Inverter" },
+ { name: "TB_Input", label: "TB Input" },
+ { name: "TB_Output", label: "TB Output" },
+ { name: "ForceGate", label: "Force Gate" }
+ ]
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/minimap.js b/v1/src/simulator/src/minimap.js
index 6cfcf49d..84286984 100644
--- a/v1/src/simulator/src/minimap.js
+++ b/v1/src/simulator/src/minimap.js
@@ -1,6 +1,7 @@
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import { colors } from './themer/themer'
import { layoutModeGet } from './layoutMode'
+import { updateOrder } from './metadata'
/**
* @type {Object} miniMapArea
diff --git a/v1/src/simulator/src/moduleSetup.js b/v1/src/simulator/src/moduleSetup.js
index 5002bc69..fb75f6a8 100644
--- a/v1/src/simulator/src/moduleSetup.js
+++ b/v1/src/simulator/src/moduleSetup.js
@@ -54,7 +54,7 @@ import Rom from './sequential/Rom'
import SRflipFlop from './sequential/SRflipFlop'
import TflipFlop from './sequential/TflipFlop'
import TTY from './sequential/TTY'
-import ForceGate from './testbench/ForceGate'
+import ForceGate from './sequential/ForceGate'
import TB_Input from './testbench/testbenchInput'
import TB_Output from './testbench/testbenchOutput'
import verilogMultiplier from './modules/verilogMultiplier'
diff --git a/v1/src/simulator/src/modules.js b/v1/src/simulator/src/modules.js
index 41bacb6f..f52adb3b 100644
--- a/v1/src/simulator/src/modules.js
+++ b/v1/src/simulator/src/modules.js
@@ -1,5 +1,5 @@
/* eslint-disable import/no-cycle */
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
export function getNextPosition(x = 0, scope = globalScope) {
let possibleY = 20
diff --git a/v1/src/simulator/src/modules/ALU.js b/v1/src/simulator/src/modules/ALU.js
index 19cda667..bd10474e 100644
--- a/v1/src/simulator/src/modules/ALU.js
+++ b/v1/src/simulator/src/modules/ALU.js
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText4 } from '../canvasApi'
import { colors } from '../themer/themer'
@@ -95,7 +95,7 @@ export default class ALU extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = colors['hover_select']
}
diff --git a/v1/src/simulator/src/modules/Adder.js b/v1/src/simulator/src/modules/Adder.js
index 8f369a9f..205455b1 100644
--- a/v1/src/simulator/src/modules/Adder.js
+++ b/v1/src/simulator/src/modules/Adder.js
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
/**
* @class
diff --git a/v1/src/simulator/src/modules/AndGate.js b/v1/src/simulator/src/modules/AndGate.js
index 43c3fced..4885d8ab 100644
--- a/v1/src/simulator/src/modules/AndGate.js
+++ b/v1/src/simulator/src/modules/AndGate.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, arc } from '../canvasApi'
import { changeInputSize } from '../modules'
import { colors } from '../themer/themer'
@@ -123,7 +123,7 @@ export default class AndGate extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -142,7 +142,7 @@ export default class AndGate extends CircuitElement {
* @category modules
*/
AndGate.prototype.tooltipText =
- 'And Gate Tooltip : Implements logical conjunction'
+ 'And Gate ToolTip : Implements logical conjunction'
/**
* @memberof AndGate
diff --git a/v1/src/simulator/src/modules/Arrow.js b/v1/src/simulator/src/modules/Arrow.js
index 24eeddfd..1956bb70 100644
--- a/v1/src/simulator/src/modules/Arrow.js
+++ b/v1/src/simulator/src/modules/Arrow.js
@@ -1,8 +1,6 @@
import CircuitElement from '../circuitElement'
-import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
-import { correctWidth, lineTo, moveTo, arc } from '../canvasApi'
-import { changeInputSize } from '../modules'
+import { simulationArea } from '../simulationArea'
+import { correctWidth, lineTo, moveTo } from '../canvasApi'
/**
* @class
* Arrow
@@ -64,7 +62,7 @@ export default class Arrow extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/BitSelector.js b/v1/src/simulator/src/modules/BitSelector.js
index 8c91cee4..d730a8d5 100644
--- a/v1/src/simulator/src/modules/BitSelector.js
+++ b/v1/src/simulator/src/modules/BitSelector.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode, extractBits } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect, fillText } from '../canvasApi'
/**
* @class
@@ -118,7 +118,7 @@ export default class BitSelector extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Buffer.js b/v1/src/simulator/src/modules/Buffer.js
index f3e9cd69..e1237b83 100644
--- a/v1/src/simulator/src/modules/Buffer.js
+++ b/v1/src/simulator/src/modules/Buffer.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
-import { correctWidth, lineTo, moveTo, arc } from '../canvasApi'
-import { changeInputSize } from '../modules'
+import { simulationArea } from '../simulationArea'
+import { correctWidth, lineTo, moveTo } from '../canvasApi'
/**
* @class
* Buffer
@@ -103,7 +102,7 @@ export default class Buffer extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Button.js b/v1/src/simulator/src/modules/Button.js
index b108afaa..e4099ffa 100644
--- a/v1/src/simulator/src/modules/Button.js
+++ b/v1/src/simulator/src/modules/Button.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, drawCircle2 } from '../canvasApi'
/**
@@ -86,7 +86,7 @@ export default class Button extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(232, 13, 13,0.6)'
}
@@ -111,7 +111,7 @@ export default class Button extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = 'rgba(232, 13, 13,0.6)'
if (this.wasClicked) ctx.fillStyle = 'rgba(232, 13, 13,0.8)'
diff --git a/v1/src/simulator/src/modules/ConstantVal.js b/v1/src/simulator/src/modules/ConstantVal.js
index d5f9028a..3e58dc64 100644
--- a/v1/src/simulator/src/modules/ConstantVal.js
+++ b/v1/src/simulator/src/modules/ConstantVal.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect2, fillText, oppositeDirection } from '../canvasApi'
import { colors } from '../themer/themer'
@@ -140,7 +140,7 @@ export default class ConstantVal extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/ControlledInverter.js b/v1/src/simulator/src/modules/ControlledInverter.js
index c846abec..4f74d147 100644
--- a/v1/src/simulator/src/modules/ControlledInverter.js
+++ b/v1/src/simulator/src/modules/ControlledInverter.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, drawCircle2 } from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* ControlledInverter
@@ -19,9 +18,6 @@ import { colors } from '../themer/themer'
export default class ControlledInverter extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['ControlledInverter'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 15)
@@ -72,9 +68,14 @@ export default class ControlledInverter extends CircuitElement {
(32 - this.bitWidth)
simulationArea.simulationQueue.add(this.output1)
}
- if (this.state.value === 0) {
- this.output1.value = undefined
+ else if (
+ this.output1.value !== undefined &&
+ !simulationArea.contentionPending.has(this.output1)
+ ) {
+ this.output1.value = undefined;
+ simulationArea.simulationQueue.add(this.output1);
}
+ simulationArea.contentionPending.removeAllContentionsForNode(this.output1);
}
/**
@@ -96,7 +97,7 @@ export default class ControlledInverter extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Counter.js b/v1/src/simulator/src/modules/Counter.js
index 7ffb23fc..633baaec 100644
--- a/v1/src/simulator/src/modules/Counter.js
+++ b/v1/src/simulator/src/modules/Counter.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { lineTo, moveTo, fillText, correctWidth, rect2 } from '../canvasApi'
import { colors } from '../themer/themer'
@@ -142,7 +142,7 @@ export default class Counter extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32,0.6)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Decoder.js b/v1/src/simulator/src/modules/Decoder.js
index 6b6d9278..3d4a6955 100644
--- a/v1/src/simulator/src/modules/Decoder.js
+++ b/v1/src/simulator/src/modules/Decoder.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, rect, fillText } from '../canvasApi'
/**
* @class
@@ -18,10 +18,6 @@ import { colors } from '../themer/themer'
export default class Decoder extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'LEFT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Decoder'].push(this);
- */
- // this.controlSignalSize = controlSignalSize || parseInt(prompt("Enter control signal bitWidth"), 10);
this.outputsize = 1 << this.bitWidth
this.xOff = 0
this.yOff = 1
@@ -31,31 +27,8 @@ export default class Decoder extends CircuitElement {
if (this.bitWidth <= 3) {
this.yOff = 2
}
-
- // this.changeControlSignalSize = function(size) {
- // if (size === undefined || size < 1 || size > 32) return;
- // if (this.controlSignalSize === size) return;
- // let obj = new window[this.objectType](this.x, this.y, this.scope, this.direction, this.bitWidth, size);
- // this.cleanDelete();
- // simulationArea.lastSelected = obj;
- // return obj;
- // }
- // this.mutableProperties = {
- // "controlSignalSize": {
- // name: "Control Signal Size",
- // type: "number",
- // max: "32",
- // min: "1",
- // func: "changeControlSignalSize",
- // },
- // }
// eslint-disable-next-line no-shadow
this.newBitWidth = function (bitWidth) {
- // this.bitWidth = bitWidth;
- // for (let i = 0; i < this.inputSize; i++) {
- // this.outputs1[i].bitWidth = bitWidth
- // }
- // this.input.bitWidth = bitWidth;
if (bitWidth === undefined || bitWidth < 1 || bitWidth > 32) return
if (this.bitWidth === bitWidth) return
const obj = new Decoder(
@@ -85,8 +58,6 @@ export default class Decoder extends CircuitElement {
)
this.output1.push(a)
}
-
- // this.controlSignalInput = new Node(0,this.yOff * 10 * (this.outputsize / 2 - 1) +this.xOff + 10, 0, this, this.controlSignalSize,"Control Signal");
}
/**
@@ -129,12 +100,6 @@ export default class Decoder extends CircuitElement {
const xx = this.x
const yy = this.y
-
- // ctx.beginPath();
- // moveTo(ctx, 0,this.yOff * 10 * (this.outputsize / 2 - 1) + 10 + 0.5 *this.xOff, xx, yy, this.direction);
- // lineTo(ctx, 0,this.yOff * 5 * (this.outputsize - 1) +this.xOff, xx, yy, this.direction);
- // ctx.stroke();
-
ctx.beginPath()
ctx.strokeStyle = colors['stroke']
ctx.lineWidth = correctWidth(4)
@@ -176,7 +141,7 @@ export default class Decoder extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = colors['hover_select']
}
@@ -186,7 +151,6 @@ export default class Decoder extends CircuitElement {
ctx.beginPath()
ctx.fillStyle = 'black'
ctx.textAlign = 'center'
- // [xFill,yFill] = rotate(xx + this.output1[i].x - 7, yy + this.output1[i].y + 2);
for (let i = 0; i < this.outputsize; i++) {
if (this.direction === 'LEFT')
fillText(
diff --git a/v1/src/simulator/src/modules/Demultiplexer.js b/v1/src/simulator/src/modules/Demultiplexer.js
index feb21cfa..1a679539 100644
--- a/v1/src/simulator/src/modules/Demultiplexer.js
+++ b/v1/src/simulator/src/modules/Demultiplexer.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText } from '../canvasApi'
/**
* @class
@@ -206,7 +206,7 @@ export default class Demultiplexer extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = colors['hover_select']
}
diff --git a/v1/src/simulator/src/modules/DigitalLed.js b/v1/src/simulator/src/modules/DigitalLed.js
index df17fbfa..da280340 100644
--- a/v1/src/simulator/src/modules/DigitalLed.js
+++ b/v1/src/simulator/src/modules/DigitalLed.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import {
correctWidth,
lineTo,
@@ -10,7 +10,6 @@ import {
drawCircle2,
validColor,
} from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* DigitalLed
@@ -26,13 +25,11 @@ import { colors } from '../themer/themer'
export default class DigitalLed extends CircuitElement {
constructor(x, y, scope = globalScope, color = 'Red') {
// Calling base class constructor
-
super(x, y, scope, 'UP', 1)
- /* this is done in this.baseSetup() now
- this.scope['DigitalLed'].push(this);
- */
this.rectangleObject = false
- this.setDimensions(10, 20)
+ this.setWidth(10);
+ this.upDimensionY = 20;
+ this.downDimensionY = 40;
this.inp1 = new Node(-40, 0, 0, this, 1)
this.directionFixed = true
this.fixedBitWidth = true
@@ -114,7 +111,7 @@ export default class DigitalLed extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -140,7 +137,7 @@ export default class DigitalLed extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = 'rgba(255, 255, 32,0.8)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Flag.js b/v1/src/simulator/src/modules/Flag.js
index f332622b..b0cd9bf2 100644
--- a/v1/src/simulator/src/modules/Flag.js
+++ b/v1/src/simulator/src/modules/Flag.js
@@ -1,9 +1,8 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect2, fillText } from '../canvasApi'
import plotArea from '../plotArea'
-import EventQueue from '../eventQueue'
/**
* @class
* Flag
@@ -28,9 +27,6 @@ export default class Flag extends CircuitElement {
identifier
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Flag'].push(this);
- */
this.setWidth(60)
this.setHeight(20)
this.rectangleObject = false
@@ -127,7 +123,7 @@ export default class Flag extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -189,9 +185,6 @@ export default class Flag extends CircuitElement {
} else {
this.inp1.leftx = 20
}
- // if(this.direction=="LEFT" || this.direction=="RIGHT") this.inp1.leftx=50-this.xSize;
- // this.inp1.refresh();
-
this.inp1.refresh()
}
}
diff --git a/v1/src/simulator/src/modules/Ground.js b/v1/src/simulator/src/modules/Ground.js
index f1c88932..e9e801b9 100644
--- a/v1/src/simulator/src/modules/Ground.js
+++ b/v1/src/simulator/src/modules/Ground.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
-import { correctWidth, lineTo, moveTo, arc } from '../canvasApi'
-import { changeInputSize } from '../modules'
+import { simulationArea } from '../simulationArea'
+import { correctWidth, lineTo, moveTo } from '../canvasApi'
/**
* @class
* Ground
@@ -18,33 +17,12 @@ import { colors } from '../themer/themer'
export default class Ground extends CircuitElement {
constructor(x, y, scope = globalScope, bitWidth = 1) {
super(x, y, scope, 'RIGHT', bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Ground'].push(this);
- */
this.rectangleObject = false
this.setDimensions(10, 10)
this.directionFixed = true
this.output1 = new Node(0, -10, 1, this)
}
- /**
- * @memberof Ground
- * fn to create save Json Data of object
- * @return {JSON}
- */
- customSave() {
- const data = {
- nodes: {
- output1: findNode(this.output1),
- },
- values: {
- state: this.state,
- },
- constructorParamaters: [this.direction, this.bitWidth],
- }
- return data
- }
-
/**
* @memberof Ground
* resolve output values based on inputData
@@ -80,7 +58,7 @@ export default class Ground extends CircuitElement {
ctx.strokeStyle = [colors['stroke'], 'brown'][
((this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)) + 0
+ simulationArea.multipleObjectSelections.includes(this)) + 0
]
ctx.lineWidth = correctWidth(3)
diff --git a/v1/src/simulator/src/modules/HexDisplay.js b/v1/src/simulator/src/modules/HexDisplay.js
index b96cd096..1c58b1b1 100644
--- a/v1/src/simulator/src/modules/HexDisplay.js
+++ b/v1/src/simulator/src/modules/HexDisplay.js
@@ -1,16 +1,14 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import {
correctWidth,
lineTo,
moveTo,
- arc,
rect2,
validColor,
colorToRGBA,
} from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* HexDisplay
@@ -25,9 +23,6 @@ import { colors } from '../themer/themer'
export default class HexDisplay extends CircuitElement {
constructor(x, y, scope = globalScope, color = 'Red') {
super(x, y, scope, 'RIGHT', 4)
- /* this is done in this.baseSetup() now
- this.scope['HexDisplay'].push(this);
- */
this.directionFixed = true
this.fixedBitWidth = true
this.setDimensions(30, 50)
@@ -96,9 +91,6 @@ export default class HexDisplay extends CircuitElement {
customDraw() {
var ctx = simulationArea.context
- const xx = this.x
- const yy = this.y
-
ctx.strokeStyle = colors['stroke']
ctx.lineWidth = correctWidth(3)
@@ -366,7 +358,7 @@ export default class HexDisplay extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32,0.6)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/ImageAnnotation.js b/v1/src/simulator/src/modules/ImageAnnotation.js
index 67ac4d8b..d46eba66 100644
--- a/v1/src/simulator/src/modules/ImageAnnotation.js
+++ b/v1/src/simulator/src/modules/ImageAnnotation.js
@@ -1,9 +1,8 @@
import CircuitElement from '../circuitElement'
-import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect, fillText, drawImage } from '../canvasApi'
import { colors } from '../themer/themer'
-import { promptFile, showMessage, getImageDimensions } from '../utils'
+import { promptFile, showMessage } from '../utils'
/**
* @class
* Image
@@ -113,7 +112,7 @@ export default class ImageAnnotation extends CircuitElement {
if (
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32,0.1)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Input.js b/v1/src/simulator/src/modules/Input.js
index d33c8627..d6ac8dd2 100644
--- a/v1/src/simulator/src/modules/Input.js
+++ b/v1/src/simulator/src/modules/Input.js
@@ -1,7 +1,7 @@
/* eslint-disable no-unused-expressions */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, oppositeDirection, fillText } from '../canvasApi'
import { getNextPosition } from '../modules'
import { generateId } from '../utils'
@@ -40,9 +40,6 @@ export default class Input extends CircuitElement {
layoutProperties
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Input'].push(this);
- */
if (layoutProperties) {
this.layoutProperties = layoutProperties
} else {
diff --git a/v1/src/simulator/src/modules/LSB.js b/v1/src/simulator/src/modules/LSB.js
index 0f7e4e61..c4b9e487 100644
--- a/v1/src/simulator/src/modules/LSB.js
+++ b/v1/src/simulator/src/modules/LSB.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode, dec2bin } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect, fillText } from '../canvasApi'
/**
* @class
@@ -18,16 +18,12 @@ import { colors } from '../themer/themer'
export default class LSB extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['LSB'].push(this);
- */
this.leftDimensionX = 10
this.rightDimensionX = 20
this.setHeight(30)
this.directionFixed = true
this.bitWidth = bitWidth || parseInt(prompt('Enter bitWidth'), 10)
this.rectangleObject = false
- // this.inputSize = 1 << this.bitWidth;
this.intputSize = this.bitWidth
this.inp1 = new Node(-10, 0, 0, this, this.inputSize)
@@ -58,7 +54,6 @@ export default class LSB extends CircuitElement {
* @param {number} bitWidth - new bitwidth
*/
newBitWidth(bitWidth) {
- // this.inputSize = 1 << bitWidth
this.inputSize = bitWidth
this.inp1.bitWidth = this.inputSize
this.bitWidth = bitWidth
@@ -104,9 +99,9 @@ export default class LSB extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
- ctx.fillStyle = colors['hover_select']
+ ctx.fillStyle = colors['hover_select']
ctx.fill()
ctx.stroke()
diff --git a/v1/src/simulator/src/modules/MSB.js b/v1/src/simulator/src/modules/MSB.js
index fbe14b2c..dfb587b4 100644
--- a/v1/src/simulator/src/modules/MSB.js
+++ b/v1/src/simulator/src/modules/MSB.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode, dec2bin } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect, fillText } from '../canvasApi'
/**
* @class
@@ -18,17 +18,12 @@ import { colors } from '../themer/themer'
export default class MSB extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['MSB'].push(this);
- */
- // this.setDimensions(20, 20);
this.leftDimensionX = 10
this.rightDimensionX = 20
this.setHeight(30)
this.directionFixed = true
this.bitWidth = bitWidth || parseInt(prompt('Enter bitWidth'), 10)
this.rectangleObject = false
- // this.inputSize = 1 << this.bitWidth;
this.intputSize = this.bitWidth
this.inp1 = new Node(-10, 0, 0, this, this.inputSize)
@@ -98,9 +93,9 @@ export default class MSB extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
- ctx.fillStyle = colors['hover_select']
+ ctx.fillStyle = colors['hover_select']
ctx.fill()
ctx.stroke()
diff --git a/v1/src/simulator/src/modules/Multiplexer.js b/v1/src/simulator/src/modules/Multiplexer.js
index 638b9d01..59c92387 100644
--- a/v1/src/simulator/src/modules/Multiplexer.js
+++ b/v1/src/simulator/src/modules/Multiplexer.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText } from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* Multiplexer
@@ -27,9 +26,6 @@ export default class Multiplexer extends CircuitElement {
controlSignalSize = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Multiplexer'].push(this);
- */
this.controlSignalSize =
controlSignalSize ||
parseInt(prompt('Enter control signal bitWidth'), 10)
@@ -215,7 +211,7 @@ export default class Multiplexer extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = colors['hover_select']
}
diff --git a/v1/src/simulator/src/modules/NandGate.js b/v1/src/simulator/src/modules/NandGate.js
index 1cf25e82..2a57fe14 100644
--- a/v1/src/simulator/src/modules/NandGate.js
+++ b/v1/src/simulator/src/modules/NandGate.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, drawCircle2, arc } from '../canvasApi'
import { changeInputSize } from '../modules'
import { gateGenerateVerilog } from '../utils'
@@ -29,9 +29,6 @@ export default class NandGate extends CircuitElement {
bitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['NandGate'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 20)
this.inp = []
@@ -120,7 +117,7 @@ export default class NandGate extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/NorGate.js b/v1/src/simulator/src/modules/NorGate.js
index 38572dd5..e7e370c0 100644
--- a/v1/src/simulator/src/modules/NorGate.js
+++ b/v1/src/simulator/src/modules/NorGate.js
@@ -1,13 +1,12 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { gateGenerateVerilog } from '../utils'
import {
correctWidth,
bezierCurveTo,
moveTo,
- arc2,
drawCircle2,
} from '../canvasApi'
import { changeInputSize } from '../modules'
@@ -35,9 +34,6 @@ export default class NorGate extends CircuitElement {
bitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['NorGate'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 20)
@@ -134,9 +130,9 @@ export default class NorGate extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
- ctx.fillStyle = colors['hover_select']
+ ctx.fillStyle = colors['hover_select']
ctx.fill()
ctx.stroke()
ctx.beginPath()
diff --git a/v1/src/simulator/src/modules/NotGate.js b/v1/src/simulator/src/modules/NotGate.js
index 38ec3a05..6c1ca9a5 100644
--- a/v1/src/simulator/src/modules/NotGate.js
+++ b/v1/src/simulator/src/modules/NotGate.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, drawCircle2 } from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* NotGate
@@ -19,12 +18,8 @@ import { colors } from '../themer/themer'
export default class NotGate extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['NotGate'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 15)
-
this.inp1 = new Node(-10, 0, 0, this)
this.output1 = new Node(20, 0, 1, this)
}
@@ -79,7 +74,7 @@ export default class NotGate extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -107,7 +102,7 @@ export default class NotGate extends CircuitElement {
* @category modules
*/
NotGate.prototype.tooltipText =
- 'Not Gate Tooltip : Inverts the input digital signal.'
+ 'Not Gate ToolTip : Inverts the input digital signal.'
NotGate.prototype.helplink = 'https://docs.circuitverse.org/#/chapter4/4gates?id=not-gate'
NotGate.prototype.objectType = 'NotGate'
NotGate.prototype.verilogType = 'not'
diff --git a/v1/src/simulator/src/modules/OrGate.js b/v1/src/simulator/src/modules/OrGate.js
deleted file mode 100644
index 31b557cd..00000000
--- a/v1/src/simulator/src/modules/OrGate.js
+++ /dev/null
@@ -1,175 +0,0 @@
-import CircuitElement from '../circuitElement'
-import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
-import { correctWidth, bezierCurveTo, moveTo, arc2 } from '../canvasApi'
-import { changeInputSize } from '../modules'
-import { gateGenerateVerilog } from '../utils'
-
-/**
- * @class
- * OrGate
- * @extends CircuitElement
- * @param {number} x - x coordinate of element.
- * @param {number} y - y coordinate of element.
- * @param {Scope=} scope - Cirucit on which element is drawn
- * @param {string=} dir - direction of element
- * @param {number=} inputs - number of input nodes
- * @param {number=} bitWidth - bit width per node.
- * @category modules
- */
-import { colors } from '../themer/themer'
-
-export default class OrGate extends CircuitElement {
- constructor(
- x,
- y,
- scope = globalScope,
- dir = 'RIGHT',
- inputs = 2,
- bitWidth = 1
- ) {
- // Calling base class constructor
- super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['OrGate'].push(this);
- */
- this.rectangleObject = false
- this.setDimensions(15, 20)
- // Inherit base class prototype
- this.inp = []
- this.inputSize = inputs
- if (inputs % 2 === 1) {
- for (let i = Math.floor(inputs / 2) - 1; i >= 0; i--) {
- const a = new Node(-10, -10 * (i + 1), 0, this)
- this.inp.push(a)
- }
- let a = new Node(-10, 0, 0, this)
- this.inp.push(a)
- for (let i = 0; i < Math.floor(inputs / 2); i++) {
- a = new Node(-10, 10 * (i + 1), 0, this)
- this.inp.push(a)
- }
- } else {
- for (let i = inputs / 2 - 1; i >= 0; i--) {
- const a = new Node(-10, -10 * (i + 1), 0, this)
- this.inp.push(a)
- }
- for (let i = 0; i < inputs / 2; i++) {
- const a = new Node(-10, 10 * (i + 1), 0, this)
- this.inp.push(a)
- }
- }
- this.output1 = new Node(20, 0, 1, this)
- }
-
- /**
- * @memberof OrGate
- * fn to create save Json Data of object
- * @return {JSON}
- */
- customSave() {
- const data = {
- constructorParamaters: [
- this.direction,
- this.inputSize,
- this.bitWidth,
- ],
-
- nodes: {
- inp: this.inp.map(findNode),
- output1: findNode(this.output1),
- },
- }
- return data
- }
-
- /**
- * @memberof OrGate
- * resolve output values based on inputData
- */
- resolve() {
- let result = this.inp[0].value || 0
- if (this.isResolvable() === false) {
- return
- }
- for (let i = 1; i < this.inputSize; i++)
- result |= this.inp[i].value || 0
- this.output1.value = result >>> 0
- simulationArea.simulationQueue.add(this.output1)
- }
-
- /**
- * @memberof OrGate
- * function to draw element
- */
- customDraw() {
- var ctx = simulationArea.context
- ctx.strokeStyle = colors['stroke']
- ctx.lineWidth = correctWidth(3)
-
- const xx = this.x
- const yy = this.y
- ctx.beginPath()
- ctx.fillStyle = colors['fill']
-
- moveTo(ctx, -10, -20, xx, yy, this.direction, true)
- bezierCurveTo(0, -20, +15, -10, 20, 0, xx, yy, this.direction)
- bezierCurveTo(
- 0 + 15,
- 0 + 10,
- 0,
- 0 + 20,
- -10,
- +20,
- xx,
- yy,
- this.direction
- )
- bezierCurveTo(0, 0, 0, 0, -10, -20, xx, yy, this.direction)
- ctx.closePath()
- if (
- (this.hover && !simulationArea.shiftDown) ||
- simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
- )
- ctx.fillStyle = colors['hover_select']
- ctx.fill()
- ctx.stroke()
- }
-
- generateVerilog() {
- return gateGenerateVerilog.call(this, '|')
- }
-}
-
-/**
- * @memberof OrGate
- * Help Tip
- * @type {string}
- * @category modules
- */
-OrGate.prototype.tooltipText =
- 'Or Gate Tooltip : Implements logical disjunction'
-
-/**
- * @memberof OrGate
- * function to change input nodes of the element
- * @category modules
- */
-OrGate.prototype.changeInputSize = changeInputSize
-
-/**
- * @memberof SevenSegDisplay
- * @type {boolean}
- * @category modules
- */
-OrGate.prototype.alwaysResolve = true
-
-/**
- * @memberof SevenSegDisplay
- * @type {string}
- * @category modules
- */
-OrGate.prototype.verilogType = 'or'
-OrGate.prototype.helplink = 'https://docs.circuitverse.org/#/chapter4/4gates?id=or-gate'
-OrGate.prototype.objectType = 'OrGate'
diff --git a/v1/src/simulator/src/modules/OrGate.ts b/v1/src/simulator/src/modules/OrGate.ts
new file mode 100644
index 00000000..897cc229
--- /dev/null
+++ b/v1/src/simulator/src/modules/OrGate.ts
@@ -0,0 +1,133 @@
+import CircuitElement from '../circuitElement';
+import Node, { findNode } from '../node';
+import { simulationArea } from '../simulationArea';
+import { correctWidth, bezierCurveTo, moveTo } from '../canvasApi';
+import { changeInputSize } from '../modules';
+import { gateGenerateVerilog } from '../utils';
+
+import { colors } from '../themer/themer';
+
+export default class OrGate extends CircuitElement {
+ private inp: Node[];
+ private inputSize: number;
+ private output1: Node;
+
+ constructor(
+ x: number,
+ y: number,
+ scope: any = globalScope,
+ dir: string = 'RIGHT',
+ inputs: number = 2,
+ bitWidth: number = 1
+ ) {
+ super(x, y, scope, dir, bitWidth);
+ this.rectangleObject = false;
+ this.setDimensions(15, 20);
+ this.inp = [];
+ this.inputSize = inputs;
+ if (inputs % 2 === 1) {
+ for (let i = Math.floor(inputs / 2) - 1; i >= 0; i--) {
+ const a = new Node(-10, -10 * (i + 1), 0, this);
+ this.inp.push(a);
+ }
+ let a = new Node(-10, 0, 0, this);
+ this.inp.push(a);
+ for (let i = 0; i < Math.floor(inputs / 2); i++) {
+ a = new Node(-10, 10 * (i + 1), 0, this);
+ this.inp.push(a);
+ }
+ } else {
+ for (let i = inputs / 2 - 1; i >= 0; i--) {
+ const a = new Node(-10, -10 * (i + 1), 0, this);
+ this.inp.push(a);
+ }
+ for (let i = 0; i < inputs / 2; i++) {
+ const a = new Node(-10, 10 * (i + 1), 0, this);
+ this.inp.push(a);
+ }
+ }
+ this.output1 = new Node(20, 0, 1, this);
+ }
+
+ // Resolve output values based on inp
+ resolve() {
+ let result = this.inp[0].value || 0;
+ if (this.isResolvable() === false) {
+ return;
+ }
+ for (let i = 1; i < this.inputSize; i++) {
+ result |= this.inp[i].value || 0;
+ }
+ this.output1.value = result >>> 0;
+ simulationArea.simulationQueue.add(this.output1);
+ }
+
+ customDraw() {
+ var ctx = simulationArea.context;
+ if (ctx) {
+ ctx.strokeStyle = colors['stroke'];
+ ctx.lineWidth = correctWidth(3);
+
+ const xx = this.x;
+ const yy = this.y;
+ ctx.beginPath();
+ ctx.fillStyle = colors['fill'];
+
+ moveTo(ctx, -10, -20, xx, yy, this.direction, true);
+ bezierCurveTo(0, -20, +15, -10, 20, 0, xx, yy, this.direction);
+ bezierCurveTo(
+ 0 + 15,
+ 0 + 10,
+ 0,
+ 0 + 20,
+ -10,
+ +20,
+ xx,
+ yy,
+ this.direction
+ );
+ bezierCurveTo(0, 0, 0, 0, -10, -20, xx, yy, this.direction);
+ ctx.closePath();
+ if (
+ (this.hover && !simulationArea.shiftDown) ||
+ simulationArea.lastSelected === this ||
+ simulationArea.multipleObjectSelections.includes(this)
+ ) {
+ ctx.fillStyle = colors['hover_select'];
+ }
+ ctx.fill();
+ ctx.stroke();
+ }
+ }
+
+ customSave(): object {
+ const data = {
+ constructorParamaters: [
+ this.direction,
+ this.inputSize,
+ this.bitWidth,
+ ],
+ nodes: {
+ inp: this.inp.map(findNode),
+ output1: findNode(this.output1),
+ },
+ };
+ return data;
+ }
+
+ generateVerilog(): string {
+ return gateGenerateVerilog.call(this, '|');
+ }
+}
+
+OrGate.prototype.tooltipText =
+ 'Or Gate ToolTip : Implements logical disjunction';
+
+OrGate.prototype.changeInputSize = changeInputSize;
+
+OrGate.prototype.alwaysResolve = true;
+
+OrGate.prototype.verilogType = 'or';
+OrGate.prototype.helplink =
+ 'https://docs.circuitverse.org/#/chapter4/4gates?id=or-gate';
+OrGate.prototype.objectType = 'OrGate';
\ No newline at end of file
diff --git a/v1/src/simulator/src/modules/Output.js b/v1/src/simulator/src/modules/Output.js
index 23ef3975..b4442664 100644
--- a/v1/src/simulator/src/modules/Output.js
+++ b/v1/src/simulator/src/modules/Output.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, fillText, rect2, oppositeDirection } from '../canvasApi'
import { getNextPosition } from '../modules'
import { generateId } from '../utils'
@@ -40,9 +40,6 @@ export default class Output extends CircuitElement {
) {
// Calling base class constructor
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Output'].push(this);
- */
if (layoutProperties) {
this.layoutProperties = layoutProperties
} else {
@@ -59,15 +56,6 @@ export default class Output extends CircuitElement {
this.inp1 = new Node(this.bitWidth * 10, 0, 0, this)
}
- /**
- * @memberof Output
- * function to generate verilog for output
- * @return {string}
- */
- generateVerilog() {
- return `assign ${this.label} = ${this.inp1.verilogLabel};`
- }
-
/**
* @memberof Output
* fn to create save Json Data of object
@@ -140,7 +128,7 @@ export default class Output extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = colors['hover_select']
}
@@ -186,6 +174,11 @@ export default class Output extends CircuitElement {
this.labelDirection = oppositeDirection[this.direction]
}
+ /**
+ * @memberof Output
+ * function to generate verilog for output
+ * @return {string}
+ */
generateVerilog() {
return (
'assign ' + this.verilogLabel + ' = ' + this.inp1.verilogLabel + ';'
diff --git a/v1/src/simulator/src/modules/Power.js b/v1/src/simulator/src/modules/Power.js
index 87c419a5..f1efe4a0 100644
--- a/v1/src/simulator/src/modules/Power.js
+++ b/v1/src/simulator/src/modules/Power.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
-import { correctWidth, lineTo, moveTo, arc } from '../canvasApi'
-import { changeInputSize } from '../modules'
+import { simulationArea } from '../simulationArea'
+import { correctWidth, lineTo, moveTo } from '../canvasApi'
/**
* @class
* Power
@@ -18,9 +17,6 @@ import { colors } from '../themer/themer'
export default class Power extends CircuitElement {
constructor(x, y, scope = globalScope, bitWidth = 1) {
super(x, y, scope, 'RIGHT', bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Power'].push(this);
- */
this.directionFixed = true
this.rectangleObject = false
this.setDimensions(10, 10)
@@ -72,7 +68,7 @@ export default class Power extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/PriorityEncoder.js b/v1/src/simulator/src/modules/PriorityEncoder.js
index b74d7f90..0eea9e7e 100644
--- a/v1/src/simulator/src/modules/PriorityEncoder.js
+++ b/v1/src/simulator/src/modules/PriorityEncoder.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode, dec2bin } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect, fillText } from '../canvasApi'
/**
* @class
@@ -18,9 +18,6 @@ import { colors } from '../themer/themer'
export default class PriorityEncoder extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['PriorityEncoder'].push(this);
- */
this.bitWidth = bitWidth || parseInt(prompt('Enter bitWidth'), 10)
this.inputSize = 1 << this.bitWidth
@@ -29,7 +26,8 @@ export default class PriorityEncoder extends CircuitElement {
this.yOff = 2
}
- this.setDimensions(20, this.yOff * 5 * this.inputSize)
+ this.setDimensions(20, this.yOff * 5 * this.inputSize + 10);
+ this.rightDimensionX += 10;
this.directionFixed = true
this.rectangleObject = false
@@ -182,7 +180,7 @@ export default class PriorityEncoder extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/RGBLed.js b/v1/src/simulator/src/modules/RGBLed.js
index a1bcc659..799979f2 100644
--- a/v1/src/simulator/src/modules/RGBLed.js
+++ b/v1/src/simulator/src/modules/RGBLed.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, arc, drawCircle2 } from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* RGBLed
@@ -18,12 +17,10 @@ export default class RGBLed extends CircuitElement {
constructor(x, y, scope = globalScope) {
// Calling base class constructor
super(x, y, scope, 'UP', 8)
- /* this is done in this.baseSetup() now
- this.scope['RGBLed'].push(this);
- */
this.rectangleObject = false
this.inp = []
this.setDimensions(10, 10)
+ this.downDimensionY = 40;
this.inp1 = new Node(-40, -10, 0, this, 8)
this.inp2 = new Node(-40, 0, 0, this, 8)
this.inp3 = new Node(-40, 10, 0, this, 8)
@@ -89,7 +86,6 @@ export default class RGBLed extends CircuitElement {
`rgba(${a}, ${b}, ${c}, 0.8)`,
'rgba(227, 228, 229, 0.8)',
][(a === undefined || b === undefined || c === undefined) + 0]
- // ctx.fillStyle = ["rgba(200, 200, 200, 0.3)","rgba(227, 228, 229, 0.8)"][((a === undefined || b === undefined || c === undefined) || (a === 0 && b === 0 && c === 0)) + 0];
ctx.lineWidth = correctWidth(1)
ctx.beginPath()
@@ -115,7 +111,7 @@ export default class RGBLed extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -145,7 +141,7 @@ export default class RGBLed extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = 'rgba(255, 255, 32,0.8)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/RGBLedMatrix.js b/v1/src/simulator/src/modules/RGBLedMatrix.js
index 00fe1757..4825b0f6 100644
--- a/v1/src/simulator/src/modules/RGBLedMatrix.js
+++ b/v1/src/simulator/src/modules/RGBLedMatrix.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect2, rotate, lineTo, moveTo } from '../canvasApi'
/**
@@ -28,9 +28,6 @@ export default class RGBLedMatrix extends CircuitElement {
} = {}
) {
super(x, y, scope, 'RIGHT', 8)
- /* this is done in this.baseSetup() now
- this.scope['RGBLedMatrix'].push(this);
- */
this.fixedBitWidth = true
this.directionFixed = true
this.rectangleObject = true
diff --git a/v1/src/simulator/src/modules/Random.js b/v1/src/simulator/src/modules/Random.js
index 01c9427b..fbfa2084 100644
--- a/v1/src/simulator/src/modules/Random.js
+++ b/v1/src/simulator/src/modules/Random.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { fillText, lineTo, moveTo, correctWidth, rect2 } from '../canvasApi'
/**
* @class
@@ -131,7 +131,7 @@ export default class Random extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32,0.6)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Rectangle.js b/v1/src/simulator/src/modules/Rectangle.js
index 09bf240f..4fa2c461 100644
--- a/v1/src/simulator/src/modules/Rectangle.js
+++ b/v1/src/simulator/src/modules/Rectangle.js
@@ -1,6 +1,5 @@
import CircuitElement from '../circuitElement'
-import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect } from '../canvasApi'
/**
* @class
@@ -16,9 +15,6 @@ import { correctWidth, rect } from '../canvasApi'
export default class Rectangle extends CircuitElement {
constructor(x, y, scope = globalScope, rows = 15, cols = 20) {
super(x, y, scope, 'RIGHT', 1)
- /* this is done in this.baseSetup() now
- this.scope['Rectangle'].push(this);
- */
this.directionFixed = true
this.fixedBitWidth = true
this.rectangleObject = false
@@ -100,7 +96,7 @@ export default class Rectangle extends CircuitElement {
if (
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32,0.1)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/SevenSegDisplay.js b/v1/src/simulator/src/modules/SevenSegDisplay.js
index eedd26f0..9c79ace5 100644
--- a/v1/src/simulator/src/modules/SevenSegDisplay.js
+++ b/v1/src/simulator/src/modules/SevenSegDisplay.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import {
colorToRGBA,
correctWidth,
@@ -23,9 +23,6 @@ import {
export default class SevenSegDisplay extends CircuitElement {
constructor(x, y, scope = globalScope, color = 'Red') {
super(x, y, scope, 'RIGHT', 1)
- /* this is done in this.baseSetup() now
- this.scope['SevenSegDisplay'].push(this);
- */
this.fixedBitWidth = true
this.directionFixed = true
this.setDimensions(30, 50)
@@ -266,7 +263,7 @@ export default class SevenSegDisplay extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32,0.6)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/SixteenSegDisplay.js b/v1/src/simulator/src/modules/SixteenSegDisplay.js
index 944ba443..9a15575a 100644
--- a/v1/src/simulator/src/modules/SixteenSegDisplay.js
+++ b/v1/src/simulator/src/modules/SixteenSegDisplay.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import {
colorToRGBA,
correctWidth,
@@ -10,7 +10,6 @@ import {
rect2,
validColor,
} from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* SixteenSegDisplay
@@ -23,9 +22,6 @@ import { changeInputSize } from '../modules'
export default class SixteenSegDisplay extends CircuitElement {
constructor(x, y, scope = globalScope, color = 'Red') {
super(x, y, scope, 'RIGHT', 16)
- /* this is done in this.baseSetup() now
- this.scope['SixteenSegDisplay'].push(this);
- */
this.fixedBitWidth = true
this.directionFixed = true
this.setDimensions(30, 50)
@@ -435,7 +431,7 @@ export default class SixteenSegDisplay extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32,0.6)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Splitter.js b/v1/src/simulator/src/modules/Splitter.js
index ffcb296c..1cf3f006 100644
--- a/v1/src/simulator/src/modules/Splitter.js
+++ b/v1/src/simulator/src/modules/Splitter.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText2 } from '../canvasApi'
import { colors } from '../themer/themer'
@@ -30,9 +30,6 @@ export default class Splitter extends CircuitElement {
bitWidthSplit = undefined
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Splitter'].push(this);
- */
this.rectangleObject = false
this.bitWidthSplit =
@@ -169,8 +166,6 @@ export default class Splitter extends CircuitElement {
this.inp1.value = n >>> 0
simulationArea.simulationQueue.add(this.inp1)
}
- // else if (this.inp1.value !== n) {
- // }
}
this.prevInpValue = this.inp1.value
}
@@ -183,57 +178,16 @@ export default class Splitter extends CircuitElement {
this.prevInpValue = undefined
}
- /**
- * @memberof Splitter
- * fn to process verilog of the element
- * @return {JSON}
- */
- processVerilog() {
- if (
- this.inp1.verilogLabel !== '' &&
- this.outputs[0].verilogLabel === ''
- ) {
- let bitCount = 0
- for (let i = 0; i < this.splitCount; i++) {
- // let bitSplitValue = extractBits(this.inp1.value, bitCount, bitCount + this.bitWidthSplit[i] - 1);
- if (this.bitWidthSplit[i] > 1) {
- const label = `${this.inp1.verilogLabel}[ ${
- bitCount + this.bitWidthSplit[i] - 1
- }:${bitCount}]`
- } else {
- const label = `${this.inp1.verilogLabel}[${bitCount}]`
- }
- if (this.outputs[i].verilogLabel !== label) {
- this.outputs[i].verilogLabel = label
- this.scope.stack.push(this.outputs[i])
- }
- bitCount += this.bitWidthSplit[i]
- }
- } else if (
- this.inp1.verilogLabel === '' &&
- this.outputs[0].verilogLabel !== ''
- ) {
- const label = `{${this.outputs
- .map((x) => x.verilogLabel)
- .join(',')}}`
- if (this.inp1.verilogLabel !== label) {
- this.inp1.verilogLabel = label
- this.scope.stack.push(this.inp1)
- }
- }
- }
-
/**
* @memberof Splitter
* function to draw element
*/
customDraw() {
var ctx = simulationArea.context
- //
ctx.strokeStyle = [colors['splitter'], 'brown'][
((this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)) + 0
+ simulationArea.multipleObjectSelections.includes(this)) + 0
]
ctx.lineWidth = correctWidth(3)
const xx = this.x
@@ -280,13 +234,18 @@ export default class Splitter extends CircuitElement {
ctx.fill()
}
+ /**
+ * @memberof Splitter
+ * fn to process verilog of the element
+ * @return {JSON}
+ */
processVerilog() {
// Combiner
if (this.inp1.verilogLabel == '') {
this.isSplitter = false
this.inp1.verilogLabel = this.verilogLabel + '_cmb'
if (
- !this.scope.verilogWireList[this.bitWidth].contains(
+ !this.scope.verilogWireList[this.bitWidth].includes(
this.inp1.verilogLabel
)
)
diff --git a/v1/src/simulator/src/modules/SquareRGBLed.js b/v1/src/simulator/src/modules/SquareRGBLed.js
index b93e0bb6..c9bb5295 100644
--- a/v1/src/simulator/src/modules/SquareRGBLed.js
+++ b/v1/src/simulator/src/modules/SquareRGBLed.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, rect2 } from '../canvasApi'
/**
@@ -17,9 +17,6 @@ import { correctWidth, lineTo, moveTo, rect2 } from '../canvasApi'
export default class SquareRGBLed extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'UP', pinLength = 1) {
super(x, y, scope, dir, 8)
- /* this is done in this.baseSetup() now
- this.scope['SquareRGBLed'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 15)
this.pinLength = pinLength === undefined ? 1 : pinLength
@@ -146,7 +143,7 @@ export default class SquareRGBLed extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32)'
}
@@ -175,7 +172,7 @@ export default class SquareRGBLed extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = 'rgba(255, 255, 32)'
}
diff --git a/v1/src/simulator/src/modules/Stepper.js b/v1/src/simulator/src/modules/Stepper.js
index c6cfbd3f..7b0b0cb1 100644
--- a/v1/src/simulator/src/modules/Stepper.js
+++ b/v1/src/simulator/src/modules/Stepper.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { fillText } from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* Stepper
@@ -19,11 +18,7 @@ import { colors } from '../themer/themer'
export default class Stepper extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 8) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Stepper'].push(this);
- */
this.setDimensions(20, 20)
-
this.output1 = new Node(20, 0, 1, this, bitWidth)
this.state = 0
}
diff --git a/v1/src/simulator/src/modules/Text.js b/v1/src/simulator/src/modules/Text.js
index 7248c575..3713edbc 100644
--- a/v1/src/simulator/src/modules/Text.js
+++ b/v1/src/simulator/src/modules/Text.js
@@ -1,6 +1,5 @@
import CircuitElement from '../circuitElement'
-import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { rect2, fillText } from '../canvasApi'
/**
* @class
@@ -19,10 +18,6 @@ import { copy, paste } from '../events'
export default class Text extends CircuitElement {
constructor(x, y, scope = globalScope, label = '', fontSize = 14) {
super(x, y, scope, 'RIGHT', 1)
- /* this is done in this.baseSetup() now
- this.scope['Text'].push(this);
- */
- // this.setDimensions(15, 15);
this.fixedBitWidth = true
this.directionFixed = true
this.labelDirectionFixed = true
@@ -130,7 +125,7 @@ export default class Text extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.beginPath()
ctx.fillStyle = colors['fill']
diff --git a/v1/src/simulator/src/modules/TriState.js b/v1/src/simulator/src/modules/TriState.js
index e4048fc9..b408a0d9 100644
--- a/v1/src/simulator/src/modules/TriState.js
+++ b/v1/src/simulator/src/modules/TriState.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
-import { correctWidth, lineTo, moveTo, arc } from '../canvasApi'
-import { changeInputSize } from '../modules'
+import { simulationArea } from '../simulationArea'
+import { correctWidth, lineTo, moveTo } from '../canvasApi'
/**
* @class
* TriState
@@ -19,9 +18,6 @@ import { colors } from '../themer/themer'
export default class TriState extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['TriState'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 15)
@@ -29,9 +25,6 @@ export default class TriState extends CircuitElement {
this.output1 = new Node(20, 0, 1, this)
this.state = new Node(0, 0, 0, this, 1, 'Enable')
}
-
- // TriState.prototype.propagationDelay=10000;
-
/**
* @memberof TriState
* fn to create save Json Data of object
@@ -74,15 +67,14 @@ export default class TriState extends CircuitElement {
this.output1.value = this.inp1.value // >>>0)<<(32-this.bitWidth))>>>(32-this.bitWidth);
simulationArea.simulationQueue.add(this.output1)
}
- simulationArea.contentionPending.clean(this)
} else if (
this.output1.value !== undefined &&
- !simulationArea.contentionPending.contains(this)
+ !simulationArea.contentionPending.has(this.output1)
) {
this.output1.value = undefined
simulationArea.simulationQueue.add(this.output1)
}
- simulationArea.contentionPending.clean(this)
+ simulationArea.contentionPending.removeAllContentionsForNode(this.output1);
}
/**
@@ -104,7 +96,7 @@ export default class TriState extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/Tunnel.js b/v1/src/simulator/src/modules/Tunnel.js
index 7e3f96c5..d8acab0a 100644
--- a/v1/src/simulator/src/modules/Tunnel.js
+++ b/v1/src/simulator/src/modules/Tunnel.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect2, fillText } from '../canvasApi'
import plotArea from '../plotArea'
import { showError } from '../utils'
@@ -28,9 +28,6 @@ export default class Tunnel extends CircuitElement {
identifier
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['Tunnel'].push(this);
- */
this.rectangleObject = false
this.centerElement = true
this.xSize = 10
@@ -77,8 +74,6 @@ export default class Tunnel extends CircuitElement {
this.upDimensionY = Math.abs(-20 + yRotate)
this.rightDimensionX = Math.abs(xRotate)
this.downDimensionY = Math.abs(20 + yRotate)
-
- // rect2(ctx, -120 + xRotate + this.xSize, -20 + yRotate, 120 - this.xSize, 40, xx, yy, "RIGHT");
}
/**
@@ -174,13 +169,18 @@ export default class Tunnel extends CircuitElement {
* @param {string=} id - id so that every link is unique
*/
setIdentifier(id = '') {
- if (id.length === 0) return
- if (this.scope.tunnelList[this.identifier])
- this.scope.tunnelList[this.identifier].clean(this)
+ if (id.length === 0) {
+ return
+ }
+ if (this.scope.tunnelList[this.identifier]) {
+ this.scope.tunnelList[this.identifier] = this.scope.tunnelList[this.identifier].filter(x=> x !== this);
+ }
this.identifier = id
- if (this.scope.tunnelList[this.identifier])
+ if (this.scope.tunnelList[this.identifier]) {
this.scope.tunnelList[this.identifier].push(this)
- else this.scope.tunnelList[this.identifier] = [this]
+ } else {
+ this.scope.tunnelList[this.identifier] = [this]
+ }
// Change the bitwidth to be same as the other elements with this.identifier
if (
@@ -203,8 +203,8 @@ export default class Tunnel extends CircuitElement {
* delete the tunnel element
*/
delete() {
- this.scope.Tunnel.clean(this)
- this.scope.tunnelList[this.identifier].clean(this)
+ this.scope.Tunnel = this.scope.Tunnel.filter(x => x !== this);
+ this.scope.tunnelList[this.identifier] = this.scope.tunnelList[this.identifier].filter(x=> x !== this);
super.delete()
}
@@ -250,7 +250,7 @@ export default class Tunnel extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.fillStyle = colors['hover_select']
}
diff --git a/v1/src/simulator/src/modules/TwoComplement.js b/v1/src/simulator/src/modules/TwoComplement.js
index ace62ec7..88b35979 100644
--- a/v1/src/simulator/src/modules/TwoComplement.js
+++ b/v1/src/simulator/src/modules/TwoComplement.js
@@ -1,8 +1,7 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, fillText, drawCircle2 } from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* TwoComplement
@@ -19,9 +18,6 @@ import { colors } from '../themer/themer'
export default class TwoComplement extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['TwoComplement'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 15)
this.inp1 = new Node(-10, 0, 0, this, this.bitWidth, 'input stream')
@@ -77,7 +73,7 @@ export default class TwoComplement extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -98,5 +94,5 @@ export default class TwoComplement extends CircuitElement {
* @category modules
*/
TwoComplement.prototype.tooltipText =
- "Two's Complement Tooltip : Calculates the two's complement"
+ "Two's Complement ToolTip : Calculates the two's complement"
TwoComplement.prototype.objectType = 'TwoComplement'
diff --git a/v1/src/simulator/src/modules/VariableLed.js b/v1/src/simulator/src/modules/VariableLed.js
index a32cb5aa..bd9c5bef 100644
--- a/v1/src/simulator/src/modules/VariableLed.js
+++ b/v1/src/simulator/src/modules/VariableLed.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import {
correctWidth,
lineTo,
@@ -10,7 +10,6 @@ import {
colorToRGBA,
validColor,
} from '../canvasApi'
-import { changeInputSize } from '../modules'
/**
* @class
* VariableLed
@@ -24,14 +23,10 @@ import { colors } from '../themer/themer'
export default class VariableLed extends CircuitElement {
constructor(x, y, scope = globalScope, color = 'Red') {
- // Calling base class constructor
-
super(x, y, scope, 'UP', 8)
- /* this is done in this.baseSetup() now
- this.scope['VariableLed'].push(this);
- */
this.rectangleObject = false
this.setDimensions(10, 20)
+ this.downDimensionY = 40;
this.inp1 = new Node(-40, 0, 0, this, 8)
this.directionFixed = true
this.fixedBitWidth = true
@@ -120,16 +115,12 @@ export default class VariableLed extends CircuitElement {
lineTo(ctx, 0, -9, xx, yy, this.direction)
arc(ctx, 0, 0, 9, -Math.PI / 2, Math.PI / 2, xx, yy, this.direction)
lineTo(ctx, -20, 9, xx, yy, this.direction)
- /* lineTo(ctx,-18,12,xx,yy,this.direction);
- arc(ctx,0,0,Math.sqrt(468),((Math.PI/2) + Math.acos(12/Math.sqrt(468))),((-Math.PI/2) - Math.asin(18/Math.sqrt(468))),xx,yy,this.direction);
-
- */
lineTo(ctx, -20, -9, xx, yy, this.direction)
ctx.stroke()
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -157,7 +148,7 @@ export default class VariableLed extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected == this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = 'rgba(255, 255, 32,0.8)'
ctx.fill()
diff --git a/v1/src/simulator/src/modules/XnorGate.js b/v1/src/simulator/src/modules/XnorGate.js
index dd93e734..0a95867e 100644
--- a/v1/src/simulator/src/modules/XnorGate.js
+++ b/v1/src/simulator/src/modules/XnorGate.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import {
correctWidth,
bezierCurveTo,
@@ -35,9 +35,6 @@ export default class XnorGate extends CircuitElement {
bitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['XnorGate'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 20)
@@ -132,12 +129,11 @@ export default class XnorGate extends CircuitElement {
this.direction
)
bezierCurveTo(0, 0, 0, 0, -10, -20, xx, yy, this.direction)
- // arc(ctx, 0, 0, -20, (-Math.PI / 2), (Math.PI / 2), xx, yy, this.direction);
ctx.closePath()
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/modules/XorGate.js b/v1/src/simulator/src/modules/XorGate.js
index 74c5b0d8..067afd05 100644
--- a/v1/src/simulator/src/modules/XorGate.js
+++ b/v1/src/simulator/src/modules/XorGate.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, bezierCurveTo, moveTo, arc2 } from '../canvasApi'
import { changeInputSize } from '../modules'
import { gateGenerateVerilog } from '../utils'
@@ -29,9 +29,6 @@ export default class XorGate extends CircuitElement {
bitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['XorGate'].push(this);
- */
this.rectangleObject = false
this.setDimensions(15, 20)
@@ -125,12 +122,11 @@ export default class XorGate extends CircuitElement {
this.direction
)
bezierCurveTo(0, 0, 0, 0, -10, -20, xx, yy, this.direction)
- // arc(ctx, 0, 0, -20, (-Math.PI / 2), (Math.PI / 2), xx, yy, this.direction);
ctx.closePath()
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
@@ -161,7 +157,7 @@ export default class XorGate extends CircuitElement {
* @type {string}
* @category modules
*/
-XorGate.prototype.tooltipText = 'Xor Gate Tooltip : Implements an exclusive OR.'
+XorGate.prototype.tooltipText = 'Xor Gate ToolTip : Implements an exclusive OR.'
/**
* @memberof XorGate
diff --git a/v1/src/simulator/src/modules/verilogDivider.js b/v1/src/simulator/src/modules/verilogDivider.js
index cd6acaf5..c3421cc8 100644
--- a/v1/src/simulator/src/modules/verilogDivider.js
+++ b/v1/src/simulator/src/modules/verilogDivider.js
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
/**
* @class
@@ -24,9 +24,6 @@ export default class verilogDivider extends CircuitElement {
outputBitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['verilogDivider'].push(this);
- */
this.setDimensions(20, 20)
this.outputBitWidth = outputBitWidth
this.inpA = new Node(-20, -10, 0, this, this.bitWidth, 'A')
diff --git a/v1/src/simulator/src/modules/verilogMultiplier.js b/v1/src/simulator/src/modules/verilogMultiplier.js
index d428c036..2e3a41db 100644
--- a/v1/src/simulator/src/modules/verilogMultiplier.js
+++ b/v1/src/simulator/src/modules/verilogMultiplier.js
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
/**
* @class
@@ -24,9 +24,6 @@ export default class verilogMultiplier extends CircuitElement {
outputBitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['verilogMultiplier'].push(this);
- */
this.setDimensions(20, 20)
this.outputBitWidth = outputBitWidth
this.inpA = new Node(-20, -10, 0, this, this.bitWidth, 'A')
diff --git a/v1/src/simulator/src/modules/verilogPower.js b/v1/src/simulator/src/modules/verilogPower.js
index ded6fdc1..10f764fa 100644
--- a/v1/src/simulator/src/modules/verilogPower.js
+++ b/v1/src/simulator/src/modules/verilogPower.js
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
/**
* @class
@@ -24,9 +24,6 @@ export default class verilogPower extends CircuitElement {
outputBitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['verilogPower'].push(this);
- */
this.setDimensions(20, 20)
this.outputBitWidth = outputBitWidth
this.inpA = new Node(-20, -10, 0, this, this.bitWidth, 'A')
diff --git a/v1/src/simulator/src/modules/verilogShiftLeft.js b/v1/src/simulator/src/modules/verilogShiftLeft.js
index 65a61a4c..012fa63f 100644
--- a/v1/src/simulator/src/modules/verilogShiftLeft.js
+++ b/v1/src/simulator/src/modules/verilogShiftLeft.js
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
/**
* @class
@@ -24,9 +24,6 @@ export default class verilogShiftLeft extends CircuitElement {
outputBitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['verilogShiftLeft'].push(this);
- */
this.setDimensions(20, 20)
this.outputBitWidth = outputBitWidth
this.inp1 = new Node(-20, -10, 0, this, this.bitWidth, 'Input')
diff --git a/v1/src/simulator/src/modules/verilogShiftRight.js b/v1/src/simulator/src/modules/verilogShiftRight.js
index a37332fb..5aad5c23 100644
--- a/v1/src/simulator/src/modules/verilogShiftRight.js
+++ b/v1/src/simulator/src/modules/verilogShiftRight.js
@@ -1,7 +1,7 @@
/* eslint-disable no-bitwise */
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
/**
* @class
@@ -24,9 +24,6 @@ export default class verilogShiftRight extends CircuitElement {
outputBitWidth = 1
) {
super(x, y, scope, dir, bitWidth)
- /* this is done in this.baseSetup() now
- this.scope['verilogShiftRight'].push(this);
- */
this.setDimensions(20, 20)
this.outputBitWidth = outputBitWidth
this.inp1 = new Node(-20, -10, 0, this, this.bitWidth, 'Input')
diff --git a/v1/src/simulator/src/node.js b/v1/src/simulator/src/node.js
index 696a664b..c81f781a 100644
--- a/v1/src/simulator/src/node.js
+++ b/v1/src/simulator/src/node.js
@@ -1,6 +1,6 @@
/* eslint-disable import/no-cycle */
import { drawCircle, drawLine, arc } from './canvasApi'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import { distance, showError } from './utils'
import {
renderCanvas,
@@ -12,8 +12,8 @@ import {
canvasMessageData,
} from './engine'
import Wire from './wire'
-// import { colors } from './themer/themer';
import { colors } from './themer/themer'
+import ContentionMeta from './contention'
/**
* Constructs all the connections of Node node
@@ -24,7 +24,7 @@ import { colors } from './themer/themer'
export function constructNodeConnections(node, data) {
for (var i = 0; i < data.connections.length; i++) {
if (
- !node.connections.contains(node.scope.allNodes[data.connections[i]])
+ !node.connections.includes(node.scope.allNodes[data.connections[i]])
)
node.connect(node.scope.allNodes[data.connections[i]])
}
@@ -42,12 +42,13 @@ export function replace(node, index) {
}
var { scope } = node
var { parent } = node
- parent.nodeList.clean(node)
+ parent.nodeList = parent.nodeList.filter(x=> x !== node);
node.delete()
node = scope.allNodes[index]
node.parent = parent
parent.nodeList.push(node)
node.updateRotation()
+ node.scope.timeStamp = new Date().getTime()
return node
}
function rotate(x1, y1, dir) {
@@ -162,7 +163,7 @@ export default class Node {
this.id = `node${uniqueIdCounter}`
uniqueIdCounter++
this.parent = parent
- if (type != 2 && this.parent.nodeList !== undefined) {
+ if (type != NODE_INTERMEDIATE && this.parent.nodeList !== undefined) {
this.parent.nodeList.push(this)
}
@@ -187,6 +188,7 @@ export default class Node {
this.hover = false
this.wasClicked = false
this.scope = this.parent.scope
+ this.scope.timeStamp = new Date().getTime()
/**
* @type {string}
* value of this.prev is
@@ -201,7 +203,7 @@ export default class Node {
// This fn is called during rotations and setup
this.refresh()
- if (this.type == 2) {
+ if (this.type == NODE_INTERMEDIATE) {
this.parent.scope.nodes.push(this)
}
@@ -226,7 +228,7 @@ export default class Node {
* function to convert a node to intermediate node
*/
converToIntermediate() {
- this.type = 2
+ this.type = NODE_INTERMEDIATE
this.x = this.absX()
this.y = this.absY()
this.parent = this.scope.root
@@ -250,10 +252,10 @@ export default class Node {
}
/**
- * Funciton for saving a node
+ * function for saving a node
*/
saveObject() {
- if (this.type == 2) {
+ if (this.type == NODE_INTERMEDIATE) {
this.leftx = this.x
this.lefty = this.y
}
@@ -288,8 +290,9 @@ export default class Node {
refresh() {
this.updateRotation()
for (var i = 0; i < this.connections.length; i++) {
- this.connections[i].connections.clean(this)
+ this.connections[i].connections = this.connections[i].connections.filter(x => x !== this)
}
+ this.scope.timeStamp = new Date().getTime()
this.connections = []
}
@@ -312,7 +315,7 @@ export default class Node {
*/
updateScope(scope) {
this.scope = scope
- if (this.type == 2) this.parent = scope.root
+ if (this.type == NODE_INTERMEDIATE) this.parent = scope.root
}
/**
@@ -335,11 +338,15 @@ export default class Node {
*/
connect(n) {
if (n == this) return
- if (n.connections.contains(this)) return
- var w = new Wire(this, n, this.parent.scope)
+ if (n.connections.includes(this)) {
+ return
+ }
+ new Wire(this, n, this.parent.scope)
this.connections.push(n)
n.connections.push(this)
+ this.scope.timeStamp = new Date().getTime()
+
updateCanvasSet(true)
updateSimulationSet(true)
scheduleUpdate()
@@ -350,11 +357,13 @@ export default class Node {
*/
connectWireLess(n) {
if (n == this) return
- if (n.connections.contains(this)) return
+ if (n.connections.includes(this)) return
this.connections.push(n)
n.connections.push(this)
- updateCanvasSet(true)
+ this.scope.timeStamp = new Date().getTime()
+
+ // updateCanvasSet(true)
updateSimulationSet(true)
scheduleUpdate()
}
@@ -363,14 +372,22 @@ export default class Node {
* disconnecting two nodes connected wirelessly
*/
disconnectWireLess(n) {
- this.connections.clean(n)
- n.connections.clean(this)
+ this.connections = this.connections.filter(x => x !== n)
+ n.connections = n.connections.filter(x => x !== this)
+
+ this.scope.timeStamp = new Date().getTime()
}
/**
* function to resolve a node
*/
resolve() {
+ if (this.type == NODE_OUTPUT) {
+ // Since output node forces its value on its neighbours, remove its contentions.
+ // An existing contention will now trickle to the other output node that was causing
+ // the contention.
+ simulationArea.contentionPending.removeAllContentionsForNode(this);
+ }
// Remove Propogation of values (TriState)
if (this.value == undefined) {
for (var i = 0; i < this.connections.length; i++) {
@@ -395,7 +412,7 @@ export default class Node {
this.parent.isResolvable() &&
!this.parent.queueProperties.inQueue
) {
- if (this.parent.objectType == 'TriState') {
+ if (this.parent.objectType == 'TriState' || this.parent.objectType == 'ControlledInverter') {
if (this.parent.state.value) {
simulationArea.simulationQueue.add(this.parent)
}
@@ -408,52 +425,69 @@ export default class Node {
return
}
- if (this.type == 0) {
+ // For input nodes, resolve its parents if they are resolvable at this point.
+ if (this.type == NODE_INPUT) {
if (this.parent.isResolvable()) {
simulationArea.simulationQueue.add(this.parent)
}
}
+ else if (this.type == NODE_OUTPUT) {
+ // Since output node forces its value on its neighbours, remove its contentions.
+ // An existing contention will now trickle to the other output node that was causing
+ // the contention.
+ simulationArea.contentionPending.removeAllContentionsForNode(this);
+ }
for (var i = 0; i < this.connections.length; i++) {
- const node = this.connections[i]
-
- if (node.value != this.value || node.bitWidth != this.bitWidth) {
- if (
- node.type == 1 &&
- node.value != undefined &&
- node.parent.objectType != 'TriState' &&
- !(node.subcircuitOverride && node.scope != this.scope) && // Subcircuit Input Node Output Override
- node.parent.objectType != 'SubCircuit'
- ) {
- // Subcircuit Output Node Override
- this.highlighted = true
- node.highlighted = true
- var circuitName = node.scope.name
- var circuitElementName = node.parent.objectType
- showError(
- `Contention Error: ${this.value} and ${node.value} at ${circuitElementName} in ${circuitName}`
- )
- } else if (node.bitWidth == this.bitWidth || node.type == 2) {
- if (
- node.parent.objectType == 'TriState' &&
- node.value != undefined &&
- node.type == 1
- ) {
- if (node.parent.state.value) {
- simulationArea.contentionPending.push(node.parent)
+ const node = this.connections[i];
+
+ switch (node.type) {
+ // TODO: For an output node, a downstream value (value given by elements other than the parent)
+ // should be overwritten in contention check and should not cause contention.
+ case NODE_OUTPUT:
+ if (node.value != this.value || node.bitWidth != this.bitWidth) {
+ // Check contentions
+ if (node.value != undefined && node.parent.objectType != 'SubCircuit'
+ && !(node.subcircuitOverride && node.scope != this.scope)) {
+ // Tristate has always been a pain in the ass.
+ if ((node.parent.objectType == 'TriState' || node.parent.objectType == 'ControlledInverter') && node.value != undefined) {
+ if (node.parent.state.value) {
+ simulationArea.contentionPending.add(node, this);
+ break;
+ }
+ }
+ else {
+ simulationArea.contentionPending.add(node, this);
+ break;
}
}
-
- node.bitWidth = this.bitWidth
- node.value = this.value
- simulationArea.simulationQueue.add(node)
} else {
- this.highlighted = true
- node.highlighted = true
- showError(
- `BitWidth Error: ${this.bitWidth} and ${node.bitWidth}`
- )
+ // Output node was given an agreeing value, so remove any contention
+ // entry between these two nodes if it exists.
+ simulationArea.contentionPending.remove(node, this);
+ }
+
+ // Fallthrough. NODE_OUTPUT propagates like a contention checked NODE_INPUT
+ case NODE_INPUT:
+ // Check bitwidths
+ if (this.bitWidth != node.bitWidth) {
+ this.highlighted = true;
+ node.highlighted = true;
+ showError(`BitWidth Error: ${this.bitWidth} and ${node.bitWidth}`);
+ break;
}
+
+ // Fallthrough. NODE_INPUT propagates like a bitwidth checked NODE_INTERMEDIATE
+ case NODE_INTERMEDIATE:
+
+ if (node.value != this.value || node.bitWidth != this.bitWidth) {
+ // Propagate
+ node.bitWidth = this.bitWidth;
+ node.value = this.value;
+ simulationArea.simulationQueue.add(node);
+ }
+ default:
+ break;
}
}
}
@@ -563,8 +597,8 @@ export default class Node {
if (this.bitWidth == 1)
colorNode = [colorNodeConnect, colorNodePow][this.value]
if (this.value == undefined) colorNode = colorNodeLose
- if (this.type == 2) this.checkHover()
- if (this.type == 2) {
+ if (this.type == NODE_INTERMEDIATE) this.checkHover()
+ if (this.type == NODE_INTERMEDIATE) {
drawCircle(ctx, this.absX(), this.absY(), 3, colorNode)
} else {
drawCircle(ctx, this.absX(), this.absY(), 3, colorNodeSelected)
@@ -576,7 +610,7 @@ export default class Node {
(this.isHover() &&
!simulationArea.selected &&
!simulationArea.shiftDown) ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
ctx.strokeStyle = colorNodeSelected
ctx.beginPath()
@@ -600,7 +634,7 @@ export default class Node {
if (this.showHover || simulationArea.lastSelected == this) {
canvasMessageData.x = this.absX()
canvasMessageData.y = this.absY() - 15
- if (this.type == 2) {
+ if (this.type == NODE_INTERMEDIATE) {
var v = 'X'
if (this.value !== undefined) {
v = this.value.toString(16)
@@ -629,7 +663,7 @@ export default class Node {
*/
checkDeleted() {
if (this.deleted) this.delete()
- if (this.connections.length == 0 && this.type == 2) this.delete()
+ if (this.connections.length == 0 && this.type == NODE_INTERMEDIATE) this.delete()
}
/**
@@ -670,10 +704,10 @@ export default class Node {
if (!this.wasClicked && this.clicked) {
this.wasClicked = true
this.prev = 'a'
- if (this.type == 2) {
+ if (this.type == NODE_INTERMEDIATE) {
if (
!simulationArea.shiftDown &&
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
for (
var i = 0;
@@ -689,9 +723,9 @@ export default class Node {
if (simulationArea.shiftDown) {
simulationArea.lastSelected = undefined
if (
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
- simulationArea.multipleObjectSelections.clean(this)
+ simulationArea.multipleObjectSelections = simulationArea.multipleObjectSelections.filter(x=> x !== this);
} else {
simulationArea.multipleObjectSelections.push(this)
}
@@ -702,7 +736,7 @@ export default class Node {
} else if (this.wasClicked && this.clicked) {
if (
!simulationArea.shiftDown &&
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
) {
for (
var i = 0;
@@ -712,7 +746,7 @@ export default class Node {
simulationArea.multipleObjectSelections[i].drag()
}
}
- if (this.type == 2) {
+ if (this.type == NODE_INTERMEDIATE) {
if (
this.connections.length == 1 &&
this.connections[0].absX() == simulationArea.mouseX &&
@@ -881,7 +915,7 @@ export default class Node {
simulationArea.lastSelected = n2
}
- if (this.type == 2 && simulationArea.mouseDown == false) {
+ if (this.type == NODE_INTERMEDIATE && simulationArea.mouseDown == false) {
if (this.connections.length == 2) {
if (
this.connections[0].absX() == this.connections[1].absX() ||
@@ -900,17 +934,20 @@ export default class Node {
delete() {
updateSimulationSet(true)
this.deleted = true
- this.parent.scope.allNodes.clean(this)
- this.parent.scope.nodes.clean(this)
+ this.parent.scope.allNodes = this.parent.scope.allNodes.filter(x => x !== this)
+ this.parent.scope.nodes = this.parent.scope.nodes.filter(x => x !== this)
- this.parent.scope.root.nodeList.clean(this) // Hope this works! - Can cause bugs
+ this.parent.scope.root.nodeList = this.parent.scope.root.nodeList.filter(x => x !== this) // Hope this works! - Can cause bugs
if (simulationArea.lastSelected == this)
simulationArea.lastSelected = undefined
for (var i = 0; i < this.connections.length; i++) {
- this.connections[i].connections.clean(this)
+ this.connections[i].connections = this.connections[i].connections.filter(x => x !== this)
this.connections[i].checkDeleted()
}
+
+ this.scope.timeStamp = new Date().getTime()
+
wireToBeCheckedSet(1)
forceResetNodesSet(true)
scheduleUpdate()
@@ -947,7 +984,7 @@ export default class Node {
y == this.parent.scope.allNodes[i].absY()
) {
n = this.parent.scope.allNodes[i]
- if (this.type == 2) {
+ if (this.type == NODE_INTERMEDIATE) {
for (var j = 0; j < this.connections.length; j++) {
n.connect(this.connections[j])
}
@@ -964,7 +1001,7 @@ export default class Node {
for (var i = 0; i < this.parent.scope.wires.length; i++) {
if (this.parent.scope.wires[i].checkConvergence(this)) {
var n = this
- if (this.type != 2) {
+ if (this.type != NODE_INTERMEDIATE) {
n = new Node(
this.absX(),
this.absY(),
diff --git a/v1/src/simulator/src/plotArea.js b/v1/src/simulator/src/plotArea.js
index 79bf2582..869d27ac 100644
--- a/v1/src/simulator/src/plotArea.js
+++ b/v1/src/simulator/src/plotArea.js
@@ -1,5 +1,10 @@
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import { convertors } from './utils'
+import { join, downloadDir } from '@tauri-apps/api/path';
+import { writeFile } from '@tauri-apps/plugin-fs';
+import { isTauri } from '@tauri-apps/api/core'
+import { useSimulatorMobileStore } from '#/store/simulatorMobileStore'
+import { toRefs } from 'vue'
var DPR = window.devicePixelRatio || 1
@@ -106,12 +111,43 @@ const plotArea = {
},
// download as image
download() {
+ if(isTauri()){
+ this.downloadImageDesktop()
+ return
+ }
+
var img = this.canvas.toDataURL(`image/png`)
const anchor = document.createElement('a')
anchor.href = img
anchor.download = `waveform.png`
anchor.click()
},
+ // download as image for desktop
+ async downloadImageDesktop() {
+ try {
+ const img = this.canvas.toDataURL('image/png');
+
+ const response = await fetch(img);
+ const blob = await response.blob();
+
+ const arrayBuffer = await new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onloadend = () => resolve(reader.result);
+ reader.onerror = reject;
+ reader.readAsArrayBuffer(blob);
+ });
+
+ const downloadsDirectory = await downloadDir();
+
+ const random = Math.random().toString(36).substring(7);
+
+ const path = await join(downloadsDirectory, `waveform-${random}.png`);
+
+ await writeFile({ path, contents: new Uint8Array(arrayBuffer) });
+ } catch (error) {
+ console.error('Error during download:', error);
+ }
+ },
// update canvas size to use full screen
resize() {
var oldHeight = this.height
@@ -403,12 +439,16 @@ const plotArea = {
},
// Driver function to render and update
plot() {
+ const simulatorMobileStore = useSimulatorMobileStore()
+ const { showCanvas } = toRefs(simulatorMobileStore)
if (embed) return
if (globalScope.Flag.length === 0) {
this.canvas.width = 0
this.canvas.height = 0
+ showCanvas.value = false
return
}
+ showCanvas.value = true
this.update()
this.render()
@@ -445,52 +485,6 @@ const timingDiagramButtonActions = {
export { timingDiagramButtonActions }
export function setupTimingListeners() {
- // $('.timing-diagram-smaller').on('click', () => {
- // $('#plot').width(Math.max($('#plot').width() - 20, 560))
- // plotArea.resize()
- // })
- // $('.timing-diagram-larger').on('click', () => {
- // $('#plot').width($('#plot').width() + 20)
- // plotArea.resize()
- // })
- // $('.timing-diagram-small-height').on('click', () => {
- // if (plotHeight >= sh(20)) {
- // plotHeight -= sh(5)
- // waveFormHeight = plotHeight - 2 * waveFormPadding
- // }
- // })
- // $('.timing-diagram-large-height').on('click', () => {
- // if (plotHeight < sh(50)) {
- // plotHeight += sh(5)
- // waveFormHeight = plotHeight - 2 * waveFormPadding
- // }
- // })
- // $('.timing-diagram-reset').on('click', () => {
- // plotArea.reset()
- // })
- // $('.timing-diagram-calibrate').on('click', () => {
- // plotArea.calibrate()
- // })
- // $('.timing-diagram-resume').on('click', () => {
- // plotArea.resume()
- // })
- // $('.timing-diagram-pause').on('click', () => {
- // plotArea.pause()
- // })
- // $('.timing-diagram-download').on('click', () => {
- // plotArea.download()
- // })
- // $('.timing-diagram-zoom-in').on('click', () => {
- // plotArea.zoomIn()
- // })
- // $('.timing-diagram-zoom-out').on('click', () => {
- // plotArea.zoomOut()
- // })
- // $('#timing-diagram-units').on('change paste keyup', function () {
- // var timeUnits = parseInt($(this).val(), 10)
- // if (isNaN(timeUnits) || timeUnits < 1) return
- // plotArea.cycleUnit = timeUnits
- // })
document.getElementById('plotArea').addEventListener('mousedown', (e) => {
var rect = plotArea.canvas.getBoundingClientRect()
var x = sh(e.clientX - rect.left)
diff --git a/v0/src/simulator/src/quinMcCluskey.js b/v1/src/simulator/src/quinMcCluskey.ts
similarity index 84%
rename from v0/src/simulator/src/quinMcCluskey.js
rename to v1/src/simulator/src/quinMcCluskey.ts
index f15041db..5983fb47 100644
--- a/v0/src/simulator/src/quinMcCluskey.js
+++ b/v1/src/simulator/src/quinMcCluskey.ts
@@ -1,11 +1,18 @@
// Algorithm used for Combinational Analysis
+type BooleanMinimizeType = {
+ minTerms: number[]
+ dontCares: number[]
+ numVars: number
+ result: string[]
+}
+
export default function BooleanMinimize(
- numVarsArg,
- minTermsArg,
- dontCaresArg = []
+ numVarsArg: number,
+ minTermsArg: number[],
+ dontCaresArg: number[] = []
) {
- var __result
+ var __result: string[]
Object.defineProperties(this, {
minTerms: {
@@ -47,7 +54,7 @@ export default function BooleanMinimize(
}
BooleanMinimize.prototype.solve = function () {
- function dec_to_binary_string(n) {
+ const dec_to_binary_string = (n: number) => {
var str = n.toString(2)
while (str.length != this.numVars) {
@@ -57,14 +64,14 @@ BooleanMinimize.prototype.solve = function () {
return str
}
- function num_set_bits(s) {
+ const num_set_bits = (s: string) => {
var ans = 0
for (let i = 0; i < s.length; ++i) if (s[i] === '1') ans++
return ans
}
- function get_prime_implicants(allTerms) {
- var table = []
+ const get_prime_implicants = (allTerms: string[]) => {
+ var table: Set[] = []
var primeImplicants = new Set()
var reduced
@@ -115,11 +122,11 @@ BooleanMinimize.prototype.solve = function () {
return primeImplicants
}
- function get_essential_prime_implicants(primeImplicants, minTerms) {
+ const get_essential_prime_implicants = (primeImplicants: string[], minTerms: string[]) => {
var table = [],
column
- function check_if_similar(minTerm, primeImplicant) {
+ const check_if_similar = (minTerm: string, primeImplicant: string) => {
for (let i = 0; i < primeImplicant.length; ++i) {
if (
primeImplicant[i] !== '-' &&
@@ -131,7 +138,7 @@ BooleanMinimize.prototype.solve = function () {
return true
}
- function get_complexity(terms) {
+ const get_complexity = (terms: string[]) => {
var complexity = terms.length
for (let t of terms) {
@@ -146,7 +153,7 @@ BooleanMinimize.prototype.solve = function () {
return complexity
}
- function isSubset(sub, sup) {
+ const isSubset = (sub: Set, sup: Set) => {
for (let i of sub) {
if (!sup.has(i)) return false
}
@@ -166,8 +173,8 @@ BooleanMinimize.prototype.solve = function () {
table.push(column)
}
- var possibleSets = [],
- tempSets
+ let possibleSets: Set[] = [],
+ tempSets: Set[]
for (let i of table[0]) {
possibleSets.push(new Set([i]))
@@ -216,12 +223,12 @@ BooleanMinimize.prototype.solve = function () {
return essentialImplicants
}
- var minTerms = this.minTerms.map(dec_to_binary_string.bind(this))
- var dontCares = this.dontCares.map(dec_to_binary_string.bind(this))
+ var minTerms: string[] = this.minTerms.map(dec_to_binary_string.bind(this))
+ var dontCares: string[] = this.dontCares.map(dec_to_binary_string.bind(this))
return get_essential_prime_implicants.call(
this,
- Array.from(get_prime_implicants.call(this, minTerms.concat(dontCares))),
+ Array.from(get_prime_implicants.call(this, minTerms.concat(dontCares))) as string[],
minTerms
)
}
diff --git a/v1/src/simulator/src/sequential.js b/v1/src/simulator/src/sequential.js
index bd1740de..46dcd693 100644
--- a/v1/src/simulator/src/sequential.js
+++ b/v1/src/simulator/src/sequential.js
@@ -1,5 +1,5 @@
import { scheduleUpdate, play, updateCanvasSet } from './engine'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
/**
* a global function as a helper for simulationArea.changeClockEnable
@@ -8,18 +8,3 @@ import simulationArea from './simulationArea'
export function changeClockEnable(val) {
simulationArea.clockEnabled = val
}
-
-/**
- * WIP function defined and used
- * @param {number} n
- * @category sequential
- */
-export function runTest(n = 10) {
- var t = new Date().getTime()
- for (var i = 0; i < n; i++) {
- clockTick()
- }
- updateCanvasSet(true)
- play()
- scheduleUpdate()
-}
diff --git a/v1/src/simulator/src/sequential/Clock.js b/v1/src/simulator/src/sequential/Clock.js
index 86e24955..fcfac673 100644
--- a/v1/src/simulator/src/sequential/Clock.js
+++ b/v1/src/simulator/src/sequential/Clock.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo } from '../canvasApi'
import { colors } from '../themer/themer'
/**
@@ -17,9 +17,6 @@ import { colors } from '../themer/themer'
export default class Clock extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT') {
super(x, y, scope, dir, 1)
- /*
- this.scope['Clock'].push(this);
- */
this.fixedBitWidth = true
this.output1 = new Node(10, 0, 1, this, 1)
this.state = 0
diff --git a/v1/src/simulator/src/sequential/DflipFlop.js b/v1/src/simulator/src/sequential/DflipFlop.js
index 4543ba61..f21fe2a1 100644
--- a/v1/src/simulator/src/sequential/DflipFlop.js
+++ b/v1/src/simulator/src/sequential/DflipFlop.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText } from '../canvasApi'
import { colors } from '../themer/themer'
/**
@@ -18,9 +18,6 @@ import { colors } from '../themer/themer'
export default class DflipFlop extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /*
- this.scope['DflipFlop'].push(this);
- */
this.directionFixed = true
this.setDimensions(20, 20)
this.rectangleObject = true
@@ -43,9 +40,6 @@ export default class DflipFlop extends CircuitElement {
*/
isResolvable() {
return true
- // if (this.reset.value == 1) return true;
- // if (this.clockInp.value != undefined && this.dInp.value != undefined) return true;
- // return false;
}
newBitWidth(bitWidth) {
@@ -116,7 +110,6 @@ export default class DflipFlop extends CircuitElement {
customDraw() {
var ctx = simulationArea.context
- //
ctx.strokeStyle = colors['stroke']
ctx.fillStyle = colors['fill']
ctx.beginPath()
@@ -127,7 +120,6 @@ export default class DflipFlop extends CircuitElement {
moveTo(ctx, -20, 5, xx, yy, this.direction)
lineTo(ctx, -15, 10, xx, yy, this.direction)
lineTo(ctx, -20, 15, xx, yy, this.direction)
- // if ((this.b.hover&&!simulationArea.shiftDown)|| simulationArea.lastSelected == this || simulationArea.multipleObjectSelections.contains(this)) ctx.fillStyle = "rgba(255, 255, 32,0.8)";ctx.fill();
ctx.stroke()
ctx.beginPath()
diff --git a/v1/src/simulator/src/sequential/Dlatch.js b/v1/src/simulator/src/sequential/Dlatch.js
index 7532d3db..cc3b7097 100644
--- a/v1/src/simulator/src/sequential/Dlatch.js
+++ b/v1/src/simulator/src/sequential/Dlatch.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText } from '../canvasApi'
/**
* @class
@@ -20,9 +20,6 @@ import { colors } from '../themer/themer'
export default class Dlatch extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
super(x, y, scope, dir, bitWidth)
- /*
- this.scope['Dlatch'].push(this);
- */
this.directionFixed = true
this.setDimensions(20, 20)
this.rectangleObject = true
@@ -30,16 +27,13 @@ export default class Dlatch extends CircuitElement {
this.dInp = new Node(-20, -10, 0, this, this.bitWidth, 'D')
this.qOutput = new Node(20, -10, 1, this, this.bitWidth, 'Q')
this.qInvOutput = new Node(20, 10, 1, this, this.bitWidth, 'Q Inverse')
- // this.reset = new Node(10, 20, 0, this, 1, "Asynchronous Reset");
- // this.preset = new Node(0, 20, 0, this, this.bitWidth, "Preset");
- // this.en = new Node(-10, 20, 0, this, 1, "Enable");
this.state = 0
this.prevClockState = 0
this.wasClicked = false
}
/**
- * Idea: shoould be D FF?
+ * Idea: should be D FF?
*/
isResolvable() {
if (this.clockInp.value != undefined && this.dInp.value != undefined)
@@ -52,7 +46,6 @@ export default class Dlatch extends CircuitElement {
this.dInp.bitWidth = bitWidth
this.qOutput.bitWidth = bitWidth
this.qInvOutput.bitWidth = bitWidth
- // this.preset.bitWidth = bitWidth;
}
/**
@@ -80,9 +73,6 @@ export default class Dlatch extends CircuitElement {
dInp: findNode(this.dInp),
qOutput: findNode(this.qOutput),
qInvOutput: findNode(this.qInvOutput),
- // reset: findNode(this.reset),
- // preset: findNode(this.preset),
- // en: findNode(this.en),
},
constructorParamaters: [this.direction, this.bitWidth],
}
@@ -97,11 +87,9 @@ export default class Dlatch extends CircuitElement {
ctx.lineWidth = correctWidth(3)
var xx = this.x
var yy = this.y
- // rect(ctx, xx - 20, yy - 20, 40, 40);
moveTo(ctx, -20, 5, xx, yy, this.direction)
lineTo(ctx, -15, 10, xx, yy, this.direction)
lineTo(ctx, -20, 15, xx, yy, this.direction)
- // if ((this.b.hover&&!simulationArea.shiftDown)|| simulationArea.lastSelected == this || simulationArea.multipleObjectSelections.contains(this)) ctx.fillStyle = "rgba(255, 255, 32,0.8)";ctx.fill();
ctx.stroke()
ctx.beginPath()
ctx.font = '20px Raleway'
diff --git a/v1/src/simulator/src/sequential/EEPROM.js b/v1/src/simulator/src/sequential/EEPROM.js
index 3a3427b8..f2e13636 100644
--- a/v1/src/simulator/src/sequential/EEPROM.js
+++ b/v1/src/simulator/src/sequential/EEPROM.js
@@ -31,9 +31,6 @@ export default class EEPROM extends RAM {
data = null
) {
super(x, y, scope, dir, bitWidth, addressWidth)
- /*
- this.scope['EEPROM'].push(this);
- */
this.data = data || this.data
}
diff --git a/v1/src/simulator/src/sequential/ForceGate.js b/v1/src/simulator/src/sequential/ForceGate.js
new file mode 100644
index 00000000..332af06c
--- /dev/null
+++ b/v1/src/simulator/src/sequential/ForceGate.js
@@ -0,0 +1,92 @@
+import CircuitElement from '../circuitElement'
+import Node, { findNode } from '../node'
+import { simulationArea } from '../simulationArea'
+import { fillText4 } from '../canvasApi'
+/**
+ * @class
+ * ForceGate
+ * @extends CircuitElement
+ * @param {number} x - x coordinate of element.
+ * @param {number} y - y coordinate of element.
+ * @param {Scope=} scope - Cirucit on which element is drawn
+ * @param {string=} dir - direction of element
+ * @param {number=} bitWidth - bit width per node.
+ * @category testbench
+ */
+export default class ForceGate extends CircuitElement {
+ constructor(x, y, scope = globalScope, dir = 'RIGHT', bitWidth = 1) {
+ super(x, y, scope, dir, bitWidth)
+ this.setDimensions(20, 10)
+ this.objectType = 'ForceGate'
+ this.scope.ForceGate.push(this)
+ this.inp1 = new Node(-20, 0, 0, this)
+ this.inp2 = new Node(0, 0, 0, this)
+ this.output1 = new Node(20, 0, 1, this)
+ }
+
+ /**
+ * @memberof ForceGate
+ * Checks if the element is resolvable
+ * @return {boolean}
+ */
+ isResolvable() {
+ return this.inp1.value !== undefined || this.inp2.value !== undefined
+ }
+
+ /**
+ * @memberof ForceGate
+ * fn to create save Json Data of object
+ * @return {JSON}
+ */
+ customSave() {
+ const data = {
+ constructorParamaters: [this.direction, this.bitWidth],
+ nodes: {
+ output1: findNode(this.output1),
+ inp1: findNode(this.inp1),
+ inp2: findNode(this.inp2),
+ },
+ }
+ return data
+ }
+
+ /**
+ * @memberof ForceGate
+ * resolve output values based on inputData
+ */
+ resolve() {
+ if (this.inp2.value !== undefined) {
+ this.output1.value = this.inp2.value
+ } else {
+ this.output1.value = this.inp1.value
+ }
+ simulationArea.simulationQueue.add(this.output1)
+ }
+
+ /**
+ * @memberof ForceGate
+ * function to draw element
+ */
+ customDraw() {
+ var ctx = simulationArea.context
+ const xx = this.x
+ const yy = this.y
+
+ ctx.beginPath()
+ ctx.fillStyle = 'Black'
+ ctx.textAlign = 'center'
+
+ fillText4(ctx, 'I', -10, 0, xx, yy, this.direction, 10)
+ fillText4(ctx, 'O', 10, 0, xx, yy, this.direction, 10)
+ ctx.fill()
+ }
+}
+
+/**
+ * @memberof ForceGate
+ * Help Tip
+ * @type {string}
+ * @category testbench
+ */
+ForceGate.prototype.tooltipText = 'Force Gate ToolTip : ForceGate Selected.'
+ForceGate.prototype.objectType = 'ForceGate'
diff --git a/v1/src/simulator/src/sequential/JKflipFlop.js b/v1/src/simulator/src/sequential/JKflipFlop.js
index c02eae3f..4f975c79 100644
--- a/v1/src/simulator/src/sequential/JKflipFlop.js
+++ b/v1/src/simulator/src/sequential/JKflipFlop.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText } from '../canvasApi'
/**
* @class
@@ -18,9 +18,6 @@ import { colors } from '../themer/themer'
export default class JKflipFlop extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT') {
super(x, y, scope, dir, 1)
- /*
- this.scope['JKflipFlop'].push(this);
- */
this.directionFixed = true
this.fixedBitWidth = true
this.setDimensions(20, 20)
@@ -37,8 +34,6 @@ export default class JKflipFlop extends CircuitElement {
this.slaveState = 0
this.masterState = 0
this.prevClockState = 0
-
- // this.wasClicked = false;
}
/**
@@ -139,13 +134,9 @@ export default class JKflipFlop extends CircuitElement {
ctx.lineWidth = correctWidth(3)
var xx = this.x
var yy = this.y
-
- // rect(ctx, xx - 20, yy - 20, 40, 40);
moveTo(ctx, -20, 5, xx, yy, this.direction)
lineTo(ctx, -15, 10, xx, yy, this.direction)
lineTo(ctx, -20, 15, xx, yy, this.direction)
-
- // if ((this.b.hover&&!simulationArea.shiftDown)|| simulationArea.lastSelected == this || simulationArea.multipleObjectSelections.contains(this)) ctx.fillStyle = "rgba(255, 255, 32,0.8)";ctx.fill();
ctx.stroke()
ctx.beginPath()
diff --git a/v1/src/simulator/src/sequential/Keyboard.js b/v1/src/simulator/src/sequential/Keyboard.js
index ffeb7a9c..a86a1d04 100644
--- a/v1/src/simulator/src/sequential/Keyboard.js
+++ b/v1/src/simulator/src/sequential/Keyboard.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText3 } from '../canvasApi'
/**
* @class
@@ -18,15 +18,12 @@ import { colors } from '../themer/themer'
export default class Keyboard extends CircuitElement {
constructor(x, y, scope = globalScope, bufferSize = 32) {
super(x, y, scope, 'RIGHT', 1)
- /*
- this.scope['Keyboard'].push(this);
- */
this.directionFixed = true
this.fixedBitWidth = true
this.bufferSize = bufferSize || parseInt(prompt('Enter buffer size:'))
this.elementWidth = Math.max(80, Math.ceil(this.bufferSize / 2) * 20)
- this.elementHeight = 40 // Math.max(40,Math.ceil(this.rows*15/20)*20);
+ this.elementHeight = 40
this.setWidth(this.elementWidth / 2)
this.setHeight(this.elementHeight / 2)
diff --git a/v1/src/simulator/src/sequential/RAM.js b/v1/src/simulator/src/sequential/RAM.js
index b406f921..cdaab091 100644
--- a/v1/src/simulator/src/sequential/RAM.js
+++ b/v1/src/simulator/src/sequential/RAM.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, fillText2, fillText4, drawCircle2 } from '../canvasApi'
import { parseNumber, showMessage } from '../utils'
/**
@@ -43,7 +43,6 @@ import { parseNumber, showMessage } from '../utils'
* by keeping the max addressWidth small. If needed, we can increase the max.
* @category sequential
*/
-import { colors } from '../themer/themer'
import { showError } from '../utils'
export default class RAM extends CircuitElement {
constructor(
@@ -55,9 +54,6 @@ export default class RAM extends CircuitElement {
addressWidth = 10
) {
super(x, y, scope, dir, Math.min(Math.max(1, bitWidth), 32))
- /*
- this.scope['RAM'].push(this);
- */
this.setDimensions(60, 40)
this.directionFixed = true
@@ -270,9 +266,6 @@ export default class RAM extends CircuitElement {
}
showMessage('Data dumped to developer Console')
-
- console.log(JSON.stringify(this.data))
-
if (logLabel) {
console.groupEnd()
}
diff --git a/v1/src/simulator/src/sequential/Rom.js b/v1/src/simulator/src/sequential/Rom.js
index 69bb544b..823208ab 100644
--- a/v1/src/simulator/src/sequential/Rom.js
+++ b/v1/src/simulator/src/sequential/Rom.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, rect2, fillText3 } from '../canvasApi'
/**
* @class
@@ -21,9 +21,6 @@ export default class Rom extends CircuitElement {
data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
) {
super(x, y, scope, 'RIGHT', 1)
- /*
- this.scope['Rom'].push(this);
- */
this.fixedBitWidth = true
this.directionFixed = true
this.rectangleObject = false
@@ -133,7 +130,7 @@ export default class Rom extends CircuitElement {
hoverIndex === undefined &&
((!simulationArea.shiftDown && this.hover) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this))
+ simulationArea.multipleObjectSelections.includes(this))
)
ctx.fillStyle = colors['hover_select']
ctx.fill()
diff --git a/v1/src/simulator/src/sequential/SRflipFlop.js b/v1/src/simulator/src/sequential/SRflipFlop.js
index af1a16ce..f3010fbe 100644
--- a/v1/src/simulator/src/sequential/SRflipFlop.js
+++ b/v1/src/simulator/src/sequential/SRflipFlop.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, fillText } from '../canvasApi'
/**
* @class
@@ -18,9 +18,6 @@ import { colors } from '../themer/themer'
export default class SRflipFlop extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT') {
super(x, y, scope, dir, 1)
- /*
- this.scope['SRflipFlop'].push(this);
- */
this.directionFixed = true
this.fixedBitWidth = true
this.setDimensions(20, 20)
@@ -33,9 +30,6 @@ export default class SRflipFlop extends CircuitElement {
this.preset = new Node(0, 20, 0, this, 1, 'Preset')
this.en = new Node(-10, 20, 0, this, 1, 'Enable')
this.state = 0
- // this.slaveState = 0;
- // this.prevClockState = 0;
- // this.wasClicked = false;
}
newBitWidth(bitWidth) {
@@ -52,9 +46,6 @@ export default class SRflipFlop extends CircuitElement {
*/
isResolvable() {
return true
- if (this.reset.value == 1) return true
- if (this.S.value != undefined && this.R.value != undefined) return true
- return false
}
/**
@@ -105,20 +96,13 @@ export default class SRflipFlop extends CircuitElement {
ctx.lineWidth = correctWidth(3)
var xx = this.x
var yy = this.y
-
- // rect(ctx, xx - 20, yy - 20, 40, 40);
- // moveTo(ctx, -20, 5, xx, yy, this.direction);
- // lineTo(ctx, -15, 10, xx, yy, this.direction);
- // lineTo(ctx, -20, 15, xx, yy, this.direction);
-
- // if ((this.b.hover&&!simulationArea.shiftDown)|| simulationArea.lastSelected == this || simulationArea.multipleObjectSelections.contains(this)) ctx.fillStyle = "rgba(255, 255, 32,0.8)";ctx.fill();
ctx.stroke()
ctx.beginPath()
ctx.font = '20px Raleway'
ctx.fillStyle = colors['input_text']
ctx.textAlign = 'center'
- fillText(ctx, this.state.toString(16), xx, yy + 5)
+ this.state ? fillText(ctx, this.state.toString(16), xx, yy + 5) : fillText(ctx, '0', xx, yy + 5);
ctx.fill()
}
}
diff --git a/v1/src/simulator/src/sequential/TTY.js b/v1/src/simulator/src/sequential/TTY.js
index d0c89461..e533b99c 100644
--- a/v1/src/simulator/src/sequential/TTY.js
+++ b/v1/src/simulator/src/sequential/TTY.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText3 } from '../canvasApi'
import { colors } from '../themer/themer'
@@ -21,9 +21,6 @@ import { colors } from '../themer/themer'
export default class TTY extends CircuitElement {
constructor(x, y, scope = globalScope, rows = 3, cols = 32) {
super(x, y, scope, 'RIGHT', 1)
- /*
- this.scope['TTY'].push(this);
- */
this.directionFixed = true
this.fixedBitWidth = true
this.cols = cols || parseInt(prompt('Enter cols:'))
@@ -33,7 +30,6 @@ export default class TTY extends CircuitElement {
this.elementHeight = Math.max(40, Math.ceil((this.rows * 15) / 20) * 20)
this.setWidth(this.elementWidth / 2)
this.setHeight(this.elementHeight / 2)
- // this.element = new Element(x, y, "TTY",this.elementWidth/2, this,this.elementHeight/2);
this.clockInp = new Node(
-this.elementWidth / 2,
@@ -51,7 +47,6 @@ export default class TTY extends CircuitElement {
7,
'Ascii Input'
)
- // this.qOutput = new Node(20, -10, 1, this);
this.reset = new Node(
30 - this.elementWidth / 2,
this.elementHeight / 2,
@@ -68,8 +63,6 @@ export default class TTY extends CircuitElement {
1,
'Enable'
)
- // this.masterState = 0;
- // this.slaveState = 0;
this.prevClockState = 0
this.data = ''
@@ -78,7 +71,7 @@ export default class TTY extends CircuitElement {
/**
* @memberof TTY
- * this funciton is used to change the size of the screen
+ * this function is used to change the size of the screen
*/
changeRowSize(size) {
if (size == undefined || size < 1 || size > 10) return
@@ -91,7 +84,7 @@ export default class TTY extends CircuitElement {
/**
* @memberof TTY
- * this funciton is used to change the size of the screen
+ * this function is used to change the size of the screen
*/
changeColSize(size) {
if (size == undefined || size < 20 || size > 100) return
@@ -173,7 +166,6 @@ export default class TTY extends CircuitElement {
ctx.lineWidth = correctWidth(3)
var xx = this.x
var yy = this.y
- // rect(ctx, xx - this.elementWidth/2, yy - this.elementHeight/2, this.elementWidth, this.elementHeight);
moveTo(
ctx,
@@ -199,9 +191,6 @@ export default class TTY extends CircuitElement {
yy,
this.direction
)
-
- // if ((this.b.hover&&!simulationArea.shiftDown)|| simulationArea.lastSelected == this || simulationArea.multipleObjectSelections.contains(this))
- // ctx.fillStyle = "rgba(255, 255, 32,0.8)";
ctx.stroke()
ctx.beginPath()
diff --git a/v1/src/simulator/src/sequential/TflipFlop.js b/v1/src/simulator/src/sequential/TflipFlop.js
index cedb9f6b..ce1f7be9 100644
--- a/v1/src/simulator/src/sequential/TflipFlop.js
+++ b/v1/src/simulator/src/sequential/TflipFlop.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText } from '../canvasApi'
import { colors } from '../themer/themer'
@@ -19,9 +19,6 @@ import { colors } from '../themer/themer'
export default class TflipFlop extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT') {
super(x, y, scope, dir, 1)
- /*
- this.scope['TflipFlop'].push(this);
- */
this.directionFixed = true
this.fixedBitWidth = true
this.setDimensions(20, 20)
@@ -36,8 +33,6 @@ export default class TflipFlop extends CircuitElement {
this.masterState = 0
this.slaveState = 0
this.prevClockState = 0
-
- // this.wasClicked = false;
}
/**
@@ -133,12 +128,10 @@ export default class TflipFlop extends CircuitElement {
ctx.lineWidth = correctWidth(3)
var xx = this.x
var yy = this.y
- // rect(ctx, xx - 20, yy - 20, 40, 40);
moveTo(ctx, -20, 5, xx, yy, this.direction)
lineTo(ctx, -15, 10, xx, yy, this.direction)
lineTo(ctx, -20, 15, xx, yy, this.direction)
- // if ((this.b.hover&&!simulationArea.shiftDown)|| simulationArea.lastSelected == this || simulationArea.multipleObjectSelections.contains(this)) ctx.fillStyle = "rgba(255, 255, 32,0.8)";ctx.fill();
ctx.stroke()
ctx.beginPath()
ctx.font = '20px Raleway'
diff --git a/v1/src/simulator/src/sequential/verilogRAM.js b/v1/src/simulator/src/sequential/verilogRAM.js
index d1e9c71d..c3915d47 100644
--- a/v1/src/simulator/src/sequential/verilogRAM.js
+++ b/v1/src/simulator/src/sequential/verilogRAM.js
@@ -1,7 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
-import { correctWidth, fillText2, fillText4, drawCircle2 } from '../canvasApi'
+import { simulationArea } from '../simulationArea'
/**
* @class
* verilogRAM Component.
@@ -42,7 +41,6 @@ import { correctWidth, fillText2, fillText4, drawCircle2 } from '../canvasApi'
* by keeping the max addressWidth small. If needed, we can increase the max.
* @category sequential
*/
-import { colors } from '../themer/themer'
function customResolve(
clockInp,
@@ -110,7 +108,6 @@ function customResolve(
if (en[i].value == 0) {
prevClockState[i] = clockInp[i].value
} else if (en[i].value == 1 || en[i].connections.length == 0) {
- // if(en.value==1) // Creating Infinite Loop, WHY ??
if (clockInp[i].value == prevClockState[i]) {
if (clockInp[i].value == 0 && dInp[i].value != undefined) {
masterState[i] = dInp[i].value
@@ -152,9 +149,6 @@ export default class verilogRAM extends CircuitElement {
wrports
) {
super(x, y, scope, dir, Math.min(Math.max(1, bitWidth), 32))
- /*
- this.scope['verilogRAM'].push(this);
- */
this.setDimensions(60, 40)
this.directionFixed = true
@@ -413,22 +407,9 @@ export default class verilogRAM extends CircuitElement {
}
newBitWidth(value) {
- // value = parseInt(value);
- // if (!isNaN(value) && this.bitWidth != value && value >= 1 && value <= 32) {
- // this.bitWidth = value;
- // this.dataIn.bitWidth = value;
- // this.dataOut.bitWidth = value;
- // this.clearData();
- // }
}
changeAddressWidth(value) {
- // value = parseInt(value);
- // if (!isNaN(value) && this.addressWidth != value && value >= 1 && value <= this.maxAddressWidth) {
- // this.addressWidth = value;
- // this.address.bitWidth = value;
- // this.clearData();
- // }
}
clearData() {
@@ -498,27 +479,6 @@ export default class verilogRAM extends CircuitElement {
}
customDraw() {
- // var ctx = simulationArea.context;
- // //
- // var xx = this.x;
- // var yy = this.y;
- // ctx.beginPath();
- // ctx.strokeStyle = 'gray';
- // ctx.fillStyle = this.write.value ? 'red' : 'lightgreen';
- // ctx.lineWidth = correctWidth(1);
- // drawCircle2(ctx, 50, -30, 3, xx, yy, this.direction);
- // ctx.fill();
- // ctx.stroke();
- // ctx.beginPath();
- // ctx.textAlign = 'center';
- // ctx.fillStyle = 'black';
- // fillText4(ctx, this.memSizeString(), 0, -10, xx, yy, this.direction, 12);
- // fillText4(ctx, this.shortName, 0, 10, xx, yy, this.direction, 12);
- // fillText2(ctx, 'A', this.address.x + 12, this.address.y, xx, yy, this.direction);
- // fillText2(ctx, 'DI', this.dataIn.x + 12, this.dataIn.y, xx, yy, this.direction);
- // fillText2(ctx, 'W', this.write.x + 12, this.write.y, xx, yy, this.direction);
- // fillText2(ctx, 'DO', this.dataOut.x - 15, this.dataOut.y, xx, yy, this.direction);
- // ctx.fill();
}
memSizeString() {
@@ -543,9 +503,6 @@ export default class verilogRAM extends CircuitElement {
if (logLabel) {
console.group(this.label)
}
-
- console.log(this.data)
-
if (logLabel) {
console.groupEnd()
}
diff --git a/v1/src/simulator/src/setup.js b/v1/src/simulator/src/setup.js
index 3be06161..b23a8417 100644
--- a/v1/src/simulator/src/setup.js
+++ b/v1/src/simulator/src/setup.js
@@ -1,20 +1,15 @@
/* eslint-disable import/no-cycle */
/* eslint-disable no-restricted-syntax */
/* eslint-disable guard-for-in */
-
-import { Tooltip } from 'bootstrap'
-import metadata from './metadata.json'
import { generateId, showMessage } from './utils'
-import backgroundArea from './backgroundArea'
+import { backgroundArea } from './backgroundArea'
import plotArea from './plotArea'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import { dots } from './canvasApi'
import { update, updateSimulationSet, updateCanvasSet } from './engine'
import { setupUI } from './ux'
import startMainListeners from './listeners'
-// import startEmbedListeners from './embedListeners'
-import './embed'
-import { newCircuit, scopeList } from './circuit'
+import { newCircuit } from './circuit'
import load from './data/load'
import save from './data/save'
import { showTourGuide } from './tutorials'
@@ -26,7 +21,6 @@ import 'codemirror/addon/edit/closebrackets'
import 'codemirror/addon/hint/anyword-hint'
import 'codemirror/addon/hint/show-hint'
import { setupCodeMirrorEnvironment } from './Verilog2CV'
-// import { keyBinder } from '#/components/DialogBox/CustomShortcut.vue'
import '../vendor/jquery-ui.min.css'
import '../vendor/jquery-ui.min'
import { confirmSingleOption } from '#/components/helpers/confirmComponent/ConfirmComponent.vue'
@@ -47,7 +41,7 @@ export function resetup() {
if (!embed) {
height =
(document.body.clientHeight -
- document.getElementById('toolbar').clientHeight) *
+ document.getElementById('toolbar')?.clientHeight) *
DPR
} else {
height = document.getElementById('simulation').clientHeight * DPR
@@ -97,29 +91,6 @@ function setupEnvironment() {
setupCodeMirrorEnvironment()
}
-/**
- * It initializes some useful array which are helpful
- * while simulating, saving and loading project.
- * It also draws icons in the sidebar
- * @category setup
- */
-function setupElementLists() {
- // $('#menu').empty()
-
- window.circuitElementList = metadata.circuitElementList
- window.annotationList = metadata.annotationList
- window.inputList = metadata.inputList
- window.subCircuitInputList = metadata.subCircuitInputList
- window.moduleList = [...circuitElementList, ...annotationList]
- window.updateOrder = [
- 'wires',
- ...circuitElementList,
- 'nodes',
- ...annotationList,
- ] // Order of update
- window.renderOrder = [...moduleList.slice().reverse(), 'wires', 'allNodes'] // Order of render
-}
-
/**
* Fetches project data from API and loads it into the simulator.
* @param {number} projectId The ID of the project to fetch data for
@@ -142,9 +113,9 @@ async function fetchProjectData(projectId) {
const simulatorVersion = data.simulatorVersion
const projectName = data.name
if(!simulatorVersion){
- window.location.href = `/simulator/edit/${projectId}`
- }
- if(simulatorVersion && simulatorVersion != "v1"){
+ window.location.href = `/simulator/edit/${projectName}`
+ }
+ if(simulatorVersion && simulatorVersion != "v0"){
window.location.href = `/simulatorvue/edit/${projectName}?simver=${simulatorVersion}`
}
await load(data)
@@ -205,9 +176,6 @@ function showTour() {
* @category setup
*/
export function setup() {
- // let embed = false
- // const startListeners = embed ? startEmbedListeners : startMainListeners
- setupElementLists()
setupEnvironment()
if (!embed) {
setupUI()
diff --git a/v1/src/simulator/src/simulationArea.js b/v1/src/simulator/src/simulationArea.js
deleted file mode 100644
index 3784988a..00000000
--- a/v1/src/simulator/src/simulationArea.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/* eslint-disable import/no-cycle */
-import EventQueue from './eventQueue'
-import { clockTick } from './utils'
-
-/**
- * simulation environment object - holds simulation canvas
- * @type {Object} simulationArea
- * @property {HTMLCanvasElement} canvas
- * @property {boolean} selected
- * @property {boolean} hover
- * @property {number} clockState
- * @property {boolean} clockEnabled
- * @property {undefined} lastSelected
- * @property {Array} stack
- * @property {number} prevScale
- * @property {number} oldx
- * @property {number} oldy
- * @property {Array} objectList
- * @property {number} maxHeight
- * @property {number} maxWidth
- * @property {number} minHeight
- * @property {number} minWidth
- * @property {Array} multipleObjectSelections
- * @property {Array} copyList - List of selected elements
- * @property {boolean} shiftDown - shift down or not
- * @property {boolean} controlDown - contol down or not
- * @property {number} timePeriod - time period
- * @property {number} mouseX - mouse x
- * @property {number} mouseY - mouse y
- * @property {number} mouseDownX - mouse click x
- * @property {number} mouseDownY - mouse click y
- * @property {Array} simulationQueue - simulation queue
- * @property {number} clickCount - number of clicks
- * @property {string} lock - locked or unlocked
- * @property {function} timer - timer
- * @property {function} setup - to setup the simulaton area
- * @property {function} changeClockTime - change clock time
- * @property {function} clear - clear the simulation area
- * @category simulationArea
- */
-const simulationArea = {
- canvas: document.getElementById('simulationArea'),
- selected: false,
- hover: false,
- clockState: 0,
- clockEnabled: true,
- lastSelected: undefined,
- stack: [],
- prevScale: 0,
- oldx: 0,
- oldy: 0,
- objectList: [],
- maxHeight: 0,
- maxWidth: 0,
- minHeight: 0,
- minWidth: 0,
- multipleObjectSelections: [],
- copyList: [],
- shiftDown: false,
- controlDown: false,
- timePeriod: 500,
- mouseX: 0,
- mouseY: 0,
- mouseDownX: 0,
- mouseDownY: 0,
- simulationQueue: undefined,
- multiAddElement: false,
-
- clickCount: 0, // double click
- lock: 'unlocked',
- timer() {
- ckickTimer = setTimeout(() => {
- simulationArea.clickCount = 0
- }, 600)
- },
-
- setup() {
- this.canvas = document.getElementById('simulationArea')
- this.canvas.width = width
- this.canvas.height = height
- this.simulationQueue = new EventQueue(10000)
- this.context = this.canvas.getContext('2d')
- simulationArea.changeClockTime(simulationArea.timePeriod)
- this.mouseDown = false
- },
- changeClockTime(t) {
- if (t < 50) return
- clearInterval(simulationArea.ClockInterval)
- t = t || prompt('Enter Time Period:')
- simulationArea.timePeriod = t
- simulationArea.ClockInterval = setInterval(clockTick, t)
- },
- clear() {
- if (!this.context) return
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
- },
-}
-export const { changeClockTime } = simulationArea
-export default simulationArea
diff --git a/v1/src/simulator/src/simulationArea.ts b/v1/src/simulator/src/simulationArea.ts
new file mode 100644
index 00000000..bd2f3f9a
--- /dev/null
+++ b/v1/src/simulator/src/simulationArea.ts
@@ -0,0 +1,70 @@
+import { EventQueue } from './eventQueue'
+import { SimulationArea } from './interface/simulationArea'
+import { clockTick } from './utils'
+
+const simulationArea: SimulationArea = {
+ canvas: document.getElementById('simulationArea') as HTMLCanvasElement,
+ context: null,
+ selected: false,
+ hover: false,
+ clockState: 0,
+ clockEnabled: true,
+ lastSelected: null,
+ stack: [],
+ prevScale: 0,
+ oldx: 0,
+ oldy: 0,
+ objectList: [],
+ maxHeight: 0,
+ maxWidth: 0,
+ minHeight: 0,
+ minWidth: 0,
+ multipleObjectSelections: [],
+ copyList: [],
+ shiftDown: false,
+ controlDown: false,
+ timePeriod: 500,
+ mouseX: 0,
+ mouseY: 0,
+ mouseDownX: 0,
+ mouseDownY: 0,
+ simulationQueue: new EventQueue(10000),
+ clickCount: 0,
+ lock: 'unlocked',
+ mouseDown: false,
+ ClockInterval: null,
+ touch: false,
+
+ timer() {
+ const clickTimer = setTimeout(() => {
+ simulationArea.clickCount = 0
+ }, 600)
+ },
+ setup() {
+ this.canvas = document.getElementById('simulationArea') as HTMLCanvasElement;
+ this.canvas.width = width;
+ this.canvas.height = height;
+ this.simulationQueue = new EventQueue(10000);
+ this.context = this.canvas.getContext('2d')!;
+ simulationArea.changeClockTime(simulationArea.timePeriod);
+ this.mouseDown = false;
+ },
+ changeClockTime(t: number) {
+ if (t < 50) {
+ return;
+ }
+ if (simulationArea.ClockInterval != null) {
+ clearInterval(simulationArea.ClockInterval);
+ }
+ simulationArea.timePeriod = t;
+ simulationArea.ClockInterval = setInterval(clockTick, t);
+ },
+ clear() {
+ if (!this.context) {
+ return;
+ }
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ },
+};
+export { simulationArea }
+export const { changeClockTime } = simulationArea
\ No newline at end of file
diff --git a/v1/src/simulator/src/subcircuit.js b/v1/src/simulator/src/subcircuit.js
index 85fdc53e..377ea3b5 100644
--- a/v1/src/simulator/src/subcircuit.js
+++ b/v1/src/simulator/src/subcircuit.js
@@ -1,7 +1,7 @@
/* eslint-disable import/no-cycle */
import Scope, { scopeList, switchCircuit } from './circuit'
import CircuitElement from './circuitElement'
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import { scheduleBackup, checkIfBackup } from './data/backupCircuit'
import {
scheduleUpdate,
@@ -20,6 +20,8 @@ import { layoutModeGet } from './layoutMode'
import { verilogModeGet } from './Verilog2CV'
import { sanitizeLabel } from './verilogHelpers'
import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
+import { circuitElementList, subCircuitInputList } from './metadata'
+
/**
* Function to load a subcicuit
* @category subcircuit
@@ -40,50 +42,6 @@ export function createSubCircuitPrompt(scope = globalScope) {
}
const simulatorStore = SimulatorStore()
simulatorStore.dialogBox.insertsubcircuit_dialog = true
- /*
- $('#insertSubcircuitDialog').empty()
- let flag = true
- for (id in scopeList) {
- if (
- !scopeList[id].checkDependency(scope.id) &&
- scopeList[id].isVisible()
- ) {
- flag = false
- $('#insertSubcircuitDialog').append(
- ``
- )
- }
- }
- if (flag)
- $('#insertSubcircuitDialog').append(
- "Looks like there are no other circuits which doesn't have this circuit as a dependency. Create a new one!
"
- )
- $('#insertSubcircuitDialog').dialog({
- resizable: false,
- maxHeight: 800,
- width: 450,
- maxWidth: 800,
- minWidth: 250,
- buttons: !flag
- ? [
- {
- text: 'Insert SubCircuit',
- click() {
- if (!$('input[name=subCircuitId]:checked').val())
- return
- simulationArea.lastSelected = new SubCircuit(
- undefined,
- undefined,
- globalScope,
- $('input[name=subCircuitId]:checked').val()
- )
- $(this).dialog('close')
- },
- },
- ]
- : [],
- })
- */
}
/**
@@ -207,8 +165,8 @@ export default class SubCircuit extends CircuitElement {
this.downDimensionY = subcircuitScope.layout.height
}
- this.nodeList.extend(this.inputNodes)
- this.nodeList.extend(this.outputNodes)
+ this.nodeList.push(...this.inputNodes)
+ this.nodeList.push(...this.outputNodes)
} else {
this.version = '2.0'
}
@@ -297,14 +255,11 @@ export default class SubCircuit extends CircuitElement {
// Needs to be deprecated, removed
reBuild() {
- // new SubCircuit(x = this.x, y = this.y, scope = this.scope, this.id);
- // this.scope.backups = []; // Because all previous states are invalid now
- // this.delete();
- // showMessage('Subcircuit: ' + subcircuitScope.name + ' has been reloaded.');
}
/**
- * rebuilds the subcircuit if any change to localscope is made
+ * If the circuit referenced by localscope is changed, then the localscope
+ * needs to be updated. This function does that.
*/
reBuildCircuit() {
this.data = JSON.parse(scheduleBackup(scopeList[this.id]))
@@ -365,7 +320,7 @@ export default class SubCircuit extends CircuitElement {
} else {
this.scope.backups = []
this.inputNodes[i].delete()
- this.nodeList.clean(this.inputNodes[i])
+ this.nodeList = this.nodeList.filter(x => x !== this.inputNodes[i])
}
}
@@ -381,7 +336,7 @@ export default class SubCircuit extends CircuitElement {
} else {
this.scope.backups = []
temp_map_inp[id][1].delete()
- this.nodeList.clean(temp_map_inp[id][1])
+ this.nodeList = this.nodeList.filter(x => x !== temp_map_inp[id][1])
temp_map_inp[id][1] = new Node(
temp_map_inp[id][0].layoutProperties.x,
temp_map_inp[id][0].layoutProperties.y,
@@ -426,7 +381,7 @@ export default class SubCircuit extends CircuitElement {
this.outputNodes[i]
} else {
this.outputNodes[i].delete()
- this.nodeList.clean(this.outputNodes[i])
+ this.nodeList = this.nodeList.filter(x => x !== this.outputNodes[i])
}
}
@@ -441,7 +396,7 @@ export default class SubCircuit extends CircuitElement {
temp_map_out[id][1].bitWidth = temp_map_out[id][0].bitWidth
} else {
temp_map_out[id][1].delete()
- this.nodeList.clean(temp_map_out[id][1])
+ this.nodeList = this.nodeList.filter(x => x !== temp_map_out[id][1])
temp_map_out[id][1] = new Node(
temp_map_out[id][0].layoutProperties.x,
temp_map_out[id][0].layoutProperties.y,
@@ -479,12 +434,9 @@ export default class SubCircuit extends CircuitElement {
this.reBuildCircuit()
}
- // Should this be done here or only when this.reBuildCircuit() is called?
- {
- this.localScope.reset()
- updateSimulationSet(true)
- forceResetNodesSet(true)
- }
+ this.localScope.reset()
+ updateSimulationSet(true)
+ forceResetNodesSet(true)
this.makeConnections()
}
@@ -658,7 +610,7 @@ export default class SubCircuit extends CircuitElement {
if (
(this.hover && !simulationArea.shiftDown) ||
simulationArea.lastSelected === this ||
- simulationArea.multipleObjectSelections.contains(this)
+ simulationArea.multipleObjectSelections.includes(this)
)
ctx.fillStyle = colors['hover_select']
}
@@ -688,6 +640,7 @@ export default class SubCircuit extends CircuitElement {
)
}
} else {
+ console.error('Unknown Version: ', this.version)
}
for (var i = 0; i < subcircuitScope.Input.length; i++) {
diff --git a/v1/src/simulator/src/testCreator.js b/v1/src/simulator/src/testCreator.js
deleted file mode 100644
index 4a1708c2..00000000
--- a/v1/src/simulator/src/testCreator.js
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- This file contains all javascript related to the test creator UI
- at /testbench
-*/
-
-import _ from '../vendor/table2csv'
-
-const CREATORMODE = {
- NORMAL: 0,
- SIMULATOR_POPUP: 1,
-}
-
-var testMode = 'comb'
-var groupIndex = 0
-var inputCount = 0
-var nextInputIndex = 0
-var outputCount = 0
-var nextOutputIndex = 0
-var cases = [0]
-var creatorMode = CREATORMODE.NORMAL
-var circuitScopeID
-
-function dataReset() {
- groupIndex = -1
- cases = [0]
-}
-
-/**
- * Onload, check if it is opened in a popup.
- * Check if test is being edited, or created
- */
-window.onload = () => {
- const query = new URLSearchParams(window.location.search)
- if (query.has('popUp')) {
- if (query.get('popUp') == 'true') {
- creatorMode = CREATORMODE.SIMULATOR_POPUP
- $('.right-button-group').append(
- ''
- )
- }
- }
- if (query.has('data')) {
- $('#tb-creator-head').html('Edit Test')
- circuitScopeID = query.get('scopeID')
- loadData(query.get('data'))
- return
- }
-
- if (query.has('result')) {
- $('#tb-creator-head').html('Test Result')
- loadResult(query.get('result'))
- readOnlyUI()
- return
- }
-
- circuitScopeID = query.get('scopeID')
- addInput()
- addOutput()
- makeSortable()
-}
-
-/* Change UI testMode between Combinational(comb) and Sequential(seq) */
-function changeTestMode(m) {
- if (testMode === m) return false
- dataReset()
- testMode = m
- $('#combSelect').removeClass('tab-selected')
- $('#seqSelect').removeClass('tab-selected')
- $('#tb-new-group').css('visibility', m === 'seq' ? 'visible' : 'hidden')
- $(`#${m}Select`).addClass('tab-selected')
- $('#dataGroup').empty()
-
- return true
-}
-
-/* Adds case to a group */
-function addCase(grp) {
- const currentGroupTable = $(`#data-table-${grp + 1}`)
-
- let s =
- ' | \n'
- for (let i = 0; i < inputCount + outputCount; i++)
- s += '0 | '
- s += '
'
-
- // Sortable hack
- currentGroupTable.find('tbody').remove()
- currentGroupTable.append(s)
-}
-
-/* Deletes case from a group */
-function deleteCase(element) {
- const row = element.parent().parent()
- const grp = Number(row.parent().attr('id').split('-').pop())
-
- row.remove()
-}
-
-/* Adds group with default name 'Group N' or name supplied in @param groupName */
-/* Used without params by UI, used with params by loadData() */
-function addGroup(
- groupName = `${testMode === 'comb' ? 'Group' : 'Set'} ${groupIndex + 2}`
-) {
- $('.plus-button').removeClass('latest-button')
- groupIndex++
-
- const s = `
-
-
${escapeHtml(groupName)}
-
Click + to add tests to the ${
- testMode === 'comb' ? 'group' : 'set'
- }
-
-
-
- `
- cases[groupIndex] = 0
- $('#dataGroup').append(s)
-
- makeSortable()
-}
-
-/* Deletes a group */
-function deleteGroup(element) {
- const groupDiv = element.parent()
- const grp = Number(groupDiv.attr('id').split('-').pop())
- groupDiv.remove()
-}
-
-/* Adds input with default value 0 or values supplied in @param inputData */
-/* Used without params for UI, used with params by loadData() */
-function addInput(
- label = `inp${nextInputIndex + 1}`,
- bitwidth = 1,
- inputData = []
-) {
- nextInputIndex++
- inputCount++
- // Change head table contents
- const sHead = `${escapeHtml(
- label
- )} | `
- const sData = `${escapeHtml(
- bitwidth.toString()
- )} | `
- $('#testBenchTable')
- .find('tr')
- .eq(1)
- .find('th')
- .eq(inputCount - 1)
- .after(sHead)
- $('#testBenchTable')
- .find('tr')
- .eq(2)
- .find('td')
- .eq(inputCount - 1)
- .after(sData)
- $('#tb-inputs-head').attr('colspan', inputCount)
-
- // Change data tables' contents
- $('#dataGroup')
- .find('table')
- .each(function (group_i) {
- $(this)
- .find('tr')
- .each(function (case_i) {
- const s = `${
- inputData.length
- ? escapeHtml(inputData[group_i][case_i])
- : 0
- } | `
- $(this)
- .find('td')
- .eq(inputCount - 1)
- .after(s)
- })
- })
-}
-
-/* Adds output with default value 0 or values supplied in @param outputData */
-/* Used without params for UI, used with params by loadData() */
-/* Used with resultData and result=true for setting result */
-function addOutput(
- label = `out${nextOutputIndex + 1}`,
- bitwidth = 1,
- outputData = [],
- result = false,
- resultData = []
-) {
- nextOutputIndex++
- outputCount++
- // Change head table contents
- let sHead = `${escapeHtml(
- label
- )} | `
- let sData = `${escapeHtml(
- bitwidth.toString()
- )} | `
-
- // If result then set colspan to 2
- if (result) {
- sHead = `${escapeHtml(
- label
- )} | `
- sData = `${escapeHtml(
- bitwidth.toString()
- )} | `
- }
-
- $('#testBenchTable')
- .find('tr')
- .eq(1)
- .find('th')
- .eq(inputCount + outputCount - 1)
- .after(sHead)
- $('#testBenchTable')
- .find('tr')
- .eq(2)
- .find('td')
- .eq(inputCount + outputCount - 1)
- .after(sData)
- // If not result then colspan is outputCount
- $('#tb-outputs-head').attr('colspan', outputCount)
- // else it's 2*outputCount
- if (result) {
- $('#tb-outputs-head').attr('colspan', 2 * outputCount)
- }
-
- // Change data tables' contents
-
- // If not result just add the outputs
- if (!result) {
- $('#dataGroup')
- .find('table')
- .each(function (group_i) {
- $(this)
- .find('tr')
- .each(function (case_i) {
- const s = `${
- outputData.length
- ? escapeHtml(outputData[group_i][case_i])
- : 0
- } | `
- $(this)
- .find('td')
- .eq(inputCount + outputCount - 1)
- .after(s)
- })
- })
-
- // If result then add results besides the outputs
- // Hacky
- } else {
- $('#dataGroup')
- .find('table')
- .each(function (group_i) {
- $(this)
- .find('tr')
- .each(function (case_i) {
- // Add the outputs (expected values)
- const outputCellData = `${escapeHtml(
- outputData[group_i][case_i]
- )} | `
- $(this)
- .find('td')
- .eq(inputCount + 2 * (outputCount - 1))
- .after(outputCellData)
-
- // Add the actual values
- const resultColor =
- resultData[group_i][case_i] ===
- outputData[group_i][case_i]
- ? 'green'
- : 'red'
- const resultCellData = `${escapeHtml(
- resultData[group_i][case_i]
- )} | `
- $(this)
- .find('td')
- .eq(inputCount + 2 * outputCount - 1)
- .after(resultCellData)
- })
- })
- }
-}
-
-/* Deletes input unless there's only one input */
-function deleteInput(element) {
- if (inputCount === 1) return
- const columnIndex = element.parent().eq(0).index()
-
- $('#testBenchTable tr, .data-group tr')
- .slice(1)
- .each(function () {
- $(this).find('td, th').eq(columnIndex).remove()
- })
-
- inputCount--
- $('#tb-inputs-head').attr('colspan', inputCount)
-}
-
-/* Deletes output unless there's only one output */
-function deleteOutput(element) {
- if (outputCount === 1) return
- const columnIndex = element.parent().eq(0).index()
-
- $('#testBenchTable tr, .data-group tr')
- .slice(1)
- .each(function () {
- $(this).find('td, th').eq(columnIndex).remove()
- })
-
- outputCount--
- $('#tb-outputs-head').attr('colspan', outputCount)
-}
-
-/* Returns input/output(keys) and their bitwidths(values) */
-/* Called by getData() */
-function getBitWidths() {
- const bitwidths = {}
- $('#testBenchTable')
- .find('tr')
- .eq(1)
- .find('th')
- .slice(1)
- .each(function (index) {
- const inp = $(this).text()
- const bw = $('#testBenchTable')
- .find('tr')
- .eq(2)
- .find('td')
- .slice(1)
- .eq(index)
- .html()
- bitwidths[inp] = Number(bw)
- })
- return bitwidths
-}
-
-/* Returns data for all the groups for all inputs and outputs */
-/* Called by parse() */
-function getData() {
- const bitwidths = getBitWidths()
- const groups = []
- const groupCount = $('#dataGroup').children().length
- for (let group_i = 0; group_i < groupCount; group_i++) {
- const group = {}
- group.label = getGroupTitle(group_i)
- group.inputs = []
- group.outputs = []
-
- const group_table = $(`#data-table-${group_i + 1}`)
- group.n = group_table.find('tr').length
-
- // Push all the inputs in the group
- for (let inp_i = 0; inp_i < inputCount; inp_i++) {
- const label = Object.keys(bitwidths)[inp_i]
- const input = {
- label: label.slice(0, label.length - 1),
- bitWidth: bitwidths[label],
- values: [],
- }
- group_table.find('tr').each(function () {
- input.values.push($(this).find('td').slice(1).eq(inp_i).html())
- })
-
- group.inputs.push(input)
- }
-
- // Push all the outputs in the group
- for (let out_i = 0; out_i < outputCount; out_i++) {
- const label = Object.keys(bitwidths)[inputCount + out_i]
- const output = {
- label: label.slice(0, label.length - 1),
- bitWidth: bitwidths[label],
- values: [],
- }
- group_table.find('tr').each(function () {
- output.values.push(
- $(this)
- .find('td')
- .slice(1)
- .eq(inputCount + out_i)
- .html()
- )
- })
-
- group.outputs.push(output)
- }
-
- groups.push(group)
- }
-
- return groups
-}
-
-function getTestTitle() {
- return $('#test-title-label').text()
-}
-
-function getGroupTitle(group_i) {
- return $(`#data-group-title-${group_i + 1}`).text()
-}
-
-/* Parse UI table into Javascript Object */
-function parse() {
- const data = {}
- const tableData = getData()
- data.type = testMode
- data.title = getTestTitle()
- data.groups = tableData
- return data
-}
-
-/* Export test data as a CSV file */
-function exportAsCSV() {
- let csvData = ''
- csvData += 'Title,Test Type,Input Count,Output Count\n'
- csvData += `${getTestTitle()},${testMode},${inputCount},${outputCount}\n\n\n`
- csvData += $('table').eq(0).table2CSV()
- csvData += '\n\n'
- $('table')
- .slice(1)
- .each(function (group_i) {
- csvData += getGroupTitle(group_i)
- csvData += '\n'
- csvData += $(this).table2CSV()
- csvData += '\n\n'
- })
-
- download(`${getTestTitle()}.csv`, csvData)
- return csvData
-}
-
-/*
- Imports data from CSV and loads into the table
- To achieve this, first converts to JSON then uses request param to load json to table
-*/
-function importFromCSV() {
- const file = $('#csvFileInput').prop('files')[0]
- const reader = new FileReader()
-
- // If circuitScopeID exists, ie. if popup opened from testbench, then use that to redirect
- const query = new URLSearchParams(window.location.search)
- // Preserve popup status while redirecting
- const isPopup = query.get('popUp') || false
-
- // When the file is read, redirect to the data location
- reader.onload = () => {
- const csvContent = reader.result
- const jsonData = csv2json(csvContent, 1, 1)
-
- window.location = `/testbench?scopeID=${
- circuitScopeID || ''
- }&data=${jsonData}&popUp=${isPopup}`
- }
-
- reader.readAsText(file)
-}
-
-// Clicks the hidden upload file button, entrypoint into importFromCSV()
-// The hidden button in-turn calls importFromCSV()
-function clickUpload() {
- $('#csvFileInput').click()
-}
-
-/* Converts CSV to JSON to be loaded into the table */
-function csv2json(csvFileData) {
- const stripQuotes = (str) => str.replaceAll('"', '')
-
- /* Extracts bitwidths from the csv data */
- const getBitWidthsCSV = (csvDataBW) => {
- const testMetadata = csvDataBW.split('\n\n')[0].split('\n')
- const labels = testMetadata[1]
- .split(',')
- .slice(1)
- .map((label) => stripQuotes(label))
- const bitWidths = testMetadata[2]
- .split(',')
- .slice(1)
- .map((bw) => Number(stripQuotes(bw)))
-
- return { labels, bitWidths }
- }
-
- const csvMetadata = csvFileData.split('\n\n\n')[0].split('\n')[1].split(',')
- const csvData = csvFileData.split('\n\n\n')[1]
- const jsonData = {}
-
- jsonData.title = csvMetadata[0]
- jsonData.type = csvMetadata[1]
- const inputCountCSV = Number(csvMetadata[2])
- const outputCountCSV = Number(csvMetadata[3])
-
- jsonData.groups = []
- const { labels, bitWidths } = getBitWidthsCSV(csvData)
-
- const groups = csvData.split('\n\n').slice(1)
- for (let group_i = 0; group_i < groups.length - 1; group_i++) {
- const rows = groups[group_i].split('\n')
- jsonData.groups[group_i] = {
- label: rows[0],
- n: rows.length - 1,
- inputs: [],
- outputs: [],
- }
-
- // Parse Inputs
- for (let input_i = 0; input_i < inputCountCSV; input_i++) {
- const thisInput = {
- label: labels[input_i],
- bitWidth: bitWidths[input_i],
- values: [],
- }
- for (let case_i = 1; case_i < rows.length; case_i++)
- thisInput.values.push(
- stripQuotes(rows[case_i].split(',')[input_i + 1])
- )
-
- jsonData.groups[group_i].inputs.push(thisInput)
- }
-
- // Parse Outputs
- for (
- let output_i = inputCountCSV;
- output_i < inputCountCSV + outputCountCSV;
- output_i++
- ) {
- const thisOutput = {
- label: labels[output_i],
- bitWidth: bitWidths[output_i],
- values: [],
- }
- for (let case_i = 1; case_i < rows.length; case_i++) {
- thisOutput.values.push(
- stripQuotes(rows[case_i].split(',')[output_i + 1])
- )
- }
-
- jsonData.groups[group_i].outputs.push(thisOutput)
- }
- }
-
- return JSON.stringify(jsonData)
-}
-
-/* Helper function to download generated file */
-function download(filename, text) {
- var element = document.createElement('a')
- element.setAttribute(
- 'href',
- `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`
- )
- element.setAttribute('download', filename)
-
- element.style.display = 'none'
- document.body.appendChild(element)
-
- element.click()
-
- document.body.removeChild(element)
-}
-
-/**
- * Called when Save is clicked. If opened in popup, sends message to parent window
- * to attach test to the testbench.
- */
-function saveData() {
- const testData = parse()
-
- if (creatorMode === CREATORMODE.SIMULATOR_POPUP) {
- const postData = { scopeID: circuitScopeID, testData }
- window.opener.postMessage(
- { type: 'testData', data: JSON.stringify(postData) },
- '*'
- )
- window.close()
- }
-}
-
-/* Loads data from JSON string into the table */
-function loadData(dataJSON) {
- const data = JSON.parse(dataJSON)
- if (data.title) $('#test-title-label').text(data.title)
- changeTestMode()
- changeTestMode(data.type)
- for (let group_i = 0; group_i < data.groups.length; group_i++) {
- const group = data.groups[group_i]
- addGroup(group.label)
- for (let case_i = 0; case_i < group.inputs[0].values.length; case_i++) {
- addCase(group_i)
- }
- }
-
- // Add input values
- for (let input_i = 0; input_i < data.groups[0].inputs.length; input_i++) {
- const input = data.groups[0].inputs[input_i]
- const values = data.groups.map((group) => group.inputs[input_i].values)
-
- addInput(input.label, input.bitWidth, values)
- }
-
- // Add output values
- for (
- let output_i = 0;
- output_i < data.groups[0].outputs.length;
- output_i++
- ) {
- const output = data.groups[0].outputs[output_i]
- const values = data.groups.map(
- (group) => group.outputs[output_i].values
- )
-
- addOutput(output.label, output.bitWidth, values)
- }
-}
-
-/**
- * Loads result from JSON string into the testbench creator UI
- */
-function loadResult(dataJSON) {
- const data = JSON.parse(dataJSON)
- if (data.title) $('#test-title-label').text(data.title)
- changeTestMode()
- changeTestMode(data.type)
- for (let group_i = 0; group_i < data.groups.length; group_i++) {
- const group = data.groups[group_i]
- addGroup(group.label)
- for (let case_i = 0; case_i < group.inputs[0].values.length; case_i++) {
- addCase(group_i)
- }
- }
-
- // Add input values
- for (let input_i = 0; input_i < data.groups[0].inputs.length; input_i++) {
- const input = data.groups[0].inputs[input_i]
- const values = data.groups.map((group) => group.inputs[input_i].values)
-
- addInput(input.label, input.bitWidth, values)
- }
-
- // Add output values
- for (
- let output_i = 0;
- output_i < data.groups[0].outputs.length;
- output_i++
- ) {
- const output = data.groups[0].outputs[output_i]
- const values = data.groups.map(
- (group) => group.outputs[output_i].values
- )
- const results = data.groups.map(
- (group) => group.outputs[output_i].results
- )
- const expectedOutputs = []
- const actualOutputs = []
-
- for (let group_i = 0; group_i < values.length; group_i++) {
- const groupExpectedOuts = []
- const groupActualOuts = []
- for (let val_i = 0; val_i < values[group_i].length; val_i++) {
- groupExpectedOuts.push(values[group_i][val_i])
- groupActualOuts.push(results[group_i][val_i])
- }
-
- expectedOutputs.push(groupExpectedOuts)
- actualOutputs.push(groupActualOuts)
- }
- addOutput(
- `${output.label}`,
- output.bitWidth,
- expectedOutputs,
- true,
- actualOutputs
- )
- }
-}
-
-/**
- * Makes the UI read only for displaying results
- */
-function readOnlyUI() {
- makeContentUneditable()
- makeUnsortable()
- $('.lower-button, .table-button, .tb-minus').hide()
- $('.tablink').attr('disabled', 'disabled')
- $('.tablink').removeClass('tablink-no-override')
- $('.data-group-info').text('')
-}
-
-function makeContentUneditable() {
- $('body')
- .find('td, th, span, h3, div')
- .each(function () {
- $(this).attr('contenteditable', 'false')
- })
-}
-
-function makeSortable() {
- const helper = function (e, ui) {
- const helperE = ui.clone()
- helperE.children().each(function (child_i) {
- $(this).width(ui.children().eq(child_i).width())
- })
-
- return helperE
- }
-
- function makePlaceholder(e, ui) {
- ui.placeholder.children().each(function () {
- $(this).css('border', '0px')
- })
- }
-
- /*
- Sortable hack: To allow sorting inside empty tables, the tables should have some height.
- But it is not possible to give tables height without having rows, so we add a tbody.
- tbody gives the table height but messes up all the other things. So we only keep tbody
- if the table has no rows, and once table gets rows, we remove that tbody
- */
- function removeTbody(e, ui) {
- $(e.target).find('tbody').remove()
- }
-
- function createTbody(e, ui) {
- if ($(e.target).find('tr, tbody').length === 0) {
- $(e.target).append('')
- }
- }
-
- $('.data-group table').sortable({
- handle: '.tb-handle',
- helper,
- start: makePlaceholder,
- placeholder: 'clone',
- connectWith: 'table',
- receive: removeTbody, // For sortable hack
- remove: createTbody, // For sortable hack
- items: 'tr',
- revert: 50,
- scroll: false,
- })
-}
-
-function makeUnsortable() {
- $('.data-group table').sortable({ disabled: true })
-}
-
-function escapeHtml(unsafe) {
- return unsafe
- .replace(/&/g, '&')
- .replace(//g, '>')
- .replace(/"/g, '"')
- .replace(/'/g, ''')
-}
-
-// Making HTML called functions global
-
-window.addGroup = addGroup
-window.deleteGroup = deleteGroup
-window.addCase = addCase
-window.deleteCase = deleteCase
-window.addInput = addInput
-window.deleteInput = deleteInput
-window.addOutput = addOutput
-window.deleteOutput = deleteOutput
-window.parse = parse
-window.saveData = saveData
-window.changeTestMode = changeTestMode
-window.exportAsCSV = exportAsCSV
-window.importFromCSV = importFromCSV
-window.csv2json = csv2json
-window.clickUpload = clickUpload
diff --git a/v1/src/simulator/src/testbench.js b/v1/src/simulator/src/testbench.js
deleted file mode 100644
index d6f8a070..00000000
--- a/v1/src/simulator/src/testbench.js
+++ /dev/null
@@ -1,1140 +0,0 @@
-/**
- * This file contains all functions related the the testbench
- * Contains the the testbench engine and UI modules
- */
-
-import { scheduleBackup } from './data/backupCircuit'
-import { changeClockEnable } from './sequential'
-import { play } from './engine'
-import Scope from './circuit'
-import { showMessage, escapeHtml } from './utils'
-import { confirmOption } from '#/components/helpers/confirmComponent/ConfirmComponent.vue'
-
-/**
- * @typedef {number} RunContext
- */
-const CONTEXT = {
- CONTEXT_SIMULATOR: 0,
- CONTEXT_ASSIGNMENTS: 1,
-}
-
-const VALIDATION_ERRORS = {
- NOTPRESENT: 0, // Element is not present in the circuit
- WRONGBITWIDTH: 1, // Element is present but has incorrect bitwidth
- DUPLICATE_ID_DATA: 2, // Duplicate identifiers in test data
- DUPLICATE_ID_SCOPE: 3, // Duplicate identifiers in scope
- NO_RST: 4, // Sequential circuit but no reset(RST) in scope
-}
-
-const TESTBENCH_CREATOR_PATH = '/testbench'
-
-// Do we have any other function to do this?
-// Utility function. Converts decimal number to binary string
-function dec2bin(dec, bitWidth = undefined) {
- if (dec === undefined) return 'X'
- const bin = (dec >>> 0).toString(2)
- if (!bitWidth) return bin
-
- return '0'.repeat(bitWidth - bin.length) + bin
-}
-
-/**
- * Class to store all data related to the testbench and functions to use it
- * @param {Object} data - Javascript object of the test data
- * @param {number=} currentGroup - Current group index in the test
- * @param {number=} currentCase - Current case index in the group
- */
-export class TestbenchData {
- constructor(data, currentGroup = 0, currentCase = 0) {
- this.currentCase = currentCase
- this.currentGroup = currentGroup
- this.testData = data
- }
-
- /**
- * Checks whether given case-group pair exists in the test
- */
- isCaseValid() {
- if (
- this.currentGroup >= this.data.groups.length ||
- this.currentGroup < 0
- )
- return false
- const caseCount =
- this.testData.groups[this.currentGroup].inputs[0].values.length
- if (this.currentCase >= caseCount || this.currentCase < 0) return false
-
- return true
- }
-
- /**
- * Validate and set case and group in the test
- * @param {number} groupIndex - Group index to set
- * @param {number} caseIndex - Case index to set
- */
- setCase(groupIndex, caseIndex) {
- const newCase = new TestbenchData(this.testData, groupIndex, caseIndex)
- if (newCase.isCaseValid()) {
- this.currentGroup = groupIndex
- this.currentCase = caseIndex
- return true
- }
-
- return false
- }
-
- /**
- * Validate and go to the next group.
- * Skips over empty groups
- */
- groupNext() {
- const newCase = new TestbenchData(this.testData, this.currentGroup, 0)
- const groupCount = newCase.testData.groups.length
- let caseCount =
- newCase.testData.groups[newCase.currentGroup].inputs[0].values
- .length
-
- while (caseCount === 0 || this.currentGroup === newCase.currentGroup) {
- newCase.currentGroup++
- if (newCase.currentGroup >= groupCount) return false
- caseCount =
- newCase.testData.groups[newCase.currentGroup].inputs[0].values
- .length
- }
-
- this.currentGroup = newCase.currentGroup
- this.currentCase = newCase.currentCase
- return true
- }
-
- /**
- * Validate and go to the previous group.
- * Skips over empty groups
- */
- groupPrev() {
- const newCase = new TestbenchData(this.testData, this.currentGroup, 0)
- const groupCount = newCase.testData.groups.length
- let caseCount =
- newCase.testData.groups[newCase.currentGroup].inputs[0].values
- .length
-
- while (caseCount === 0 || this.currentGroup === newCase.currentGroup) {
- newCase.currentGroup--
- if (newCase.currentGroup < 0) return false
- caseCount =
- newCase.testData.groups[newCase.currentGroup].inputs[0].values
- .length
- }
-
- this.currentGroup = newCase.currentGroup
- this.currentCase = newCase.currentCase
- return true
- }
-
- /**
- * Validate and go to the next case
- */
- caseNext() {
- const caseCount =
- this.testData.groups[this.currentGroup].inputs[0].values.length
- if (this.currentCase >= caseCount - 1) return this.groupNext()
- this.currentCase++
- return true
- }
-
- /**
- * Validate and go to the previous case
- */
- casePrev() {
- if (this.currentCase <= 0) {
- if (!this.groupPrev()) return false
- const caseCount =
- this.testData.groups[this.currentGroup].inputs[0].values.length
- this.currentCase = caseCount - 1
- return true
- }
-
- this.currentCase--
- return true
- }
-
- /**
- * Finds and switches to the first non empty group to start the test from
- */
- goToFirstValidGroup() {
- const newCase = new TestbenchData(this.testData, 0, 0)
- const caseCount =
- newCase.testData.groups[this.currentGroup].inputs[0].values.length
-
- // If the first group is not empty, do nothing
- if (caseCount > 0) return true
-
- // Otherwise go next until non empty group
- const validExists = newCase.groupNext()
-
- // If all groups empty return false
- if (!validExists) return false
-
- // else set case to the non empty group
- this.currentGroup = newCase.currentGroup
- this.currentCase = newCase.currentCase
- return true
- }
-}
-
-/**
- * UI Function
- * Create prompt for the testbench UI when creator is opened
- */
-function creatorOpenPrompt(creatorWindow) {
- scheduleBackup()
- const windowSVG = `
-
- `
-
- const s = `
-
-
- ${windowSVG}
-
-
A browser pop-up is opened to create the test
-
Please save the test to open it here
-
- `
-
- $('#setTestbenchData').dialog({
- resizable: false,
- width: 'auto',
- buttons: [
- {
- text: 'Close Pop-Up',
- click() {
- $(this).dialog('close')
- creatorWindow.close()
- },
- },
- ],
- })
-
- $('#setTestbenchData').empty()
- $('#setTestbenchData').append(s)
-}
-
-/**
- * Interface function to run testbench. Called by testbench prompt on simulator or assignments
- * @param {Object} data - Object containing Test Data
- * @param {RunContext=} runContext - Whether simulator or Assignment called this function
- * @param {Scope=} scope - the circuit
- */
-export function runTestBench(
- data,
- scope = globalScope,
- runContext = CONTEXT.CONTEXT_SIMULATOR
-) {
- const isValid = validate(data, scope)
- if (!isValid.ok) {
- showMessage(
- 'Testbench: Some elements missing from circuit. Click Validate to know more'
- )
- }
-
- if (runContext === CONTEXT.CONTEXT_SIMULATOR) {
- const tempTestbenchData = new TestbenchData(data)
- if (!tempTestbenchData.goToFirstValidGroup()) {
- showMessage('Testbench: The test is empty')
- return
- }
-
- globalScope.testbenchData = tempTestbenchData
-
- updateTestbenchUI()
- return
- }
-
- if (runContext === CONTEXT.CONTEXT_ASSIGNMENTS) {
- // Not implemented
- }
-}
-
-/**
- * Updates the TestBench UI on the simulator with the current test attached
- * If no test is attached then shows the 'No test attached' screen
- * Called by runTestBench() when test is set, also called by UX/setupPanelListeners()
- * whenever ux change requires this UI to update(such as clicking on a different circuit or
- * loading a saved circuit)
- */
-export function updateTestbenchUI() {
- // Remove all listeners from buttons
- $('.tb-dialog-button').off('click')
- $('.tb-case-button').off('click')
-
- setupTestbenchUI()
- if (globalScope.testbenchData != undefined) {
- const { testbenchData } = globalScope
-
- // Initialize the UI
- setUITableHeaders(testbenchData)
-
- // Add listeners to buttons
- $('.tb-case-button#prev-case-btn').on(
- 'click',
- buttonListenerFunctions.previousCaseButton
- )
- $('.tb-case-button#next-case-btn').on(
- 'click',
- buttonListenerFunctions.nextCaseButton
- )
- $('.tb-case-button#prev-group-btn').on(
- 'click',
- buttonListenerFunctions.previousGroupButton
- )
- $('.tb-case-button#next-group-btn').on(
- 'click',
- buttonListenerFunctions.nextGroupButton
- )
- $('.tb-dialog-button#change-test-btn').on(
- 'click',
- buttonListenerFunctions.changeTestButton
- )
- $('.tb-dialog-button#runall-btn').on(
- 'click',
- buttonListenerFunctions.runAllButton
- )
- $('.tb-dialog-button#edit-test-btn').on(
- 'click',
- buttonListenerFunctions.editTestButton
- )
- $('.tb-dialog-button#validate-btn').on(
- 'click',
- buttonListenerFunctions.validateButton
- )
- $('.tb-dialog-button#remove-test-btn').on(
- 'click',
- buttonListenerFunctions.removeTestButton
- )
- }
-
- // Add listener to attach test button
- $('.tb-dialog-button#attach-test-btn').on(
- 'click',
- buttonListenerFunctions.attachTestButton
- )
-}
-
-/**
- * Defines all the functions called as event listeners for buttons on the UI
- */
-const buttonListenerFunctions = {
- previousCaseButton: () => {
- const isValid = validate(
- globalScope.testbenchData.testData,
- globalScope
- )
- if (!isValid.ok) {
- showMessage(
- 'Testbench: Some elements missing from circuit. Click Validate to know more'
- )
- return
- }
- globalScope.testbenchData.casePrev()
- buttonListenerFunctions.computeCase()
- },
-
- nextCaseButton: () => {
- const isValid = validate(
- globalScope.testbenchData.testData,
- globalScope
- )
- if (!isValid.ok) {
- showMessage(
- 'Testbench: Some elements missing from circuit. Click Validate to know more'
- )
- return
- }
- globalScope.testbenchData.caseNext()
- buttonListenerFunctions.computeCase()
- },
-
- previousGroupButton: () => {
- const isValid = validate(
- globalScope.testbenchData.testData,
- globalScope
- )
- if (!isValid.ok) {
- showMessage(
- 'Testbench: Some elements missing from circuit. Click Validate to know more'
- )
- return
- }
- globalScope.testbenchData.groupPrev()
- buttonListenerFunctions.computeCase()
- },
-
- nextGroupButton: () => {
- const isValid = validate(
- globalScope.testbenchData.testData,
- globalScope
- )
- if (!isValid.ok) {
- showMessage(
- 'Testbench: Some elements missing from circuit. Click Validate to know more'
- )
- return
- }
- globalScope.testbenchData.groupNext()
- buttonListenerFunctions.computeCase()
- },
-
- changeTestButton: () => {
- openCreator('create')
- },
-
- runAllButton: () => {
- const isValid = validate(
- globalScope.testbenchData.testData,
- globalScope
- )
- if (!isValid.ok) {
- showMessage(
- 'Testbench: Some elements missing from circuit. Click Validate to know more'
- )
- return
- }
- const results = runAll(globalScope.testbenchData.testData, globalScope)
- const { passed } = results.summary
- const { total } = results.summary
- const resultString = JSON.stringify(results.detailed)
- $('#runall-summary').text(`${passed} out of ${total}`)
- $('#runall-detailed-link').on('click', () => {
- openCreator('result', resultString)
- })
- $('.testbench-runall-label').css('display', 'table-cell')
- $('.testbench-runall-label').delay(5000).fadeOut('slow')
- },
-
- editTestButton: () => {
- const editDataString = JSON.stringify(
- globalScope.testbenchData.testData
- )
- openCreator('edit', editDataString)
- },
-
- validateButton: () => {
- const isValid = validate(
- globalScope.testbenchData.testData,
- globalScope
- )
- showValidationUI(isValid)
- },
-
- removeTestButton: async () => {
- if (
- await confirmOption(
- 'Are you sure you want to remove the test from the circuit?'
- )
- ) {
- globalScope.testbenchData = undefined
- setupTestbenchUI()
- }
- },
-
- attachTestButton: () => {
- openCreator('create')
- },
-
- rerunTestButton: () => {
- buttonListenerFunctions.computeCase()
- },
-
- computeCase: () => {
- setUICurrentCase(globalScope.testbenchData)
- const result = runSingleTest(globalScope.testbenchData, globalScope)
- setUIResult(globalScope.testbenchData, result)
- },
-}
-
-/**
- * UI Function
- * Checks whether test is attached to the scope and switches UI accordingly
- */
-export function setupTestbenchUI() {
- // Don't change UI if UI is minimized (because hide() and show() are recursive)
- if ($('.testbench-manual-panel .minimize').css('display') === 'none') return
-
- if (globalScope.testbenchData === undefined) {
- $('.tb-test-not-null').hide()
- $('.tb-test-null').show()
- return
- }
-
- $('.tb-test-null').hide()
- $('.tb-test-not-null').show()
-}
-
-/**
- * Run all the tests automatically. Called by runTestBench()
- * @param {Object} data - Object containing Test Data
- * @param {Scope=} scope - the circuit
- */
-export function runAll(data, scope = globalScope) {
- // Stop the clocks
- // TestBench will now take over clock toggling
- changeClockEnable(false)
-
- const { inputs, outputs, reset } = bindIO(data, scope)
- let totalCases = 0
- let passedCases = 0
-
- data.groups.forEach((group) => {
- // for (const output of group.outputs) output.results = [];
- group.outputs.forEach((output) => (output.results = []))
- for (let case_i = 0; case_i < group.n; case_i++) {
- totalCases++
- // Set and propagate the inputs
- setInputValues(inputs, group, case_i, scope)
- // If sequential, trigger clock now
- if (data.type === 'seq') tickClock(scope)
- // Get output values
- const caseResult = getOutputValues(data, outputs)
- // Put the results in the data
-
- let casePassed = true // Tracks if current case passed or failed
-
- caseResult.forEach((_, outName) => {
- // TODO: find() is not the best idea because of O(n)
- const output = group.outputs.find(
- (dataOutput) => dataOutput.label === outName
- )
- output.results.push(caseResult.get(outName))
-
- if (output.values[case_i] !== caseResult.get(outName))
- casePassed = false
- })
-
- // If current case passed, then increment passedCases
- if (casePassed) passedCases++
- }
-
- // If sequential, trigger reset at the end of group (set)
- if (data.type === 'seq') triggerReset(reset)
- })
-
- // Tests done, restart the clocks
- changeClockEnable(true)
-
- // Return results
- const results = {}
- results.detailed = data
- results.summary = { passed: passedCases, total: totalCases }
- return results
-}
-
-/**
- * Runs single test
- * @param {Object} data - Object containing Test Data
- * @param {number} groupIndex - Index of the group to be tested
- * @param {number} caseIndex - Index of the case inside the group
- * @param {Scope} scope - The circuit
- */
-function runSingleTest(testbenchData, scope) {
- const data = testbenchData.testData
-
- let result
- if (data.type === 'comb') {
- result = runSingleCombinational(testbenchData, scope)
- } else if (data.type === 'seq') {
- result = runSingleSequential(testbenchData, scope)
- }
-
- return result
-}
-
-/**
- * Runs single combinational test
- * @param {Object} data - Object containing Test Data
- * @param {number} groupIndex - Index of the group to be tested
- * @param {number} caseIndex - Index of the case inside the group
- * @param {Scope} scope - The circuit
- */
-function runSingleCombinational(testbenchData, scope) {
- const data = testbenchData.testData
- const groupIndex = testbenchData.currentGroup
- const caseIndex = testbenchData.currentCase
-
- const { inputs, outputs } = bindIO(data, scope)
- const group = data.groups[groupIndex]
-
- // Stop the clocks
- changeClockEnable(false)
-
- // Set input values according to the test
- setInputValues(inputs, group, caseIndex, scope)
- // Check output values
- const result = getOutputValues(data, outputs)
- // Restart the clocks
- changeClockEnable(true)
- return result
-}
-
-/**
- * Runs single sequential test and all tests above it in the group
- * Used in MANUAL mode
- * @param {Object} data - Object containing Test Data
- * @param {number} groupIndex - Index of the group to be tested
- * @param {number} caseIndex - Index of the case inside the group
- * @param {Scope} scope - The circuit
- */
-function runSingleSequential(testbenchData, scope) {
- const data = testbenchData.testData
- const groupIndex = testbenchData.currentGroup
- const caseIndex = testbenchData.currentCase
-
- const { inputs, outputs, reset } = bindIO(data, scope)
- const group = data.groups[groupIndex]
-
- // Stop the clocks
- changeClockEnable(false)
-
- // Trigger reset
- triggerReset(reset, scope)
-
- // Run the test and tests above in the same group
- for (let case_i = 0; case_i <= caseIndex; case_i++) {
- setInputValues(inputs, group, case_i, scope)
- tickClock(scope)
- }
-
- const result = getOutputValues(data, outputs)
-
- // Restart the clocks
- changeClockEnable(true)
-
- return result
-}
-
-/**
- * Set and propogate the input values according to the testcase.
- * Called by runSingle() and runAll()
- * @param {Object} inputs - Object with keys as input names and values as inputs
- * @param {Object} group - Test group
- * @param {number} caseIndex - Index of the case in the group
- * @param {Scope} scope - the circuit
- */
-function setInputValues(inputs, group, caseIndex, scope) {
- group.inputs.forEach((input) => {
- inputs[input.label].state = parseInt(input.values[caseIndex], 2)
- })
-
- // Propagate inputs
- play(scope)
-}
-
-/**
- * Gets Output values as a Map with keys as output name and value as output state
- * @param {Object} outputs - Object with keys as output names and values as outputs
- */
-function getOutputValues(data, outputs) {
- const values = new Map()
-
- data.groups[0].outputs.forEach((dataOutput) => {
- // Using node value because output state only changes on rendering
- const resultValue = outputs[dataOutput.label].nodeList[0].value
- const resultBW = outputs[dataOutput.label].nodeList[0].bitWidth
- values.set(dataOutput.label, dec2bin(resultValue, resultBW))
- })
-
- return values
-}
-
-/**
- * UI Function
- * Shows validation UI
- * @param {Object} validationErrors - Object with errors returned by validate()
- */
-function showValidationUI(validationErrors) {
- const checkSVG = `
-
- `
-
- let s = `
-
-
- ${checkSVG}
-
- All good. No validation errors
-
- `
-
- if (!validationErrors.ok) {
- s = `
-
-
Please fix these errors to run tests
-
-
- Identifier |
- Error |
-
- `
-
- validationErrors.invalids.forEach((vError) => {
- s += `
-
- ${vError.identifier} |
- ${vError.message} |
-
- `
- })
-
- s += '
'
- }
-
- $('#testbenchValidate').dialog({
- resizable: false,
- width: 'auto',
- buttons: [
- {
- text: 'Ok',
- click() {
- $(this).dialog('close')
- },
- },
- {
- text: 'Auto Fix',
- click() {
- const fixes = validationAutoFix(validationErrors)
- showMessage(`Testbench: Auto fixed ${fixes} errors`)
- $(this).dialog('close')
- },
- },
- ],
- })
-
- $('#testbenchValidate').empty()
- $('#testbenchValidate').append(s)
-}
-
-/**
- * Validate if all inputs and output elements are present with correct bitwidths
- * @param {Object} data - Object containing Test Data
- * @param {Scope} scope - the circuit
- */
-function validate(data, scope) {
- let invalids = []
-
- // Check for duplicate identifiers
- if (!checkDistinctIdentifiersData(data)) {
- invalids.push({
- type: VALIDATION_ERRORS.DUPLICATE_ID_DATA,
- identifier: '-',
- message: 'Duplicate identifiers in test data',
- })
- }
-
- if (!checkDistinctIdentifiersScope(scope)) {
- invalids.push({
- type: VALIDATION_ERRORS.DUPLICATE_ID_SCOPE,
- identifier: '-',
- message: 'Duplicate identifiers in circuit',
- })
- }
-
- // Don't do further checks if duplicates
- if (invalids.length > 0) return { ok: false, invalids }
-
- // Validate inputs and outputs
- const inputsValid = validateInputs(data, scope)
- const outputsValid = validateOutputs(data, scope)
-
- invalids = inputsValid.ok ? invalids : invalids.concat(inputsValid.invalids)
- invalids = outputsValid.ok
- ? invalids
- : invalids.concat(outputsValid.invalids)
-
- // Validate presence of reset if test is sequential
- if (data.type === 'seq') {
- const resetPresent = scope.Input.some(
- (simulatorReset) =>
- simulatorReset.label === 'RST' &&
- simulatorReset.bitWidth === 1 &&
- simulatorReset.objectType === 'Input'
- )
-
- if (!resetPresent) {
- invalids.push({
- type: VALIDATION_ERRORS.NO_RST,
- identifier: 'RST',
- message: 'Reset(RST) not present in circuit',
- })
- }
- }
-
- if (invalids.length > 0) return { ok: false, invalids }
- return { ok: true }
-}
-
-/**
- * Autofix whatever is possible in validation errors.
- * returns number of autofixed errors
- * @param {Object} validationErrors - Object with errors returned by validate()
- */
-function validationAutoFix(validationErrors) {
- // Currently only autofixes bitwidths
- let fixedErrors = 0
- // Return if no errors
- if (validationErrors.ok) return fixedErrors
-
- const bitwidthErrors = validationErrors.invalids.filter(
- (vError) => vError.type === VALIDATION_ERRORS.WRONGBITWIDTH
- )
-
- bitwidthErrors.forEach((bwError) => {
- const { element, expectedBitWidth } = bwError.extraInfo
- element.newBitWidth(expectedBitWidth)
- fixedErrors++
- })
-
- return fixedErrors
-}
-
-/**
- * Checks if all the labels in the test data are unique. Called by validate()
- * @param {Object} data - Object containing Test Data
- */
-function checkDistinctIdentifiersData(data) {
- const inputIdentifiersData = data.groups[0].inputs.map(
- (input) => input.label
- )
- const outputIdentifiersData = data.groups[0].outputs.map(
- (output) => output.label
- )
- const identifiersData = inputIdentifiersData.concat(outputIdentifiersData)
-
- return new Set(identifiersData).size === identifiersData.length
-}
-
-/**
- * Checks if all the input/output labels in the scope are unique. Called by validate()
- * TODO: Replace with identifiers
- * @param {Scope} scope - the circuit
- */
-function checkDistinctIdentifiersScope(scope) {
- const inputIdentifiersScope = scope.Input.map((input) => input.label)
- const outputIdentifiersScope = scope.Output.map((output) => output.label)
- let identifiersScope = inputIdentifiersScope.concat(outputIdentifiersScope)
-
- // Remove identifiers which have not been set yet (ie. empty strings)
- identifiersScope = identifiersScope.filter((identifer) => identifer != '')
-
- return new Set(identifiersScope).size === identifiersScope.length
-}
-
-/**
- * Validates presence and bitwidths of test inputs in the circuit.
- * Called by validate()
- * @param {Object} data - Object containing Test Data
- * @param {Scope} scope - the circuit
- */
-function validateInputs(data, scope) {
- const invalids = []
-
- data.groups[0].inputs.forEach((dataInput) => {
- const matchInput = scope.Input.find(
- (simulatorInput) => simulatorInput.label === dataInput.label
- )
-
- if (matchInput === undefined) {
- invalids.push({
- type: VALIDATION_ERRORS.NOTPRESENT,
- identifier: dataInput.label,
- message: 'Input is not present in the circuit',
- })
- } else if (matchInput.bitWidth !== dataInput.bitWidth) {
- invalids.push({
- type: VALIDATION_ERRORS.WRONGBITWIDTH,
- identifier: dataInput.label,
- extraInfo: {
- element: matchInput,
- expectedBitWidth: dataInput.bitWidth,
- },
- message: `Input bitwidths don't match in circuit and test (${matchInput.bitWidth} vs ${dataInput.bitWidth})`,
- })
- }
- })
-
- if (invalids.length > 0) return { ok: false, invalids }
- return { ok: true }
-}
-
-/**
- * Validates presence and bitwidths of test outputs in the circuit.
- * Called by validate()
- * @param {Object} data - Object containing Test Data
- * @param {Scope} scope - the circuit
- */
-function validateOutputs(data, scope) {
- const invalids = []
-
- data.groups[0].outputs.forEach((dataOutput) => {
- const matchOutput = scope.Output.find(
- (simulatorOutput) => simulatorOutput.label === dataOutput.label
- )
-
- if (matchOutput === undefined) {
- invalids.push({
- type: VALIDATION_ERRORS.NOTPRESENT,
- identifier: dataOutput.label,
- message: 'Output is not present in the circuit',
- })
- } else if (matchOutput.bitWidth !== dataOutput.bitWidth) {
- invalids.push({
- type: VALIDATION_ERRORS.WRONGBITWIDTH,
- identifier: dataOutput.label,
- extraInfo: {
- element: matchOutput,
- expectedBitWidth: dataOutput.bitWidth,
- },
- message: `Output bitwidths don't match in circuit and test (${matchOutput.bitWidth} vs ${dataOutput.bitWidth})`,
- })
- }
- })
-
- if (invalids.length > 0) return { ok: false, invalids }
- return { ok: true }
-}
-
-/**
- * Returns object of scope inputs and outputs keyed by their labels
- * @param {Object} data - Object containing Test Data
- * @param {Scope=} scope - the circuit
- */
-function bindIO(data, scope) {
- const inputs = {}
- const outputs = {}
- let reset
-
- data.groups[0].inputs.forEach((dataInput) => {
- inputs[dataInput.label] = scope.Input.find(
- (simulatorInput) => simulatorInput.label === dataInput.label
- )
- })
-
- data.groups[0].outputs.forEach((dataOutput) => {
- outputs[dataOutput.label] = scope.Output.find(
- (simulatorOutput) => simulatorOutput.label === dataOutput.label
- )
- })
-
- if (data.type === 'seq') {
- reset = scope.Input.find(
- (simulatorOutput) => simulatorOutput.label === 'RST'
- )
- }
-
- return { inputs, outputs, reset }
-}
-
-/**
- * Ticks clock recursively one full cycle (Only used in testbench context)
- * @param {Scope} scope - the circuit whose clock to be ticked
- */
-function tickClock(scope) {
- scope.clockTick()
- play(scope)
- scope.clockTick()
- play(scope)
-}
-
-/**
- * Triggers reset (Only used in testbench context)
- * @param {Input} reset - reset pin to be triggered
- * @param {Scope} scope - the circuit
- */
-function triggerReset(reset, scope) {
- reset.state = 1
- play(scope)
- reset.state = 0
- play(scope)
-}
-
-/**
- * UI Function
- * Sets IO labels and bitwidths on UI table
- * Called by simulatorRunTestbench()
- * @param {Object} data - Object containing the test data
- */
-function setUITableHeaders(testbenchData) {
- const data = testbenchData.testData
- const inputCount = data.groups[0].inputs.length
- const outputCount = data.groups[0].outputs.length
-
- $('#tb-manual-table-inputs-head').attr('colspan', inputCount)
- $('#tb-manual-table-outputs-head').attr('colspan', outputCount)
-
- $('.testbench-runall-label').css('display', 'none')
-
- $('.tb-data#data-title')
- .children()
- .eq(1)
- .text(data.title || 'Untitled')
- $('.tb-data#data-type')
- .children()
- .eq(1)
- .text(data.type === 'comb' ? 'Combinational' : 'Sequential')
-
- $('#tb-manual-table-labels').html('LABELS | ')
- $('#tb-manual-table-bitwidths').html('Bitwidth | ')
-
- data.groups[0].inputs.concat(data.groups[0].outputs).forEach((io) => {
- const label = `${escapeHtml(io.label)} | `
- const bw = `${escapeHtml(io.bitWidth.toString())} | `
- $('#tb-manual-table-labels').append(label)
- $('#tb-manual-table-bitwidths').append(bw)
- })
-
- setUICurrentCase(testbenchData)
-}
-
-/**
- * UI Function
- * Set current test case data on the UI
- * @param {Object} data - Object containing the test data
- * @param {number} groupIndex - Index of the group of current case
- * @param {number} caseIndex - Index of the case within the group
- */
-function setUICurrentCase(testbenchData) {
- const data = testbenchData.testData
- const groupIndex = testbenchData.currentGroup
- const caseIndex = testbenchData.currentCase
-
- const currCaseElement = $('#tb-manual-table-current-case')
- currCaseElement.empty()
- currCaseElement.append('Current Case | ')
- $('#tb-manual-table-test-result').empty()
- $('#tb-manual-table-test-result').append('Result | ')
-
- data.groups[groupIndex].inputs.forEach((input) => {
- currCaseElement.append(
- `${escapeHtml(input.values[caseIndex])} | `
- )
- })
-
- data.groups[groupIndex].outputs.forEach((output) => {
- currCaseElement.append(
- `${escapeHtml(output.values[caseIndex])} | `
- )
- })
-
- $('.testbench-manual-panel .group-label').text(
- data.groups[groupIndex].label
- )
- $('.testbench-manual-panel .case-label').text(caseIndex + 1)
-}
-
-/**
- * UI Function
- * Set the current test case result on the UI
- * @param {Object} data - Object containing the test data
- * @param {Map} result - Map containing the output values (returned by getOutputValues())
- */
-function setUIResult(testbenchData, result) {
- const data = testbenchData.testData
- const groupIndex = testbenchData.currentGroup
- const caseIndex = testbenchData.currentCase
- const resultElement = $('#tb-manual-table-test-result')
- let inputCount = data.groups[0].inputs.length
- resultElement.empty()
- resultElement.append('Result | ')
- while (inputCount--) {
- resultElement.append(' - | ')
- }
-
- for (const output of result.keys()) {
- const resultValue = result.get(output)
- const expectedValue = data.groups[groupIndex].outputs.find(
- (dataOutput) => dataOutput.label === output
- ).values[caseIndex]
- const color = resultValue === expectedValue ? '#17FC12' : '#FF1616'
- resultElement.append(
- `${escapeHtml(resultValue)} | `
- )
- }
-}
-
-/**
- * Use this function to navigate to test creator. This function starts the storage listener
- * so the test is loaded directly into the simulator
- * @param {string} type - 'create', 'edit' or 'result'
- * @param {String} dataString - data in JSON string to load in case of 'edit' and 'result'
- */
-function openCreator(type, dataString) {
- const popupHeight = 800
- const popupWidth = 1200
- const popupTop = (window.height - popupHeight) / 2
- const popupLeft = (window.width - popupWidth) / 2
- const POPUP_STYLE_STRING = `height=${popupHeight},width=${popupWidth},top=${popupTop},left=${popupLeft}`
- let popUp
-
- /* Listener to catch testData from pop up and load it onto the testbench */
- const dataListener = (message) => {
- if (
- message.origin !== window.origin ||
- message.data.type !== 'testData'
- )
- return
-
- // Check if the current scope requested the creator pop up
- const data = JSON.parse(message.data.data)
-
- // Unbind event listener
- window.removeEventListener('message', dataListener)
-
- // If scopeID does not match, do nothing and return
- if (data.scopeID != globalScope.id) return
-
- // Load test data onto the scope
- runTestBench(data.testData, globalScope, CONTEXT.CONTEXT_SIMULATOR)
-
- // Close the 'Pop up is open' dialog
- $('#setTestbenchData').dialog('close')
- }
-
- if (type === 'create') {
- const url = `${TESTBENCH_CREATOR_PATH}?scopeID=${globalScope.id}&popUp=true`
- popUp = window.open(url, 'popupWindow', POPUP_STYLE_STRING)
- creatorOpenPrompt(popUp)
- window.addEventListener('message', dataListener)
- }
-
- if (type === 'edit') {
- const url = `${TESTBENCH_CREATOR_PATH}?scopeID=${globalScope.id}&data=${dataString}&popUp=true`
- popUp = window.open(url, 'popupWindow', POPUP_STYLE_STRING)
- creatorOpenPrompt(popUp)
- window.addEventListener('message', dataListener)
- }
-
- if (type === 'result') {
- const url = `${TESTBENCH_CREATOR_PATH}?scopeID=${globalScope.id}&result=${dataString}&popUp=true`
- popUp = window.open(url, 'popupWindow', POPUP_STYLE_STRING)
- }
-
- // Check if popup was closed (in case it was closed by window's X button),
- // then close 'popup open' dialog
- if (popUp && type !== 'result') {
- const checkPopUp = setInterval(() => {
- if (popUp.closed) {
- // Close the dialog if it's open
- if ($('#setTestbenchData').dialog('isOpen'))
- $('#setTestbenchData').dialog('close')
-
- // Remove the event listener that listens for data from popup
- window.removeEventListener('message', dataListener)
- clearInterval(checkPopUp)
- }
- }, 1000)
- }
-}
diff --git a/v1/src/simulator/src/testbench.ts b/v1/src/simulator/src/testbench.ts
new file mode 100644
index 00000000..70676e09
--- /dev/null
+++ b/v1/src/simulator/src/testbench.ts
@@ -0,0 +1,761 @@
+import { TestData } from "#/store/testBenchStore";
+import { showMessage } from '#/simulator/src/utils'
+import { useTestBenchStore, TestBenchData } from "#/store/testBenchStore";
+import { changeClockEnable } from '#/simulator/src/sequential'
+import { play } from '#/simulator/src/engine'
+import { confirmOption } from '#/components/helpers/confirmComponent/ConfirmComponent.vue'
+import { escapeHtml } from '#/simulator/src/utils'
+
+const CONTEXT = {
+ CONTEXT_SIMULATOR: 0,
+ CONTEXT_ASSIGNMENTS: 1,
+}
+
+export const VALIDATION_ERRORS = {
+ NOTPRESENT: 0, // Element is not present in the circuit
+ WRONGBITWIDTH: 1, // Element is present but has incorrect bitwidth
+ DUPLICATE_ID_DATA: 2, // Duplicate identifiers in test data
+ DUPLICATE_ID_SCOPE: 3, // Duplicate identifiers in scope
+ NO_RST: 4, // Sequential circuit but no reset(RST) in scope
+}
+
+export class TestbenchData {
+ currentCase: number;
+ currentGroup: number;
+ testData: TestData;
+
+ constructor(data: TestData, currentGroup = 0, currentCase = 0) {
+ this.currentCase = currentCase;
+ this.currentGroup = currentGroup;
+ this.testData = data;
+ }
+
+ isCaseValid() {
+ if (this.currentGroup >= this.testData.groups.length || this.currentGroup < 0) return false;
+ const caseCount = this.testData.groups[this.currentGroup].inputs[0].values.length;
+ if (this.currentCase >= caseCount || this.currentCase < 0) return false;
+
+ return true;
+ }
+
+ setCase(groupIndex: number, caseIndex: number) {
+ const newCase = new TestbenchData(this.testData, groupIndex, caseIndex);
+ if (newCase.isCaseValid()) {
+ this.currentGroup = groupIndex;
+ this.currentCase = caseIndex;
+ return true;
+ }
+ return false;
+ }
+
+ groupNext() {
+ const newCase = new TestbenchData(this.testData, this.currentGroup, 0);
+ const groupCount = newCase.testData.groups.length;
+ let caseCount = 0;
+ if (newCase.testData.groups[this.currentGroup].inputs[0]) {
+ caseCount = newCase.testData.groups[this.currentGroup].inputs[0].values.length;
+ }
+
+ while (caseCount === 0 || this.currentGroup === newCase.currentGroup) {
+ newCase.currentGroup++;
+ if (newCase.currentGroup >= groupCount) return false;
+ caseCount = newCase.testData.groups[newCase.currentGroup].inputs[0].values.length;
+ }
+
+ this.currentGroup = newCase.currentGroup;
+ this.currentCase = newCase.currentCase;
+ return true;
+ }
+
+ groupPrev() {
+ const newCase = new TestbenchData(this.testData, this.currentGroup, 0);
+ const groupCount = newCase.testData.groups.length;
+ let caseCount = newCase.testData.groups[newCase.currentGroup].inputs[0].values.length;
+
+ while (caseCount === 0 || this.currentGroup === newCase.currentGroup) {
+ newCase.currentGroup--;
+ if (newCase.currentGroup < 0) return false;
+ caseCount = newCase.testData.groups[newCase.currentGroup].inputs[0].values.length;
+ }
+
+ this.currentGroup = newCase.currentGroup;
+ this.currentCase = newCase.currentCase;
+ return true;
+ }
+
+ caseNext() {
+ const caseCount = this.testData.groups[this.currentGroup].inputs[0].values.length;
+ if (this.currentCase >= caseCount - 1) return this.groupNext();
+ this.currentCase++;
+ return true;
+ }
+
+ casePrev() {
+ if (this.currentCase <= 0) {
+ if (!this.groupPrev()) return false;
+ const caseCount = this.testData.groups[this.currentGroup].inputs[0].values.length;
+ this.currentCase = caseCount - 1;
+ return true;
+ }
+
+ this.currentCase--;
+ return true;
+ }
+
+ goToFirstValidGroup() {
+ const newCase = new TestbenchData(this.testData, 0, 0);
+ let caseCount = 0;
+ if (newCase.testData.groups[this.currentGroup].inputs[0]) {
+ caseCount = newCase.testData.groups[this.currentGroup].inputs[0].values.length;
+ }
+
+ if (caseCount > 0) return true;
+
+ const validExists = newCase.groupNext();
+
+ if (!validExists) return false;
+
+ this.currentGroup = newCase.currentGroup;
+ this.currentCase = newCase.currentCase;
+ return true;
+ }
+}
+
+/**
+ * Checks if all the labels in the test data are unique. Called by validate()
+ */
+function checkDistinctIdentifiersData(data: TestData) {
+ const inputIdentifiersData = data.groups[0].inputs.map(
+ (input) => input.label
+ )
+ const outputIdentifiersData = data.groups[0].outputs.map(
+ (output) => output.label
+ )
+ const identifiersData = inputIdentifiersData.concat(outputIdentifiersData)
+
+ return new Set(identifiersData).size === identifiersData.length
+}
+
+/**
+ * Checks if all the input/output labels in the scope are unique. Called by validate()
+ * TODO: Replace with identifiers
+ */
+function checkDistinctIdentifiersScope(scope) {
+ const inputIdentifiersScope = scope.Input.map((input) => input.label)
+ const outputIdentifiersScope = scope.Output.map((output) => output.label)
+ let identifiersScope = inputIdentifiersScope.concat(outputIdentifiersScope)
+
+ // Remove identifiers which have not been set yet (ie. empty strings)
+ identifiersScope = identifiersScope.filter((identifer) => identifer != '')
+
+ return new Set(identifiersScope).size === identifiersScope.length
+}
+
+/**
+ * Validates presence and bitwidths of test inputs in the circuit.
+ * Called by validate()
+ */
+function validateInputs(data: TestData, scope) {
+ const invalids: Invalids[] = []
+
+ data.groups[0].inputs.forEach((dataInput) => {
+ const matchInput = scope.Input.find(
+ (simulatorInput) => simulatorInput.label === dataInput.label
+ )
+
+ if (matchInput === undefined) {
+ invalids.push({
+ type: VALIDATION_ERRORS.NOTPRESENT,
+ identifier: dataInput.label,
+ message: 'Input is not present in the circuit',
+ })
+ } else if (matchInput.bitWidth !== dataInput.bitWidth) {
+ invalids.push({
+ type: VALIDATION_ERRORS.WRONGBITWIDTH,
+ identifier: dataInput.label,
+ extraInfo: {
+ element: matchInput,
+ expectedBitWidth: dataInput.bitWidth,
+ },
+ message: `Input bitwidths don't match in circuit and test (${matchInput.bitWidth} vs ${dataInput.bitWidth})`,
+ })
+ }
+ })
+
+ if (invalids.length > 0) return { ok: false, invalids }
+ return { ok: true }
+}
+
+interface Invalids {
+ type: number
+ identifier: string
+ message: string
+ extraInfo?: any
+}
+
+/**
+ * Validates presence and bitwidths of test outputs in the circuit.
+ * Called by validate()
+ */
+function validateOutputs(data: TestData, scope) {
+ const invalids: Invalids[] = []
+
+ data.groups[0].outputs.forEach((dataOutput) => {
+ const matchOutput = scope.Output.find(
+ (simulatorOutput) => simulatorOutput.label === dataOutput.label
+ )
+
+ if (matchOutput === undefined) {
+ invalids.push({
+ type: VALIDATION_ERRORS.NOTPRESENT,
+ identifier: dataOutput.label,
+ message: 'Output is not present in the circuit',
+ })
+ } else if (matchOutput.bitWidth !== dataOutput.bitWidth) {
+ invalids.push({
+ type: VALIDATION_ERRORS.WRONGBITWIDTH,
+ identifier: dataOutput.label,
+ extraInfo: {
+ element: matchOutput,
+ expectedBitWidth: dataOutput.bitWidth,
+ },
+ message: `Output bitwidths don't match in circuit and test (${matchOutput.bitWidth} vs ${dataOutput.bitWidth})`,
+ })
+ }
+ })
+
+ if (invalids.length > 0) return { ok: false, invalids }
+ return { ok: true }
+}
+
+/**
+ * Validate if all inputs and output elements are present with correct bitwidths
+ */
+function validate(data: TestData, scope) {
+ let invalids = []
+
+ // Check for duplicate identifiers
+ if (!checkDistinctIdentifiersData(data)) {
+ invalids.push({
+ type: VALIDATION_ERRORS.DUPLICATE_ID_DATA,
+ identifier: '-',
+ message: 'Duplicate identifiers in test data',
+ })
+ }
+
+ if (!checkDistinctIdentifiersScope(scope)) {
+ invalids.push({
+ type: VALIDATION_ERRORS.DUPLICATE_ID_SCOPE,
+ identifier: '-',
+ message: 'Duplicate identifiers in circuit',
+ })
+ }
+
+ // Don't do further checks if duplicates
+ if (invalids.length > 0) return { ok: false, invalids }
+
+ // Validate inputs and outputs
+ const inputsValid = validateInputs(data, scope)
+ const outputsValid = validateOutputs(data, scope)
+
+ invalids = inputsValid.ok ? invalids : invalids.concat(inputsValid.invalids)
+ invalids = outputsValid.ok
+ ? invalids
+ : invalids.concat(outputsValid.invalids)
+
+ // Validate presence of reset if test is sequential
+ if (data.type === 'seq') {
+ const resetPresent = scope.Input.some(
+ (simulatorReset) =>
+ simulatorReset.label === 'RST' &&
+ simulatorReset.bitWidth === 1 &&
+ simulatorReset.objectType === 'Input'
+ )
+
+ if (!resetPresent) {
+ invalids.push({
+ type: VALIDATION_ERRORS.NO_RST,
+ identifier: 'RST',
+ message: 'Reset(RST) not present in circuit',
+ })
+ }
+ }
+
+ if (invalids.length > 0) return { ok: false, invalids }
+ return { ok: true }
+}
+
+/**
+ * Returns object of scope inputs and outputs keyed by their labels
+ */
+function bindIO(data: TestData, scope) {
+ const inputs: { [key: string]: any } = {}
+ const outputs: { [key: string]: any } = {}
+ let reset
+
+ data.groups[0].inputs.forEach((dataInput) => {
+ inputs[dataInput.label] = scope.Input.find(
+ (simulatorInput) => simulatorInput.label === dataInput.label
+ )
+ })
+
+ data.groups[0].outputs.forEach((dataOutput) => {
+ outputs[dataOutput.label] = scope.Output.find(
+ (simulatorOutput) => simulatorOutput.label === dataOutput.label
+ )
+ })
+
+ if (data.type === 'seq') {
+ reset = scope.Input.find(
+ (simulatorOutput) => simulatorOutput.label === 'RST'
+ )
+ }
+
+ return { inputs, outputs, reset }
+}
+
+/**
+ * Set and propogate the input values according to the testcase.
+ * Called by runSingle() and runAll()
+ */
+function setInputValues(inputs, group, caseIndex: number, scope) {
+ group.inputs.forEach((input) => {
+ inputs[input.label].state = parseInt(input.values[caseIndex], 2)
+ })
+
+ // Propagate inputs
+ play(scope)
+}
+
+/**
+ * Ticks clock recursively one full cycle (Only used in testbench context)
+ */
+function tickClock(scope: any) {
+ scope.clockTick()
+ play(scope)
+ scope.clockTick()
+ play(scope)
+}
+
+// Do we have any other function to do this?
+// Utility function. Converts decimal number to binary string
+function dec2bin(dec: number | undefined, bitWidth = undefined) {
+ if (dec === undefined) return 'X'
+ const bin = (dec >>> 0).toString(2)
+ if (!bitWidth) return bin
+
+ return '0'.repeat(bitWidth - bin.length) + bin
+}
+
+/**
+ * Gets Output values as a Map with keys as output name and value as output state
+ */
+function getOutputValues(data: TestData, outputs) {
+ const values = new Map()
+
+ data.groups[0].outputs.forEach((dataOutput) => {
+ // Using node value because output state only changes on rendering
+ const resultValue = outputs[dataOutput.label].nodeList[0].value
+ const resultBW = outputs[dataOutput.label].nodeList[0].bitWidth
+ values.set(dataOutput.label, dec2bin(resultValue, resultBW))
+ })
+
+ return values
+}
+
+/**
+ * Triggers reset (Only used in testbench context)
+ */
+function triggerReset(reset: any, scope: any) {
+ reset.state = 1
+ play(scope)
+ reset.state = 0
+ play(scope)
+}
+
+/**
+ * Interface function to run testbench. Called by testbench prompt on simulator or assignments
+ */
+export function runTestBench(
+ data: TestData,
+ scope = globalScope,
+ runContext = CONTEXT.CONTEXT_SIMULATOR
+) {
+ const testBenchStore = useTestBenchStore()
+ // const { testbenchData } = toRefs(testBenchStore)
+ const isValid = validate(data, scope)
+ if (!isValid.ok) {
+ showMessage(
+ 'Testbench: Some elements missing from circuit. Click Validate to know more'
+ )
+ }
+
+ if (runContext === CONTEXT.CONTEXT_SIMULATOR) {
+ const tempTestbenchData = new TestbenchData(data)
+ if (!tempTestbenchData.goToFirstValidGroup()) {
+ showMessage('Testbench: The test is empty')
+ testBenchStore.showTestbenchUI = false
+ return
+ }
+
+ testBenchStore.testbenchData = tempTestbenchData
+
+ return
+ }
+
+ if (runContext === CONTEXT.CONTEXT_ASSIGNMENTS) {
+ // Not implemented
+ }
+}
+
+interface Results {
+ detailed: TestData
+ summary: {
+ passed: number
+ total: number
+ }
+}
+
+/**
+ * Run all the tests automatically. Called by runTestBench()
+ */
+export function runAll(data: TestData, scope = globalScope) {
+ // Stop the clocks
+ // TestBench will now take over clock toggling
+ changeClockEnable(false)
+
+ const { inputs, outputs, reset } = bindIO(data, scope)
+ let totalCases = 0
+ let passedCases = 0
+
+ data.groups.forEach((group) => {
+ // for (const output of group.outputs) output.results = [];
+ group.outputs.forEach((output) => (output.results = []))
+ for (let case_i = 0; case_i < group.n; case_i++) {
+ totalCases++
+ // Set and propagate the inputs
+ setInputValues(inputs, group, case_i, scope)
+ // If sequential, trigger clock now
+ if (data.type === 'seq') tickClock(scope)
+ // Get output values
+ const caseResult = getOutputValues(data, outputs)
+ // Put the results in the data
+
+ let casePassed = true // Tracks if current case passed or failed
+
+ caseResult.forEach((_, outName) => {
+ // TODO: find() is not the best idea because of O(n)
+ const output = group.outputs.find(
+ (dataOutput) => dataOutput.label === outName
+ )
+ output?.results?.push(caseResult.get(outName))
+
+ if (output?.values[case_i] !== caseResult.get(outName))
+ casePassed = false
+ })
+
+ // If current case passed, then increment passedCases
+ if (casePassed) passedCases++
+ }
+
+ // If sequential, trigger reset at the end of group (set)
+ if (data.type === 'seq') triggerReset(reset, scope) // qs. why scope is not passed?
+ })
+
+ // Tests done, restart the clocks
+ changeClockEnable(true)
+
+ // Return results
+ const results: Results = {
+ detailed: data,
+ summary: { passed: passedCases, total: totalCases }
+ };
+ return results
+}
+
+/**
+ * Runs single combinational test
+ */
+function runSingleCombinational(testbenchData: TestBenchData, scope) {
+ const data = testbenchData.testData
+ const groupIndex = testbenchData.currentGroup
+ const caseIndex = testbenchData.currentCase
+
+ const { inputs, outputs } = bindIO(data, scope)
+ const group = data.groups[groupIndex]
+
+ // Stop the clocks
+ changeClockEnable(false)
+
+ // Set input values according to the test
+ setInputValues(inputs, group, caseIndex, scope)
+ // Check output values
+ const result = getOutputValues(data, outputs)
+ // Restart the clocks
+ changeClockEnable(true)
+ return result
+}
+
+/**
+ * Runs single sequential test and all tests above it in the group
+ * Used in MANUAL mode
+ */
+function runSingleSequential(testbenchData: TestBenchData, scope) {
+ const data = testbenchData.testData
+ const groupIndex = testbenchData.currentGroup
+ const caseIndex = testbenchData.currentCase
+
+ const { inputs, outputs, reset } = bindIO(data, scope)
+ const group = data.groups[groupIndex]
+
+ // Stop the clocks
+ changeClockEnable(false)
+
+ // Trigger reset
+ triggerReset(reset, scope)
+
+ // Run the test and tests above in the same group
+ for (let case_i = 0; case_i <= caseIndex; case_i++) {
+ setInputValues(inputs, group, case_i, scope)
+ tickClock(scope)
+ }
+
+ const result = getOutputValues(data, outputs)
+
+ // Restart the clocks
+ changeClockEnable(true)
+
+ return result
+}
+
+type openCreatorType = 'create' | 'edit' | 'result'
+
+export function openCreator(type: openCreatorType) {
+ const testBenchStore = useTestBenchStore();
+ if (type === 'create') {
+ testBenchStore.showResults = false;
+ testBenchStore.readOnly = false;
+ testBenchStore.showTestBenchCreator = true;
+ }
+
+ if (type === 'edit') {
+ testBenchStore.showResults = false;
+ testBenchStore.readOnly = false;
+ testBenchStore.showTestBenchCreator = true;
+ }
+
+ if (type === 'result') {
+ testBenchStore.showResults = true;
+ testBenchStore.readOnly = true;
+ testBenchStore.showTestBenchCreator = true;
+ }
+}
+
+/**
+* UI Function
+* Set the current test case result on the UI
+*/
+
+function setUIResult(testbenchData: TestBenchData, result) {
+ const testBenchStore = useTestBenchStore();
+ const data = testbenchData.testData;
+ const groupIndex = testbenchData.currentGroup;
+ const caseIndex = testbenchData.currentCase;
+
+ const inputCount = data.groups[0].inputs.length;
+ const newResultValues = [];
+
+ for (let i = 0; i < inputCount; i++) {
+ newResultValues.push({ value: ' - ', color: '#000' });
+ }
+
+ for (const output of result.keys()) {
+ const resultValue = result.get(output);
+ const outputData = data.groups[groupIndex].outputs.find(
+ (dataOutput) => dataOutput.label === output
+ );
+
+ const expectedValue = outputData ? outputData.values[caseIndex] : undefined;
+ const color = resultValue === expectedValue ? '#17FC12' : '#FF1616';
+ newResultValues.push({ value: escapeHtml(resultValue), color });
+ }
+
+ testBenchStore.resultValues = newResultValues;
+}
+
+/**
+ * Defines all the functions called as event listeners for buttons on the UI
+ */
+export const buttonListenerFunctions = {
+ previousCaseButton: () => {
+ const isValid = validate(
+ useTestBenchStore().testbenchData.testData,
+ globalScope
+ )
+ if (!isValid.ok) {
+ showMessage(
+ 'Testbench: Some elements missing from circuit. Click Validate to know more'
+ )
+ return
+ }
+ const testbenchData = useTestBenchStore().testbenchData;
+ if (testbenchData && testbenchData.casePrev) {
+ testbenchData.casePrev();
+ }
+ buttonListenerFunctions.computeCase()
+ },
+
+ nextCaseButton: () => {
+ const isValid = validate(
+ useTestBenchStore().testbenchData.testData,
+ globalScope
+ )
+ if (!isValid.ok) {
+ showMessage(
+ 'Testbench: Some elements missing from circuit. Click Validate to know more'
+ )
+ return
+ }
+ const testbenchData = useTestBenchStore().testbenchData;
+ if (testbenchData && testbenchData.caseNext) {
+ testbenchData.caseNext();
+ }
+ buttonListenerFunctions.computeCase()
+ },
+
+ previousGroupButton: () => {
+ const isValid = validate(
+ useTestBenchStore().testbenchData.testData,
+ globalScope
+ )
+ if (!isValid.ok) {
+ showMessage(
+ 'Testbench: Some elements missing from circuit. Click Validate to know more'
+ )
+ return
+ }
+ const testbenchData = useTestBenchStore().testbenchData;
+ if (testbenchData && testbenchData.groupPrev) {
+ testbenchData.groupPrev();
+ }
+ buttonListenerFunctions.computeCase()
+ },
+
+ nextGroupButton: () => {
+ const isValid = validate(
+ useTestBenchStore().testbenchData.testData,
+ globalScope
+ )
+ if (!isValid.ok) {
+ showMessage(
+ 'Testbench: Some elements missing from circuit. Click Validate to know more'
+ )
+ return
+ }
+ const testbenchData = useTestBenchStore().testbenchData;
+ if (testbenchData && testbenchData.groupNext) {
+ testbenchData.groupNext();
+ }
+ buttonListenerFunctions.computeCase()
+ },
+
+ changeTestButton: () => {
+ openCreator('create')
+ },
+
+ runAllButton: () => {
+ const isValid = validate(
+ useTestBenchStore().testbenchData.testData,
+ globalScope
+ )
+ if (!isValid.ok) {
+ showMessage(
+ 'Testbench: Some elements missing from circuit. Click Validate to know more'
+ )
+ return
+ }
+ const results = runAll(useTestBenchStore().testbenchData.testData, globalScope)
+ const { passed } = results.summary
+ const { total } = results.summary
+
+ useTestBenchStore().passed = passed
+ useTestBenchStore().total = total
+ useTestBenchStore().showPassed = true
+
+ setTimeout(() => {
+ useTestBenchStore().showPassed = false
+ }, 3000)
+ },
+
+ editTestButton: () => {
+ const editDataString = JSON.stringify(
+ useTestBenchStore().testbenchData.testData
+ )
+ openCreator('edit')
+ },
+
+ validateButton: () => {
+ const testBenchStore = useTestBenchStore()
+ const isValid = validate(
+ useTestBenchStore().testbenchData.testData,
+ globalScope
+ )
+ testBenchStore.validationErrors = isValid
+ testBenchStore.showTestBenchValidator = true
+ },
+
+ removeTestButton: async () => {
+ if (
+ await confirmOption(
+ 'Are you sure you want to remove the test from the circuit?'
+ )
+ ) {
+ useTestBenchStore().testbenchData = {
+ testData: {
+ type: "",
+ title: "",
+ groups: [
+ {
+ label: "Group 1",
+ inputs: [],
+ outputs: [],
+ n: 0
+ }
+ ],
+ },
+ currentGroup: 0,
+ currentCase: 0,
+ }
+ useTestBenchStore().showTestbenchUI = false
+ }
+ },
+
+ attachTestButton: () => {
+ openCreator('create')
+ },
+
+ rerunTestButton: () => {
+ buttonListenerFunctions.computeCase()
+ },
+
+ computeCase: () => {
+ const result = runSingleTest(useTestBenchStore().testbenchData, globalScope)
+ setUIResult(useTestBenchStore().testbenchData, result)
+ },
+}
+
+/**
+* Runs single test
+*/
+function runSingleTest(testbenchData: TestBenchData, scope) {
+ const data = testbenchData.testData
+
+ let result
+ if (data.type === 'comb') {
+ result = runSingleCombinational(testbenchData, scope)
+ } else if (data.type === 'seq') {
+ result = runSingleSequential(testbenchData, scope)
+ }
+
+ return result
+}
diff --git a/v1/src/simulator/src/testbench/ForceGate.js b/v1/src/simulator/src/testbench/ForceGate.js
index 5da82c6f..332af06c 100644
--- a/v1/src/simulator/src/testbench/ForceGate.js
+++ b/v1/src/simulator/src/testbench/ForceGate.js
@@ -1,6 +1,6 @@
import CircuitElement from '../circuitElement'
import Node, { findNode } from '../node'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { fillText4 } from '../canvasApi'
/**
* @class
diff --git a/v1/src/simulator/src/testbench/testbenchInput.js b/v1/src/simulator/src/testbench/testbenchInput.js
index bdf7452b..f877aca8 100644
--- a/v1/src/simulator/src/testbench/testbenchInput.js
+++ b/v1/src/simulator/src/testbench/testbenchInput.js
@@ -1,5 +1,5 @@
import CircuitElement from '../circuitElement'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, lineTo, moveTo, fillText } from '../canvasApi'
import Node, { findNode } from '../node'
import plotArea from '../plotArea'
@@ -63,12 +63,11 @@ export default class TB_Input extends CircuitElement {
setup() {
this.iteration = 0
this.running = false
- this.nodeList.clean(this.clockInp)
+ this.nodeList = this.nodeList.filter(x=> x !== this.clockInp);
this.deleteNodes()
this.nodeList = []
this.nodeList.push(this.clockInp)
this.testData = this.testData || { inputs: [], outputs: [], n: 0 }
- // this.clockInp = new Node(0,20, 0,this,1);
this.setDimensions()
diff --git a/v1/src/simulator/src/testbench/testbenchOutput.js b/v1/src/simulator/src/testbench/testbenchOutput.js
index 865ec258..49117626 100644
--- a/v1/src/simulator/src/testbench/testbenchOutput.js
+++ b/v1/src/simulator/src/testbench/testbenchOutput.js
@@ -1,5 +1,5 @@
import CircuitElement from '../circuitElement'
-import simulationArea from '../simulationArea'
+import { simulationArea } from '../simulationArea'
import { correctWidth, fillText } from '../canvasApi'
import Node, { findNode } from '../node'
@@ -29,15 +29,8 @@ function dec2bin(dec, bitWidth = undefined) {
export default class TB_Output extends CircuitElement {
constructor(x, y, scope = globalScope, dir = 'RIGHT', identifier) {
super(x, y, scope, dir, 1)
- // this.setDimensions(60,20);
this.objectType = 'TB_Output'
this.scope.TB_Output.push(this)
-
- // this.xSize=10;
-
- // this.plotValues = [];
- // this.inp1 = new Node(0, 0, 0, this);
- // this.inp1 = new Node(100, 100, 0, this);
this.setIdentifier(identifier || 'Test1')
this.inputs = []
this.testBenchInput = undefined
@@ -45,10 +38,6 @@ export default class TB_Output extends CircuitElement {
this.setup()
}
- // TB_Output.prototype.dblclick=function(){
- // this.testData=JSON.parse(prompt("Enter TestBench Json"));
- // this.setup();
- // }
setDimensions() {
this.leftDimensionX = 0
this.rightDimensionX = 160
@@ -61,9 +50,6 @@ export default class TB_Output extends CircuitElement {
}
setup() {
- // this.iteration = 0;
- // this.running = false;
- // this.nodeList.clean(this.clockInp);
this.deleteNodes() // deletes all nodes whenever setup is called.
this.nodeList = []
@@ -161,22 +147,6 @@ export default class TB_Output extends CircuitElement {
yRotate = 20
}
- // rect2(ctx, -120+xRotate+this.xSize, -20+yRotate, 120-this.xSize, 40, xx, yy, "RIGHT");
- // if ((this.hover && !simulationArea.shiftDown) || simulationArea.lastSelected == this || simulationArea.multipleObjectSelections.contains(this))
- // ctx.fillStyle = "rgba(255, 255, 32,0.8)";
- // ctx.fill();
- // ctx.stroke();
- //
- // ctx.font = "14px Raleway";
- // this.xOff = ctx.measureText(this.identifier).width;
- // ctx.beginPath();
- // rect2(ctx, -105+xRotate+this.xSize, -11+yRotate,this.xOff + 10, 23, xx, yy, "RIGHT");
- // ctx.fillStyle = "#eee"
- // ctx.strokeStyle = "#ccc";
- // ctx.fill();
- // ctx.stroke();
- //
-
ctx.beginPath()
ctx.textAlign = 'center'
ctx.fillStyle = 'black'
@@ -187,9 +157,6 @@ export default class TB_Output extends CircuitElement {
yy + 14,
10
)
-
- // fillText(ctx, ["Not Running","Running"][+this.running], xx + this.rightDimensionX/ 2 , yy + 14 + 10 + 20*this.testData.inputs.length, 10);
- // fillText(ctx, "Case: "+(this.iteration), xx + this.rightDimensionX/ 2 , yy + 14 + 20 + 20*this.testData.inputs.length, 10);
fillText(
ctx,
['Unpaired', 'Paired'][+(this.testBenchInput != undefined)],
@@ -209,7 +176,6 @@ export default class TB_Output extends CircuitElement {
i < this.testBenchInput.testData.outputs.length;
i++
) {
- // ctx.beginPath();
fillText(
ctx,
this.testBenchInput.testData.outputs[i].label,
diff --git a/v1/src/simulator/src/themer/customThemeAbstraction.js b/v1/src/simulator/src/themer/customThemeAbstraction.ts
similarity index 74%
rename from v1/src/simulator/src/themer/customThemeAbstraction.js
rename to v1/src/simulator/src/themer/customThemeAbstraction.ts
index 399134ea..341226d0 100644
--- a/v1/src/simulator/src/themer/customThemeAbstraction.js
+++ b/v1/src/simulator/src/themer/customThemeAbstraction.ts
@@ -3,7 +3,24 @@
* @param {*} themeOptions
* @returns an Object
*/
-export const CreateAbstraction = (themeOptions) => {
+
+interface ThemeProperties {
+ color: string;
+ description: string;
+ ref: string[];
+}
+
+export interface Themes {
+ Navbar?: ThemeProperties;
+ Primary?: ThemeProperties;
+ Secondary?: ThemeProperties;
+ Canvas?: ThemeProperties;
+ Stroke?: ThemeProperties;
+ Text?: ThemeProperties;
+ Borders?: ThemeProperties;
+}
+
+export const CreateAbstraction = (themeOptions: { [key: string]: string }): Themes => {
return {
Navbar: {
color: themeOptions['--bg-navbar'],
diff --git a/v1/src/simulator/src/themer/customThemer.js b/v1/src/simulator/src/themer/customThemer.js
deleted file mode 100644
index 51a7e0b2..00000000
--- a/v1/src/simulator/src/themer/customThemer.js
+++ /dev/null
@@ -1,154 +0,0 @@
-// /* eslint-disable import/prefer-default-export */
-// /* eslint-disable import/no-cycle */
-// import { dots } from '../canvasApi'
-// import themeOptions from './themes'
-// import { updateThemeForStyle } from './themer'
-// import { CreateAbstraction } from './customThemeAbstraction'
-
-// /**
-// *
-// */
-// var customTheme = CreateAbstraction(themeOptions['Custom Theme'])
-
-// const updateBG = () => dots(true, false, true)
-
-// /**
-// * Generates Custom theme card HTML
-// * return Html Element Theme card html (properties_container)
-// */
-// // const getCustomThemeCard = () => {
-// // var propertiesContainer = document.createElement('form')
-// // const keys = Object.keys(customTheme)
-// // keys.forEach((key) => {
-// // const property = document.createElement('div')
-// // const newPropertyLabel = document.createElement('label')
-// // newPropertyLabel.textContent = `${key} (${customTheme[key].description})`
-// // newPropertyLabel.setAttribute('for', key)
-// // const newPropertyInput = document.createElement('input')
-// // newPropertyInput.setAttribute('type', 'color')
-// // newPropertyInput.setAttribute('name', key)
-// // newPropertyInput.setAttribute('value', customTheme[key].color)
-// // newPropertyInput.classList.add('customColorInput')
-// // property.append(newPropertyLabel)
-// // property.append(newPropertyInput)
-// // propertiesContainer.append(property)
-// // })
-// // const downloadAnchor = document.createElement('a')
-// // downloadAnchor.setAttribute('id', 'downloadThemeFile')
-// // downloadAnchor.setAttribute('style', 'display:none')
-// // propertiesContainer.appendChild(downloadAnchor)
-// // return propertiesContainer
-// // }
-
-// /**
-// * Create Custom Color Themes Dialog
-// */
-// // export const CustomColorThemes = () => {
-// // $('#CustomColorThemesDialog').empty()
-// // $('#CustomColorThemesDialog').append(getCustomThemeCard())
-// // $('#CustomColorThemesDialog').dialog({
-// // resizable: false,
-// // close() {
-// // themeOptions['Custom Theme'] =
-// // JSON.parse(localStorage.getItem('Custom Theme')) ||
-// // themeOptions['Default Theme'] // hack for closing dialog box without saving
-// // // Rollback to previous theme
-// // updateThemeForStyle(localStorage.getItem('theme'))
-// // updateBG()
-// // },
-// // buttons: [
-// // {
-// // text: 'Apply Theme',
-// // click() {
-// // // update theme to Custom Theme
-// // localStorage.setItem('theme', 'Custom Theme')
-// // // add Custom theme to custom theme object
-// // localStorage.setItem(
-// // 'Custom Theme',
-// // JSON.stringify(themeOptions['Custom Theme'])
-// // )
-// // $('.set').removeClass('set')
-// // $('.selected').addClass('set')
-// // $(this).dialog('close')
-// // },
-// // },
-// // {
-// // text: 'Import Theme',
-// // click() {
-// // $('#importThemeFile').click()
-// // },
-// // },
-// // {
-// // text: 'Export Theme',
-// // click() {
-// // const dlAnchorElem =
-// // document.getElementById('downloadThemeFile')
-// // dlAnchorElem.setAttribute(
-// // 'href',
-// // `data:text/json;charset=utf-8,${encodeURIComponent(
-// // JSON.stringify(themeOptions['Custom Theme'])
-// // )}`
-// // )
-// // dlAnchorElem.setAttribute('download', 'CV_CustomTheme.json')
-// // dlAnchorElem.click()
-// // },
-// // },
-// // ],
-// // })
-
-// // $('#CustomColorThemesDialog').focus()
-
-// // /**
-// // * To preview the changes
-// // */
-// // // function setColorEvent() {
-// // // $('.customColorInput').on('input', (e) => {
-// // // customTheme[e.target.name].color = e.target.value
-// // // customTheme[e.target.name].ref.forEach((property) => {
-// // // themeOptions['Custom Theme'][property] = e.target.value
-// // // })
-// // // updateThemeForStyle('Custom Theme')
-// // // updateBG()
-// // // })
-// // // }
-// // // setColorEvent()
-
-// // // hack for updating current theme to the saved custom theme
-// // setTimeout(() => {
-// // updateThemeForStyle('Custom Theme')
-// // updateBG()
-// // }, 50)
-
-// // /**
-// // * Read JSON file and
-// // * set Custom theme to the Content of the JSON file
-// // * */
-// // // function receivedText(e) {
-// // // const lines = JSON.parse(e.target.result)
-// // // customTheme = CreateAbstraction(lines)
-// // // themeOptions['Custom Theme'] = lines
-// // // // preview theme
-// // // updateThemeForStyle('Custom Theme')
-// // // updateBG()
-// // // // update colors in dialog box
-// // // $('#CustomColorThemesDialog').empty()
-// // // $('#CustomColorThemesDialog').append(getCustomThemeCard())
-// // // setColorEvent()
-// // // }
-
-// // /**
-// // * Add listener for file input
-// // * Read imported JSON file
-// // */
-// // // $('#importThemeFile').on('change', (event) => {
-// // // var File = event.target.files[0]
-// // // if (File !== null && File.name.split('.')[1] === 'json') {
-// // // var fr = new FileReader()
-// // // fr.onload = receivedText
-// // // fr.readAsText(File)
-// // // $('#importThemeFile').val('')
-// // // } else {
-// // // alert('File Not Supported !')
-// // // }
-// // // })
-// // }
diff --git a/v1/src/simulator/src/themer/customThemer.vue b/v1/src/simulator/src/themer/customThemer.vue
new file mode 100644
index 00000000..17f64f6e
--- /dev/null
+++ b/v1/src/simulator/src/themer/customThemer.vue
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v1/src/simulator/src/themer/themeCardSvg.js b/v1/src/simulator/src/themer/themeCardSvg.ts
similarity index 98%
rename from v1/src/simulator/src/themer/themeCardSvg.js
rename to v1/src/simulator/src/themer/themeCardSvg.ts
index 5e1776cb..de3c9f78 100644
--- a/v1/src/simulator/src/themer/themeCardSvg.js
+++ b/v1/src/simulator/src/themer/themeCardSvg.ts
@@ -1,4 +1,4 @@
-export default ``;
+
+export default svgString;
\ No newline at end of file
diff --git a/v1/src/simulator/src/themer/themer.js b/v1/src/simulator/src/themer/themer.js
deleted file mode 100644
index 2c61865e..00000000
--- a/v1/src/simulator/src/themer/themer.js
+++ /dev/null
@@ -1,223 +0,0 @@
-import { dots } from '../canvasApi'
-import themeOptions from './themes'
-import themeCardSvg from './themeCardSvg'
-import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
-
-/**
- * Extracts canvas theme colors from CSS-Variables and returns a JSON Object
- * @returns {object}
- */
-const getCanvasColors = () => {
- let colors = {}
- colors['hover_select'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--hover-and-sel')
- colors['fill'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--fill')
- colors['mini_fill'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--mini-map')
- colors['mini_stroke'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--mini-map-stroke')
- colors['stroke'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--stroke')
- colors['stroke_alt'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--secondary-stroke')
- colors['input_text'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--input-text')
- colors['color_wire_draw'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--wire-draw')
- colors['color_wire_con'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--wire-cnt')
- colors['color_wire_pow'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--wire-pow')
- colors['color_wire_sel'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--wire-sel')
- colors['color_wire_lose'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--wire-lose')
- colors['color_wire'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--wire-norm')
- colors['text'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--text')
- colors['node'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--node')
- colors['node_norm'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--node-norm')
- colors['splitter'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--splitter')
- colors['out_rect'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--output-rect')
- colors['canvas_stroke'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--canvas-stroke')
- colors['canvas_fill'] = getComputedStyle(
- document.documentElement
- ).getPropertyValue('--canvas-fill')
- return colors
-}
-
-/**
- * Common canvas theme color object, used for rendering canvas elements
- */
-export let colors = getCanvasColors()
-
-/**
- * Updates theme
- * 1) Sets CSS Variables for UI elements
- * 2) Sets color variable for Canvas elements
- */
-export function updateThemeForStyle(themeName) {
- const selectedTheme = themeOptions[themeName]
- if (selectedTheme === undefined) return
- const html = document.getElementsByTagName('html')[0]
- Object.keys(selectedTheme).forEach((property, i) => {
- html.style.setProperty(property, selectedTheme[property])
- })
- colors = getCanvasColors()
-}
-
-/**
- * Theme Preview Card SVG
- * Sets the SVG colors according to theme
- * @param {string} themeName Name of theme
- * @returns {SVG}
- */
-export const getThemeCardSvg = (themeName) => {
- const colors = themeOptions[themeName]
- let svgIcon = $(themeCardSvg)
-
- // Dynamically set the colors according to the theme
- $('.svgText', svgIcon).attr('fill', colors['--text-panel'])
-
- $('.svgNav', svgIcon).attr('fill', colors['--bg-tab'])
- $('.svgNav', svgIcon).attr('stroke', colors['--br-primary'])
-
- $('.svgGridBG', svgIcon).attr('fill', colors['--canvas-fill'])
- $('.svgGrid', svgIcon).attr('fill', colors['--canvas-stroke'])
-
- $('.svgPanel', svgIcon).attr('fill', colors['--primary'])
- $('.svgPanel', svgIcon).attr('stroke', colors['--br-primary'])
-
- $('.svgChev', svgIcon).attr('stroke', colors['--br-secondary'])
-
- $('.svgHeader', svgIcon).attr('fill', colors['--primary'])
- let temp = svgIcon.prop('outerHTML')
- return svgIcon.prop('outerHTML')
-}
-
-/**
- * Generates theme card HTML
- * @param {string} themeName Name of theme
- * @param {boolean} selected Flag variable for currently selected theme
- * @return {string} Theme card html
- */
-export const getThemeCard = (themeName, selected) => {
- if (themeName === 'Custom Theme') return ''
- let themeId = themeName.replace(' ', '')
- let selectedClass = selected ? 'selected set' : ''
- // themeSel is the hit area
- return `
-
-
-
${getThemeCardSvg(themeName)}
-
-
-
-
-
- `
-}
-
-/**
- * Create Color Themes Dialog
- */
-export const colorThemes = () => {
- const simulatorStore = SimulatorStore()
- simulatorStore.dialogBox.theme_dialog = true
-
- // const selectedTheme = localStorage.getItem('theme')
- // $('#colorThemesDialog').empty()
- // const themes = Object.keys(themeOptions)
- // themes.forEach((theme) => {
- // if (theme === selectedTheme) {
- // $('#colorThemesDialog').append(getThemeCard(theme, true))
- // } else {
- // $('#colorThemesDialog').append(getThemeCard(theme, false))
- // }
- // })
-
- // $('.selected label').trigger('click')
- // $('#colorThemesDialog').dialog({
- // resizable: false,
- // close() {
- // // Rollback to previous theme
- // updateThemeForStyle(localStorage.getItem('theme'))
- // updateBG()
- // },
- // buttons: [
- // {
- // text: 'Apply Theme',
- // click() {
- // // check if any theme is selected or not
- // if ($('.selected label').text()) {
- // localStorage.removeItem('Custom Theme')
- // localStorage.setItem(
- // 'theme',
- // $('.selected label').text()
- // )
- // }
- // $('.set').removeClass('set')
- // $('.selected').addClass('set')
- // $(this).dialog('close')
- // },
- // },
- // {
- // text: 'Custom Theme',
- // click() {
- // CustomColorThemes()
- // $(this).dialog('close')
- // },
- // },
- // ],
- // })
-
- $('#colorThemesDialog').focus()
- $('.ui-dialog[aria-describedby="colorThemesDialog"]').on('click', () =>
- $('#colorThemesDialog').focus()
- ) //hack for losing focus
-
- $('.themeSel').on('mousedown', (e) => {
- e.preventDefault()
- $('.selected').removeClass('selected')
- let themeCard = $(e.target.parentElement)
- themeCard.addClass('selected')
- // Extract radio button
- var radioButton = themeCard.find('input[type=radio]')
- radioButton.trigger('click') // Mark as selected
- updateThemeForStyle(themeCard.find('label').text()) // Extract theme name and set
- updateBG()
- })
-}
-
-export const updateBG = () => dots(true, false, true)
-;(() => {
- if (!localStorage.getItem('theme'))
- localStorage.setItem('theme', 'Default Theme')
- updateThemeForStyle(localStorage.getItem('theme'))
-})()
diff --git a/v1/src/simulator/src/themer/themer.ts b/v1/src/simulator/src/themer/themer.ts
new file mode 100644
index 00000000..d8597939
--- /dev/null
+++ b/v1/src/simulator/src/themer/themer.ts
@@ -0,0 +1,218 @@
+import { dots } from '../canvasApi';
+import importedThemeOptions from './themes';
+import { ThemeOptions } from './themer.types';
+import themeCardSvg from './themeCardSvg';
+import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore';
+
+const themeOptions: ThemeOptions = importedThemeOptions;
+
+/**
+ * Helper function to set CSS variable values into a colors object.
+ */
+const setColor = (colors: Record, key: string, cssVar: string): void => {
+ colors[key] = getComputedStyle(document.documentElement).getPropertyValue(cssVar);
+};
+
+/**
+ * Extracts canvas theme colors from CSS variables and returns a JSON object.
+ */
+const getCanvasColors = (): Record => {
+ const colors: Record = {};
+ setColor(colors, 'hover_select', '--hover-and-sel');
+ setColor(colors, 'fill', '--fill');
+ setColor(colors, 'mini_fill', '--mini-map');
+ setColor(colors, 'mini_stroke', '--mini-map-stroke');
+ setColor(colors, 'stroke', '--stroke');
+ setColor(colors, 'stroke_alt', '--secondary-stroke');
+ setColor(colors, 'input_text', '--input-text');
+ setColor(colors, 'color_wire_draw', '--wire-draw');
+ setColor(colors, 'color_wire_con', '--wire-cnt');
+ setColor(colors, 'color_wire_pow', '--wire-pow');
+ setColor(colors, 'color_wire_sel', '--wire-sel');
+ setColor(colors, 'color_wire_lose', '--wire-lose');
+ setColor(colors, 'color_wire', '--wire-norm');
+ setColor(colors, 'text', '--text');
+ setColor(colors, 'node', '--node');
+ setColor(colors, 'node_norm', '--node-norm');
+ setColor(colors, 'splitter', '--splitter');
+ setColor(colors, 'out_rect', '--output-rect');
+ setColor(colors, 'canvas_stroke', '--canvas-stroke');
+ setColor(colors, 'canvas_fill', '--canvas-fill');
+ return colors;
+};
+
+/**
+ * Common canvas theme color object, used for rendering canvas elements.
+ */
+export let colors: Record = getCanvasColors();
+
+/**
+ * Updates theme by setting CSS variables and updating the colors object.
+ */
+export function updateThemeForStyle(themeName: string): void {
+ const selectedTheme = themeOptions[themeName];
+ if (selectedTheme === undefined) return;
+
+ const html = document.documentElement;
+ Object.keys(selectedTheme).forEach((property) => {
+ html.style.setProperty(property, selectedTheme[property]);
+ });
+
+ colors = getCanvasColors();
+}
+
+/**
+ * Helper function to set attributes for SVG elements.
+ */
+const setAttributes = (element: Element, attributes: Record): void => {
+ Object.entries(attributes).forEach(([attr, value]) => {
+ element.setAttribute(attr, value);
+ });
+};
+
+/**
+ * Generates a theme preview card SVG with colors based on the selected theme.
+ */
+export const getThemeCardSvg = (themeName: string): string => {
+ if (!themeOptions[themeName]) {
+ console.error(`Theme "${themeName}" not found`);
+ return '';
+ }
+
+ const colors = themeOptions[themeName];
+ const parser = new DOMParser();
+ const svgDoc = parser.parseFromString(themeCardSvg, 'image/svg+xml');
+
+ // Check for parsing errors
+ const parserError = svgDoc.querySelector('parsererror');
+ if (parserError) {
+ console.error('Failed to parse SVG:', parserError);
+ return '';
+ }
+
+ const svgElement = svgDoc.documentElement;
+
+ const applyStyles = (selector: string, attributes: Record): void => {
+ svgElement.querySelectorAll(selector).forEach((el) => setAttributes(el, attributes));
+ };
+
+ applyStyles('.svgText', { fill: colors['--text-panel'] || '#000000' });
+ applyStyles('.svgNav', { fill: colors['--bg-tab'], stroke: colors['--br-primary'] });
+ applyStyles('.svgGridBG', { fill: colors['--canvas-fill'] });
+ applyStyles('.svgGrid', { fill: colors['--canvas-stroke'] });
+ applyStyles('.svgPanel', { fill: colors['--primary'], stroke: colors['--br-primary'] });
+ applyStyles('.svgChev', { stroke: colors['--br-secondary'] });
+ applyStyles('.svgHeader', { fill: colors['--primary'] });
+
+ return svgElement.outerHTML;
+};
+
+/**
+ * Generates theme card HTML.
+ */
+export const getThemeCard = (themeName: string, selected: boolean): string => {
+ if (themeName === 'Custom Theme') return '';
+
+ const themeId = themeName.replace(' ', '');
+ const selectedClass = selected ? 'selected set' : '';
+
+ return `
+
+
+
${getThemeCardSvg(themeName)}
+
+
+
+
+
+ `;
+};
+
+/**
+ * Handles theme selection logic.
+ */
+const handleThemeSelection = (e: MouseEvent): void => {
+ e.preventDefault();
+
+ // Remove 'selected' class from all theme cards
+ document.querySelectorAll('.selected').forEach((el) => el.classList.remove('selected'));
+
+ const themeCard = (e.target as HTMLElement).parentElement;
+ if (!themeCard) return;
+
+ // Add 'selected' class to the clicked theme card
+ themeCard.classList.add('selected');
+
+ // Find the radio button and label within the theme card
+ const radioButton = themeCard.querySelector('input[type=radio]') as HTMLInputElement;
+ const label = themeCard.querySelector('label');
+
+ if (radioButton) {
+ radioButton.click(); // Mark the radio button as selected
+ }
+
+ if (label) {
+ updateThemeForStyle(label.textContent || ''); // Update the theme based on the label text
+ }
+
+ updateBG(); // Update the background
+};
+
+/**
+ * Sets up event listeners for theme selection.
+ */
+const setupThemeSelectionHandlers = (cleanupListeners: (() => void)[]): void => {
+ document.querySelectorAll('.themeSel').forEach((element) => {
+ const mousedownHandler = (e: MouseEvent) => handleThemeSelection(e);
+
+ element.addEventListener('mousedown', mousedownHandler as EventListener);
+ cleanupListeners.push(() => element.removeEventListener('mousedown', mousedownHandler as EventListener));
+ });
+};
+
+/**
+ * Initializes the color themes dialog.
+ */
+export const colorThemes = (): void => {
+ const simulatorStore = SimulatorStore();
+ const cleanupListeners: (() => void)[] = [];
+
+ simulatorStore.dialogBox.theme_dialog = true;
+
+ const dialog = document.querySelector('.ui-dialog[aria-describedby="colorThemesDialog"]');
+ if (dialog) {
+ const dialogClickHandler = () => {
+ const colorThemesDialog = document.getElementById('colorThemesDialog');
+ if (colorThemesDialog) colorThemesDialog.focus();
+ };
+
+ dialog.addEventListener('click', dialogClickHandler);
+ cleanupListeners.push(() => dialog.removeEventListener('click', dialogClickHandler));
+ }
+
+ setupThemeSelectionHandlers(cleanupListeners);
+
+ // Add cleanup method to store
+ (simulatorStore as any).cleanupThemeDialog = () => {
+ cleanupListeners.forEach(cleanup => cleanup());
+ };
+};
+
+/**
+ * Updates the background of the canvas.
+ */
+export const updateBG = (): void => dots(true, false, true);
+
+/**
+ * Initializes the theme on load.
+ */
+const initializeTheme = (): void => {
+ const theme = localStorage.getItem('theme') || 'Default Theme';
+ if (!localStorage.getItem('theme')) {
+ localStorage.setItem('theme', theme);
+ }
+ updateThemeForStyle(theme);
+};
+
+// Initialize theme on load
+initializeTheme();
\ No newline at end of file
diff --git a/v1/src/simulator/src/themer/themer.types.ts b/v1/src/simulator/src/themer/themer.types.ts
new file mode 100644
index 00000000..639e5052
--- /dev/null
+++ b/v1/src/simulator/src/themer/themer.types.ts
@@ -0,0 +1,13 @@
+export interface ThemeOptions {
+ [key: string]: {
+ [property: string]: string;
+ };
+}
+
+interface Theme {
+ [key: string]: string;
+}
+
+export interface Themes {
+ [themeName: string]: Theme;
+}
\ No newline at end of file
diff --git a/v0/src/simulator/src/themer/themes.js b/v1/src/simulator/src/themer/themes.ts
similarity index 99%
rename from v0/src/simulator/src/themer/themes.js
rename to v1/src/simulator/src/themer/themes.ts
index d4f8caa1..b0dbe421 100644
--- a/v0/src/simulator/src/themer/themes.js
+++ b/v1/src/simulator/src/themer/themes.ts
@@ -1,4 +1,6 @@
-export default {
+import { Themes } from './themer.types'
+
+const themes: Themes = {
'Default Theme': {
'--text-navbar--alt': '#000',
'--br-secondary': '#7d7d7d',
@@ -326,7 +328,7 @@ export default {
'--disable': '#956c6a',
'--table-head-dark': '#2e2b21',
},
- 'Custom Theme': JSON.parse(localStorage.getItem('Custom Theme')) || {
+ 'Custom Theme': JSON.parse(localStorage.getItem('Custom Theme') || '{}') || {
'--text-navbar--alt': '#000',
'--br-secondary': '#7d7d7d',
'--br-circuit-cur': '#ffffff',
@@ -380,3 +382,5 @@ export default {
'--output-rect': '#0000ff',
},
}
+
+export default themes;
diff --git a/v1/src/simulator/src/tutorials.js b/v1/src/simulator/src/tutorials.js
index a1f10d67..dde6f52c 100644
--- a/v1/src/simulator/src/tutorials.js
+++ b/v1/src/simulator/src/tutorials.js
@@ -33,16 +33,6 @@ export const tour = [
// offset: 750,
},
},
- // {
- // element: '.forum-tab',
- // popover: {
- // className: "",
- // title: 'Forum Tab',
- // description: "The forums can help you report issues & bugs, feature requests, and discussing about circuits with the community!",
- // position: 'right',
- // // offset: -25,
- // },
- // },
{
element: '#tabsBar',
popover: {
@@ -63,16 +53,6 @@ export const tour = [
offset: 0,
},
},
-
- // {
- // element: '#delCirGuide',
- // popover: {
- // title: 'Delete sub-circuit button',
- // description: "You can make delete sub-circuits by pressing the cross *Note that main circuit cannot be deleted.",
- // position: 'right',
- // // offset: 250,
- // },
- // },
{
element: '.report-sidebar a',
popover: {
@@ -95,6 +75,15 @@ export const tour = [
offset: 0,
},
},
+ {
+ element: '.testbench-manual-panel',
+ popover: {
+ title: 'Test Bench Panel',
+ description: 'This panel helps you test your circuit correctness by observing how your circuit responds under different test cases, ensuring a thorough and effective validation process.',
+ position: 'right',
+ offset: 0,
+ },
+ },
]
// Not used currently
diff --git a/v1/src/simulator/src/types/app.types.ts b/v1/src/simulator/src/types/app.types.ts
new file mode 100644
index 00000000..e126fcd6
--- /dev/null
+++ b/v1/src/simulator/src/types/app.types.ts
@@ -0,0 +1,33 @@
+interface Device {
+ type: string;
+ net?: string;
+ order?: number;
+ bits: number;
+ label?: string;
+ abits?: number;
+ words?: number;
+ offset?: number;
+ rdports?: Array<{ clock_polarity?: boolean }>;
+ wrports?: Array<{ clock_polarity?: boolean }>;
+ memdata?: Array;
+}
+
+interface Connector {
+ to: {
+ id: string;
+ port: string;
+ };
+ from: {
+ id: string;
+ port: string;
+ };
+ name: string;
+}
+
+export interface JsConfig {
+ devices: {
+ [key: string]: Device;
+ };
+ connectors: Connector[];
+ subcircuits: Record;
+}
\ No newline at end of file
diff --git a/v1/src/simulator/src/utils.js b/v1/src/simulator/src/utils.ts
similarity index 50%
rename from v1/src/simulator/src/utils.js
rename to v1/src/simulator/src/utils.ts
index 9d6a32b9..a85b186e 100644
--- a/v1/src/simulator/src/utils.js
+++ b/v1/src/simulator/src/utils.ts
@@ -1,4 +1,4 @@
-import simulationArea from './simulationArea'
+import { simulationArea } from './simulationArea'
import {
scheduleUpdate,
play,
@@ -9,6 +9,10 @@ import {
import { layoutModeGet } from './layoutMode'
import plotArea from './plotArea'
import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
+import { useActions } from '#/store/SimulatorStore/actions'
+import { writeTextFile } from '@tauri-apps/plugin-fs';
+import { join, downloadDir } from '@tauri-apps/api/path';
+import { isTauri } from '@tauri-apps/api/core'
window.globalScope = undefined
window.lightMode = false // To be deprecated
@@ -16,14 +20,14 @@ window.projectId = undefined
window.id = undefined
window.loading = false // Flag - all assets are loaded
-var prevErrorMessage // Global variable for error messages
-var prevShowMessage // Global variable for error messages
+let prevErrorMessage: string | undefined // Global variable for error messages
+let prevShowMessage: string | undefined // Global variable for error messages
export function generateId() {
- var id = ''
- var possible =
+ let id = ''
+ const possible =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
- for (var i = 0; i < 20; i++) {
+ for (let i = 0; i < 20; i++) {
id += possible.charAt(Math.floor(Math.random() * possible.length))
}
@@ -48,39 +52,25 @@ export function clockTick() {
/**
* Helper function to show error
- * @param {string} error -The error to be shown
- * @category utils
*/
-export function showError(error) {
+export function showError(error: string) {
errorDetectedSet(true)
// if error ha been shown return
if (error === prevErrorMessage) return
prevErrorMessage = error
- var id = Math.floor(Math.random() * 10000)
- $('#MessageDiv').append(
- ` ${error}
`
- )
- setTimeout(() => {
- prevErrorMessage = undefined
- $(`#${id}`).fadeOut()
- }, 1500)
+
+ useActions().showMessage(error, 'error')
}
// Helper function to show message
-export function showMessage(mes) {
+export function showMessage(mes: string) {
if (mes === prevShowMessage) return
prevShowMessage = mes
- var id = Math.floor(Math.random() * 10000)
- $('#MessageDiv').append(
- ` ${mes}
`
- )
- setTimeout(() => {
- prevShowMessage = undefined
- $(`#${id}`).fadeOut()
- }, 2500)
+
+ useActions().showMessage(mes, 'success')
}
-export function distance(x1, y1, x2, y2) {
+export function distance(x1: number, y1: number, x2: number, y2: number) {
return Math.sqrt((x2 - x1) ** 2) + (y2 - y1) ** 2
}
@@ -89,22 +79,22 @@ export function distance(x1, y1, x2, y2) {
* @param {Array} a - any array
* @category utils
*/
-export function uniq(a) {
- var seen = {}
+export function uniq(a: any[]) {
+ const seen: { [key: string]: boolean } = {};
const tmp = a.filter((item) =>
seen.hasOwnProperty(item) ? false : (seen[item] = true)
- )
- return tmp
+ );
+ return tmp;
}
// Generates final verilog code for each element
// Gate = &/|/^
// Invert is true for xNor, Nor, Nand
export function gateGenerateVerilog(gate, invert = false) {
- var inputs = []
- var outputs = []
+ let inputs = []
+ let outputs = []
- for (var i = 0; i < this.nodeList.length; i++) {
+ for (let i = 0; i < this.nodeList.length; i++) {
if (this.nodeList[i].type == NODE_INPUT) {
inputs.push(this.nodeList[i])
} else {
@@ -114,13 +104,13 @@ export function gateGenerateVerilog(gate, invert = false) {
}
}
- var res = 'assign '
+ let res = 'assign '
if (outputs.length == 1) res += outputs[0].verilogLabel
else res += `{${outputs.map((x) => x.verilogLabel).join(', ')}}`
res += ' = '
- var inputParams = inputs.map((x) => x.verilogLabel).join(` ${gate} `)
+ const inputParams = inputs.map((x) => x.verilogLabel).join(` ${gate} `)
if (invert) {
res += `~(${inputParams});`
} else {
@@ -130,8 +120,17 @@ export function gateGenerateVerilog(gate, invert = false) {
}
// Helper function to download text
-export function download(filename, text) {
- var pom = document.createElement('a')
+export function downloadFile(filename: string, text: string | number | boolean | JSON) {
+ if (isTauri()) {
+ return downloadFileDesktop(filename, text);
+ } else {
+ return downloadFileWeb(filename, text);
+ }
+}
+
+// For Web Application
+export function downloadFileWeb(filename: string, text: string | number | boolean) {
+ const pom = document.createElement('a')
pom.setAttribute(
'href',
'data:text/plain;charset=utf-8,' + encodeURIComponent(text)
@@ -139,7 +138,7 @@ export function download(filename, text) {
pom.setAttribute('download', filename)
if (document.createEvent) {
- var event = document.createEvent('MouseEvents')
+ const event = document.createEvent('MouseEvents')
event.initEvent('click', true, true)
pom.dispatchEvent(event)
} else {
@@ -147,13 +146,25 @@ export function download(filename, text) {
}
}
+// For Desktop Application
+export async function downloadFileDesktop(filename: string, text: string | number | boolean | JSON) {
+ const downloadsDirectory = await downloadDir();
+ let path = filename;
+
+ if (!filename.startsWith('/')) {
+ path = await join(downloadsDirectory, filename);
+ }
+
+ await writeTextFile(path, text.toString());
+}
+
// Helper function to open a new tab
-export function openInNewTab(url) {
- var win = window.open(url, '_blank')
- win.focus()
+export function openInNewTab(url: string | URL | undefined) {
+ const win = window.open(url, '_blank')
+ win?.focus()
}
-export function copyToClipboard(text) {
+export function copyToClipboard(text: string) {
const textarea = document.createElement('textarea')
// Move it off-screen.
@@ -161,27 +172,27 @@ export function copyToClipboard(text) {
// Set to readonly to prevent mobile devices opening a keyboard when
// text is .select()'ed.
- textarea.setAttribute('readonly', true)
+ textarea.setAttribute('readonly', 'true')
document.body.appendChild(textarea)
textarea.value = text
// Check if there is any content selected previously.
const selected =
- document.getSelection().rangeCount > 0
- ? document.getSelection().getRangeAt(0)
+ document.getSelection()?.rangeCount ?? 0 > 0
+ ? document.getSelection()?.getRangeAt(0)
: false
// iOS Safari blocks programmatic execCommand copying normally, without this hack.
// https://stackoverflow.com/questions/34045777/copy-to-clipboard-using-javascript-in-ios
if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
const editable = textarea.contentEditable
- textarea.contentEditable = true
+ textarea.contentEditable = 'true'
const range = document.createRange()
range.selectNodeContents(textarea)
const sel = window.getSelection()
- sel.removeAllRanges()
- sel.addRange(range)
+ sel?.removeAllRanges()
+ sel?.addRange(range)
textarea.setSelectionRange(0, 999999)
textarea.contentEditable = editable
} else {
@@ -193,8 +204,8 @@ export function copyToClipboard(text) {
// Restore previous selection.
if (selected) {
- document.getSelection().removeAllRanges()
- document.getSelection().addRange(selected)
+ document.getSelection()?.removeAllRanges()
+ document.getSelection()?.addRange(selected)
}
textarea.remove()
return result
@@ -205,7 +216,7 @@ export function copyToClipboard(text) {
}
}
-export function truncateString(str, num) {
+export function truncateString(str: string, num: number) {
// If the length of str is less than or equal to num
// just return str--don't truncate it.
if (str.length <= num) {
@@ -216,13 +227,13 @@ export function truncateString(str, num) {
}
export function bitConverterDialog() {
- const simulatorStore = SimulatorStore();
- simulatorStore.dialogBox.hex_bin_dec_converter_dialog = true;
+ const simulatorStore = SimulatorStore()
+ simulatorStore.dialogBox.hex_bin_dec_converter_dialog = true
}
-export function getImageDimensions(file) {
+export function getImageDimensions(file: string) {
return new Promise(function (resolved, rejected) {
- var i = new Image()
+ const i = new Image()
i.onload = function () {
resolved({ w: i.width, h: i.height })
}
@@ -231,15 +242,24 @@ export function getImageDimensions(file) {
}
// convertors
-export var convertors = {
- dec2bin: (x) => '0b' + x.toString(2),
- dec2hex: (x) => '0x' + x.toString(16),
- dec2octal: (x) => '0' + x.toString(8),
- dec2bcd: (x) => parseInt(x.toString(10), 16).toString(2),
+export const convertors = {
+ dec2bin: (x: number) => '0b' + x.toString(2),
+ dec2hex: (x: number) => '0x' + x.toString(16),
+ dec2octal: (x: number) => '0' + x.toString(8),
+ dec2bcd: (x: number) => parseInt(x.toString(10), 16).toString(2),
}
-export function parseNumber(num) {
- if (num instanceof Number) return num
+export function setBaseValues(x) {
+ if (isNaN(x)) return;
+ $("#binaryInput").val(convertors.dec2bin(x));
+ $("#bcdInput").val(convertors.dec2bcd(x));
+ $("#octalInput").val(convertors.dec2octal(x));
+ $("#hexInput").val(convertors.dec2hex(x));
+ $("#decimalInput").val(x);
+}
+
+export function parseNumber(num: string | number) {
+ if(typeof num === 'number') return num;
if (num.slice(0, 2).toLocaleLowerCase() == '0b')
return parseInt(num.slice(2), 2)
if (num.slice(0, 2).toLocaleLowerCase() == '0x')
@@ -248,26 +268,75 @@ export function parseNumber(num) {
return parseInt(num)
}
-export function promptFile(contentType, multiple) {
- var input = document.createElement('input')
+export function setupBitConvertor() {
+ $("#decimalInput").on('keyup', function () {
+ var x = parseInt($("#decimalInput").val(), 10);
+ setBaseValues(x);
+ })
+
+ $("#binaryInput").on('keyup', function () {
+ var inp = $("#binaryInput").val();
+ var x;
+ if (inp.slice(0, 2) == '0b')
+ x = parseInt(inp.slice(2), 2);
+ else
+ x = parseInt(inp, 2);
+ setBaseValues(x);
+ })
+ $("#bcdInput").on('keyup', function () {
+ var input = $("#bcdInput").val();
+ var num = 0;
+ while (input.length % 4 !== 0){
+ input = "0" + input;
+ }
+ if(input !== 0){
+ var i = 0;
+ while (i < input.length / 4){
+ if(parseInt(input.slice((4 * i), 4 * (i + 1)), 2) < 10)
+ num = num * 10 + parseInt(input.slice((4 * i), 4 * (i + 1)), 2);
+ else
+ return setBaseValues(NaN);
+ i++;
+ }
+ }
+ return setBaseValues(x);
+ })
+
+ $("#hexInput").on('keyup', function () {
+ var x = parseInt($("#hexInput").val(), 16);
+ setBaseValues(x);
+ })
+
+ $("#octalInput").on('keyup', function () {
+ var x = parseInt($("#octalInput").val(), 8);
+ setBaseValues(x);
+ })
+}
+
+export function promptFile(contentType: string, multiple: boolean) {
+ const input = document.createElement('input')
input.type = 'file'
input.multiple = multiple
input.accept = contentType
return new Promise(function (resolve) {
- document.activeElement.onfocus = function () {
- document.activeElement.onfocus = null
- setTimeout(resolve, 500)
+ if (document.activeElement instanceof HTMLInputElement) {
+ (document.activeElement as HTMLInputElement).onfocus = function () {
+ (document.activeElement as HTMLInputElement).onfocus = null;
+ setTimeout(resolve, 500);
+ };
}
input.onchange = function () {
- var files = Array.from(input.files)
- if (multiple) return resolve(files)
- resolve(files[0])
+ const files = input.files
+ if (files === null) return resolve([])
+ const fileArray = Array.from(files)
+ if (multiple) return resolve(fileArray)
+ resolve(fileArray[0])
}
input.click()
})
}
-export function escapeHtml(unsafe) {
+export function escapeHtml(unsafe: string) {
return unsafe
.replace(/&/g, '&')
.replace(/" + obj.objectType + ''
- )
-
- if (obj.subcircuitMutableProperties && obj.canShowInSubcircuit) {
- for (let attr in obj.subcircuitMutableProperties) {
- var prop = obj.subcircuitMutableProperties[attr]
- if (obj.subcircuitMutableProperties[attr].type == 'number') {
- var s =
- '
' +
- prop.name +
- "
"
- $('#moduleProperty-inner').append(s)
- }
- }
- if (!obj.labelDirectionFixed) {
- if (!obj.subcircuitMetadata.labelDirection)
- obj.subcircuitMetadata.labelDirection = obj.labelDirection
- var s = $(
- "
'
- )
- s.val(obj.subcircuitMetadata.labelDirection)
- $('#moduleProperty-inner').append(
- '
Label Direction: ' + $(s).prop('outerHTML') + '
'
- )
- }
- }
- } else if (
- simulationArea.lastSelected === undefined ||
- ['Wire', 'CircuitElement', 'Node'].indexOf(
- simulationArea.lastSelected.objectType
- ) !== -1
- ) {
- $('#moduleProperty').show()
-
- $('#moduleProperty-inner').append(
- `
Project:
`
- )
- $('#moduleProperty-inner').append(
- `
Circuit:
`
- )
- $('#moduleProperty-inner').append(
- `
Clock Time (ms):
`
- )
- $('#moduleProperty-inner').append(
- `
Clock Enabled:
`
- )
- $('#moduleProperty-inner').append(
- `
Lite Mode:
`
- )
- $('#moduleProperty-inner').append(
- "
"
- )
- // $('#moduleProperty-inner').append("
");
- } else {
- $('#moduleProperty').show()
-
- $('#moduleProperty-inner').append(
- `
`
- )
- // $('#moduleProperty').append("
");
- if (!obj.fixedBitWidth) {
- $('#moduleProperty-inner').append(
- `
BitWidth:
`
- )
- }
-
- if (obj.changeInputSize) {
- $('#moduleProperty-inner').append(
- `
Input Size:
`
- )
- }
-
- if (!obj.propagationDelayFixed) {
- $('#moduleProperty-inner').append(
- `
Delay:
`
- )
- }
-
- if (!obj.disableLabel)
- $('#moduleProperty-inner').append(
- `
Label:
`
- )
-
- var s
- if (!obj.labelDirectionFixed) {
- s = $(
- `${
- "
'
- )
- s.val(obj.labelDirection)
- $('#moduleProperty-inner').append(
- `
Label Direction: ${$(s).prop('outerHTML')}
`
- )
- }
-
- if (!obj.directionFixed) {
- s = $(
- `${
- "
'
- )
- $('#moduleProperty-inner').append(
- `
Direction: ${$(s).prop('outerHTML')}
`
- )
- } else if (!obj.orientationFixed) {
- s = $(
- `${
- "
'
- )
- $('#moduleProperty-inner').append(
- `
Orientation: ${$(s).prop('outerHTML')}
`
- )
- }
-
- if (obj.mutableProperties) {
- for (const attr in obj.mutableProperties) {
- var prop = obj.mutableProperties[attr]
- if (obj.mutableProperties[attr].type === 'number') {
- s = `
${
- prop.name
- }
`
- $('#moduleProperty-inner').append(s)
- } else if (obj.mutableProperties[attr].type === 'text') {
- s = `
${
- prop.name
- }
`
- $('#moduleProperty-inner').append(s)
- } else if (obj.mutableProperties[attr].type === 'button') {
- s = `
`
- $('#moduleProperty-inner').append(s)
- } else if (obj.mutableProperties[attr].type === 'textarea') {
- s = `
${prop.name}
`
- $('#moduleProperty-inner').append(s)
- }
- }
- }
- }
-
- var helplink = obj && obj.helplink
- if (helplink) {
- $('#moduleProperty-inner').append(
- '
'
- )
- $('#HelpButton').on('click', () => {
- window.open(helplink)
- })
- }
-*/
checkPropertiesUpdate(this)
-
- // $(".moduleProperty input[type='number']").inputSpinner();
}
/**
@@ -613,28 +294,63 @@ export function deleteSelected() {
updateRestrictedElementsInScope()
}
-export function setupPanels() {
- // $('#dragQPanel')
- // .on('mousedown', () =>
- // $('.quick-btn').draggable({
- // disabled: false,
- // containment: 'window',
- // })
- // )
- // .on('mouseup', () => $('.quick-btn').draggable({ disabled: true }))
-
- // let position = { x: 0, y: 0 }
- // interact('.quick-btn').draggable({
- // allowFrom: '#dragQPanel',
- // listeners: {
- // move(event) {
- // position.x = position.x + event.dx
- // position.y = position.y + event.dy
- // event.target.style.transform = `translate(${position.x}px, ${position.y}px)`
- // },
- // },
- // })
+/**
+ * listener for opening the prompt for bin conversion
+ * @category ux
+ */
+$('#bitconverter').on('click', () => {
+ $('#bitconverterprompt').dialog({
+ resizable: false,
+ buttons: [
+ {
+ text: 'Reset',
+ click() {
+ $('#decimalInput').val('0')
+ $('#binaryInput').val('0')
+ $('#octalInput').val('0')
+ $('#hexInput').val('0')
+ },
+ },
+ ],
+ })
+})
+
+// convertors
+const convertors = {
+ dec2bin: (x) => `0b${x.toString(2)}`,
+ dec2hex: (x) => `0x${x.toString(16)}`,
+ dec2octal: (x) => `0${x.toString(8)}`,
+}
+
+function setBaseValues(x) {
+ if (isNaN(x)) return
+ $('#binaryInput').val(convertors.dec2bin(x))
+ $('#octalInput').val(convertors.dec2octal(x))
+ $('#hexInput').val(convertors.dec2hex(x))
+ $('#decimalInput').val(x)
+}
+
+$('#decimalInput').on('keyup', () => {
+ var x = parseInt($('#decimalInput').val(), 10)
+ setBaseValues(x)
+})
+
+$('#binaryInput').on('keyup', () => {
+ var x = parseInt($('#binaryInput').val(), 2)
+ setBaseValues(x)
+})
+
+$('#hexInput').on('keyup', () => {
+ var x = parseInt($('#hexInput').val(), 16)
+ setBaseValues(x)
+})
+
+$('#octalInput').on('keyup', () => {
+ var x = parseInt($('#octalInput').val(), 8)
+ setBaseValues(x)
+})
+export function setupPanels() {
dragging('#dragQPanel', '.quick-btn')
setupPanelListeners('.elementPanel')
@@ -648,16 +364,9 @@ export function setupPanels() {
// Minimize Timing Diagram (takes too much space)
$('.timing-diagram-panel .minimize').trigger('click')
- // Update the Testbench Panel UI
- updateTestbenchUI()
// Minimize Testbench UI
$('.testbench-manual-panel .minimize').trigger('click')
- // Hack because minimizing panel then maximizing sets visibility recursively
- // updateTestbenchUI calls some hide()s which are undone by maximization
- // TODO: Remove hack
- $('.testbench-manual-panel .maximize').on('click', setupTestbenchUI)
-
$('#projectName').on('click', () => {
$("input[name='setProjectName']").focus().select()
})
@@ -670,26 +379,6 @@ function setupPanelListeners(panelSelector) {
var bodySelector = `${panelSelector} > .panel-body`
dragging(headerSelector, panelSelector)
- // let position = { x: 0, y: 0 }
- // Drag Start
- // $(headerSelector).on('mousedown', () =>
- // $(panelSelector).draggable({ disabled: false, containment: 'window' })
- // interact(panelSelector).draggable({
- // allowFrom: headerSelector,
- // listeners: {
- // move(event) {
- // position.x += event.dx
- // position.y += event.dy
-
- // event.target.style.transform = `translate(${position.x}px, ${position.y}px)`
- // },
- // },
- // })
- // )
- // // Drag End
- // $(headerSelector).on('mouseup', () =>
- // $(panelSelector).draggable({ disabled: true })
- // )
// Current Panel on Top
var minimized = false
$(headerSelector).on('dblclick', () =>
@@ -725,6 +414,13 @@ export function exitFullView() {
element.style.display = ''
}
})
+
+ // Mobile Components
+
+ const simulatorMobileStore = toRefs(useSimulatorMobileStore());
+
+ simulatorMobileStore.showQuickButtons.value = true
+ simulatorMobileStore.showMobileButtons.value = true
}
export function fullView() {
@@ -743,61 +439,58 @@ export function fullView() {
}
})
+ // Mobile Components
+
+ const simulatorMobileStore = toRefs(useSimulatorMobileStore());
+
+ simulatorMobileStore.showElementsPanel.value = false
+ simulatorMobileStore.showPropertiesPanel.value = false
+ simulatorMobileStore.showTimingDiagram.value = false
+ simulatorMobileStore.showQuickButtons.value = false
+ simulatorMobileStore.showMobileButtons.value = false
+
app.appendChild(exitViewEl)
exitViewEl.addEventListener('click', exitFullView)
}
-/**
+/**
Fills the elements that can be displayed in the subcircuit, in the subcircuit menu
**/
export function fillSubcircuitElements() {
- $('#subcircuitMenu').empty()
- var subCircuitElementExists = false
+ const simulatorStore = SimulatorStore()
+ const { subCircuitElementList, isEmptySubCircuitElementList } = toRefs(simulatorStore)
+ subCircuitElementList.value = []
+ isEmptySubCircuitElementList.value = true
+
+ const subcircuitElements = []
+
+ let subCircuitElementExists = false
+
for (let el of circuitElementList) {
if (globalScope[el].length === 0) continue
if (!globalScope[el][0].canShowInSubcircuit) continue
- let tempHTML = ''
-
- // add a panel for each existing group
- tempHTML += ``
- tempHTML += `
`
let available = false
+ const elementGroup = {
+ type: el,
+ elements: [],
+ }
+
// add an SVG for each element
for (let i = 0; i < globalScope[el].length; i++) {
if (!globalScope[el][i].subcircuitMetadata.showInSubcircuit) {
- tempHTML += `
`
- tempHTML += `

`
- tempHTML += `
${
- globalScope[el][i].label !== ''
- ? globalScope[el][i].label
- : 'unlabeled'
- }
`
- tempHTML += '
'
available = true
+ const element = globalScope[el][i];
+ elementGroup.elements.push(element);
}
}
- tempHTML += '
'
subCircuitElementExists = subCircuitElementExists || available
- if (available) $('#subcircuitMenu').append(tempHTML)
- }
+ if (available) {
+ subcircuitElements.push(elementGroup);
+ }
- if (subCircuitElementExists) {
- // $('#subcircuitMenu').accordion('refresh')
- } else {
- $('#subcircuitMenu').append('
No layout elements available
')
+ subCircuitElementList.value = subcircuitElements
+ isEmptySubCircuitElementList.value = !subCircuitElementExists
}
-
- $('.subcircuitModule').mousedown(function () {
- let elementName = this.dataset.elementName
- let elementIndex = this.dataset.elementId
-
- let element = globalScope[elementName][elementIndex]
-
- element.subcircuitMetadata.showInSubcircuit = true
- element.newElement = true
- simulationArea.lastSelected = element
- this.parentElement.removeChild(this)
- })
}
diff --git a/v1/src/simulator/src/verilog.js b/v1/src/simulator/src/verilog.js
index d0811b2c..5e0fcc26 100644
--- a/v1/src/simulator/src/verilog.js
+++ b/v1/src/simulator/src/verilog.js
@@ -7,8 +7,6 @@
*/
import { scopeList } from './circuit'
import { errorDetectedGet } from './engine'
-import { download } from './utils'
-import { getProjectName } from './data/save'
import modules from './modules'
import { sanitizeLabel } from './verilogHelpers'
import CodeMirror from 'codemirror/lib/codemirror.js'
@@ -19,49 +17,14 @@ import 'codemirror/addon/edit/closebrackets.js'
import 'codemirror/addon/hint/anyword-hint.js'
import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/display/autorefresh.js'
-import { openInNewTab, copyToClipboard, showMessage } from './utils'
import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
+import { inputList, moduleList } from './metadata'
+
var editor
export function generateVerilog() {
const simulatorStore = SimulatorStore()
simulatorStore.dialogBox.exportverilog_dialog = true
- // var dialog = $('#verilog-export-code-window-div')
- // var data = verilog.exportVerilog()
- // editor.setValue(data)
- // $('#verilog-export-code-window-div .CodeMirror').css(
- // 'height',
- // $(window).height() - 200
- // )
- // dialog.dialog({
- // resizable: false,
- // width: '90%',
- // height: 'auto',
- // position: { my: 'center', at: 'center', of: window },
- // buttons: [
- // {
- // text: 'Download Verilog File',
- // click() {
- // var fileName = getProjectName() || 'Untitled'
- // download(fileName + '.v', editor.getValue())
- // },
- // },
- // {
- // text: 'Copy to Clipboard',
- // click() {
- // copyToClipboard(editor.getValue())
- // showMessage('Code has been copied')
- // },
- // },
- // {
- // text: 'Try in EDA Playground',
- // click() {
- // copyToClipboard(editor.getValue())
- // openInNewTab('https://www.edaplayground.com/x/XZpY')
- // },
- // },
- // ],
- // })
}
export function setupVerilogExportCodeWindow() {
@@ -529,45 +492,14 @@ export var verilog = {
return res
},
- /*
- sanitizeLabel: function(name){
- // Replace spaces by "_"
- name = name.replace(/ /g , "_");
- // Replace Hyphens by "_"
- name = name.replace(/-/g , "_");
- // Replace Colons by "_"
- name = name.replace(/:/g , "_");
- // replace ~ with inv_
- name = name.replace(/~/g , "inv_");
- // Shorten Inverse to inv
- name = name.replace(/Inverse/g , "inv");
-
- // If first character is a number
- if(name.substring(0, 1).search(/[0-9]/g) > -1) {
- name = "w_" + name;
- }
-
- // if first character is not \ already
- if (name[0] != '\\') {
- //if there are non-alphanum_ character, add \
- if (name.search(/[\W]/g) > -1)
- name = "\\" + name;
- }
- return name;
- },
- */
}
-/*
- Helper function to generate spaces for indentation
-*/
+/* Helper function to generate spaces for indentation */
function sp(indentation) {
return ' '.repeat(indentation * 2)
}
-/*
- Helper function to indent paragraph
-*/
+/* Helper function to indent paragraph */
function indent(indentation, string) {
var result = string.split('\n')
if (result[result.length - 1] == '') {
diff --git a/v1/src/simulator/src/verilogHelpers.js b/v1/src/simulator/src/verilogHelpers.js
index 3f9a4123..e2b4cb4a 100644
--- a/v1/src/simulator/src/verilogHelpers.js
+++ b/v1/src/simulator/src/verilogHelpers.js
@@ -1,5 +1,4 @@
export function sanitizeLabel(name) {
- // return name.replace(/ Inverse/g, "_inv").replace(/ /g , "_");
var temp = name
// if there is a space anywhere but the last place
// replace spaces by "_"
diff --git a/v1/src/simulator/src/wire.js b/v1/src/simulator/src/wire.js
deleted file mode 100644
index 7e06e7d2..00000000
--- a/v1/src/simulator/src/wire.js
+++ /dev/null
@@ -1,240 +0,0 @@
-/* eslint-disable no-multi-assign */
-// wire object
-import { drawLine } from './canvasApi'
-import simulationArea from './simulationArea'
-import Node from './node'
-import { updateSimulationSet, forceResetNodesSet } from './engine'
-import { colors } from './themer/themer'
-
-/**
- * Wire - To connect two nodes.
- * @class
- * @memberof module:wire
- * @param {Node} node1
- * @param {Node} node2
- * @param {Scope} scope - The circuit in which wire has to be drawn
- * @category wire
- */
-export default class Wire {
- constructor(node1, node2, scope) {
- this.objectType = 'Wire'
- this.node1 = node1
- this.scope = scope
- this.node2 = node2
- this.type = 'horizontal'
-
- this.updateData()
- this.scope.wires.push(this)
- forceResetNodesSet(true)
- }
-
- // if data changes
- updateData() {
- this.x1 = this.node1.absX()
- this.y1 = this.node1.absY()
- this.x2 = this.node2.absX()
- this.y2 = this.node2.absY()
- if (this.x1 === this.x2) this.type = 'vertical'
- }
-
- updateScope(scope) {
- this.scope = scope
- this.checkConnections()
- }
-
- // to check if nodes are disconnected
- checkConnections() {
- var check =
- this.node1.deleted ||
- this.node2.deleted ||
- !this.node1.connections.contains(this.node2) ||
- !this.node2.connections.contains(this.node1)
- if (check) this.delete()
- return check
- }
-
- dblclick() {
- if (
- this.node1.parent == globalScope.root &&
- this.node2.parent == globalScope.root
- ) {
- simulationArea.multipleObjectSelections = [this.node1, this.node2]
- simulationArea.lastSelected = undefined
- }
- }
-
- update() {
- var updated = false
- if (embed) return updated
-
- if (this.node1.absX() === this.node2.absX()) {
- this.x1 = this.x2 = this.node1.absX()
- this.type = 'vertical'
- } else if (this.node1.absY() === this.node2.absY()) {
- this.y1 = this.y2 = this.node1.absY()
- this.type = 'horizontal'
- }
-
- // if (wireToBeChecked && this.checkConnections()) {
- // this.delete();
- // return updated;
- // } // SLOW , REMOVE
- if (
- simulationArea.shiftDown === false &&
- simulationArea.mouseDown === true &&
- simulationArea.selected === false &&
- this.checkWithin(
- simulationArea.mouseDownX,
- simulationArea.mouseDownY
- )
- ) {
- simulationArea.selected = true
- simulationArea.lastSelected = this
- updated = true
- } else if (
- simulationArea.mouseDown &&
- simulationArea.lastSelected === this &&
- !this.checkWithin(simulationArea.mouseX, simulationArea.mouseY)
- ) {
- var n = new Node(
- simulationArea.mouseDownX,
- simulationArea.mouseDownY,
- 2,
- this.scope.root
- )
- n.clicked = true
- n.wasClicked = true
- simulationArea.lastSelected = n
- this.converge(n)
- }
- // eslint-disable-next-line no-empty
- if (simulationArea.lastSelected === this) {
- }
-
- if (this.node1.deleted || this.node2.deleted) {
- this.delete()
- return updated
- } // if either of the nodes are deleted
-
- if (simulationArea.mouseDown === false) {
- if (this.type === 'horizontal') {
- if (this.node1.absY() !== this.y1) {
- // if(this.checkConnections()){this.delete();return;}
- n = new Node(this.node1.absX(), this.y1, 2, this.scope.root)
- this.converge(n)
- updated = true
- } else if (this.node2.absY() !== this.y2) {
- // if(this.checkConnections()){this.delete();return;}
- n = new Node(this.node2.absX(), this.y2, 2, this.scope.root)
- this.converge(n)
- updated = true
- }
- } else if (this.type === 'vertical') {
- if (this.node1.absX() !== this.x1) {
- // if(this.checkConnections()){this.delete();return;}
- n = new Node(this.x1, this.node1.absY(), 2, this.scope.root)
- this.converge(n)
- updated = true
- } else if (this.node2.absX() !== this.x2) {
- // if(this.checkConnections()){this.delete();return;}
- n = new Node(this.x2, this.node2.absY(), 2, this.scope.root)
- this.converge(n)
- updated = true
- }
- }
- }
- return updated
- }
-
- draw() {
- // for calculating min-max Width,min-max Height
- //
- const ctx = simulationArea.context
-
- var color
- if (simulationArea.lastSelected == this) {
- color = colors['color_wire_sel']
- } else if (
- this.node1.value == undefined ||
- this.node2.value == undefined
- ) {
- color = colors['color_wire_lose']
- } else if (this.node1.bitWidth == 1) {
- color = [
- colors['color_wire_lose'],
- colors['color_wire_con'],
- colors['color_wire_pow'],
- ][this.node1.value + 1]
- } else {
- color = colors['color_wire']
- }
- drawLine(
- ctx,
- this.node1.absX(),
- this.node1.absY(),
- this.node2.absX(),
- this.node2.absY(),
- color,
- 3
- )
- }
-
- // checks if node lies on wire
- checkConvergence(n) {
- return this.checkWithin(n.absX(), n.absY())
- }
-
- // fn checks if coordinate lies on wire
- checkWithin(x, y) {
- if (
- this.type === 'horizontal' &&
- this.node1.absX() < this.node2.absX() &&
- x > this.node1.absX() &&
- x < this.node2.absX() &&
- y === this.node2.absY()
- )
- return true
- if (
- this.type === 'horizontal' &&
- this.node1.absX() > this.node2.absX() &&
- x < this.node1.absX() &&
- x > this.node2.absX() &&
- y === this.node2.absY()
- )
- return true
- if (
- this.type === 'vertical' &&
- this.node1.absY() < this.node2.absY() &&
- y > this.node1.absY() &&
- y < this.node2.absY() &&
- x === this.node2.absX()
- )
- return true
- if (
- this.type === 'vertical' &&
- this.node1.absY() > this.node2.absY() &&
- y < this.node1.absY() &&
- y > this.node2.absY() &&
- x === this.node2.absX()
- )
- return true
- return false
- }
-
- // add intermediate node between these 2 nodes
- converge(n) {
- this.node1.connect(n)
- this.node2.connect(n)
- this.delete()
- }
-
- delete() {
- forceResetNodesSet(true)
- updateSimulationSet(true)
- this.node1.connections.clean(this.node2)
- this.node2.connections.clean(this.node1)
- this.scope.wires.clean(this)
- this.node1.checkDeleted()
- this.node2.checkDeleted()
- }
-}
diff --git a/v1/src/simulator/src/wire.ts b/v1/src/simulator/src/wire.ts
new file mode 100644
index 00000000..885701c1
--- /dev/null
+++ b/v1/src/simulator/src/wire.ts
@@ -0,0 +1,265 @@
+/* eslint-disable no-multi-assign */
+import { drawLine } from './canvasApi';
+import { simulationArea } from './simulationArea';
+import Node from './node';
+import { updateSimulationSet, forceResetNodesSet } from './engine';
+import { colors } from './themer/themer';
+import CircuitElement from './circuitElement';
+
+interface Scope {
+ wires: Wire[];
+ root: CircuitElement;
+ timeStamp: number;
+}
+
+enum WireValue {
+ LOOSE = -1,
+ LOW = 0,
+ HIGH = 1
+}
+
+export default class Wire {
+ objectType = 'Wire';
+ type = 'horizontal';
+ x1: number;
+ y1: number;
+ x2: number;
+ y2: number;
+
+ constructor(public node1: Node, public node2: Node, public scope: Scope) {
+ this.x1 = this.node1.absX();
+ this.y1 = this.node1.absY();
+ this.x2 = this.node2.absX();
+ this.y2 = this.node2.absY();
+ this.updateData();
+ this.scope.wires.push(this);
+ forceResetNodesSet(true);
+ }
+
+ updateData(): void {
+ [this.x1, this.y1, this.x2, this.y2] = [
+ this.node1.absX(), this.node1.absY(),
+ this.node2.absX(), this.node2.absY()
+ ];
+ if (this.x1 === this.x2) this.type = 'vertical';
+ }
+
+ updateScope(scope: Scope): void {
+ this.scope = scope;
+ this.checkConnections();
+ }
+
+ checkConnections(): boolean {
+ const disconnected = this.node1.deleted || this.node2.deleted ||
+ !this.node1.connections?.includes(this.node2) ||
+ !this.node2.connections?.includes(this.node1);
+ if (disconnected) this.delete();
+ return disconnected;
+ }
+
+ dblclick(): void {
+ if (this.node1.parent === globalScope.root && this.node2.parent === globalScope.root) {
+ simulationArea.multipleObjectSelections = [this.node1, this.node2];
+ simulationArea.lastSelected = undefined;
+ }
+ }
+
+ update(): boolean {
+ let updated = false;
+ if (embed) return updated;
+
+ this.updateWireType();
+ updated = this.handleMouseInteraction() || updated;
+
+ if (this.node1.deleted || this.node2.deleted) {
+ this.delete();
+ return updated;
+ }
+
+ if (!simulationArea.mouseDown) {
+ updated = this.handleNodeAlignment() || updated;
+ }
+
+ return updated;
+ }
+
+ draw(): void {
+ drawLine(
+ simulationArea.context,
+ this.node1.absX(), this.node1.absY(),
+ this.node2.absX(), this.node2.absY(),
+ this.getWireColor(), 3
+ );
+ }
+
+ checkConvergence(n: Node): boolean {
+ return this.checkWithin(n.absX(), n.absY());
+ }
+
+ checkWithin(x: number, y: number): boolean {
+ if (this.type === 'horizontal') {
+ return y === this.node1.absY() && this.isBetween(x, this.node1.absX(), this.node2.absX());
+ }
+
+ if (this.type === 'vertical') {
+ return x === this.node1.absX() && this.isBetween(y, this.node1.absY(), this.node2.absY());
+ }
+
+ return false;
+ }
+
+ private isBetween(value: number, a: number, b: number): boolean {
+ return value >= Math.min(a, b) && value <= Math.max(a, b);
+ }
+
+ converge(n: Node): void {
+ this.node1.connect(n);
+ this.node2.connect(n);
+ this.delete();
+ }
+
+ delete(): void {
+ forceResetNodesSet(true);
+ updateSimulationSet(true);
+ this.removeMutualConnections();
+ this.scope.wires = this.scope.wires.filter(x => x !== this);
+ this.node1.checkDeleted();
+ this.node2.checkDeleted();
+ this.scope.timeStamp = Date.now();
+ }
+
+ private removeMutualConnections(): void {
+ this.removeConnection(this.node1, this.node2);
+ this.removeConnection(this.node2, this.node1);
+ }
+
+ private removeConnection(node: Node, otherNode: Node): void {
+ if (node.connections) {
+ node.connections = node.connections.filter(x => x !== otherNode);
+ }
+ }
+
+ private updateWireType(): void {
+ const x1 = this.node1.absX();
+ const x2 = this.node2.absX();
+ const y1 = this.node1.absY();
+ const y2 = this.node2.absY();
+
+ if (x1 === x2) {
+ this.x1 = this.x2 = x1;
+ this.type = 'vertical';
+ } else if (y1 === y2) {
+ this.y1 = this.y2 = y1;
+ this.type = 'horizontal';
+ }
+ }
+
+ private handleMouseInteraction(): boolean {
+ if (this.checkWireSelection()) {
+ simulationArea.selected = true;
+ simulationArea.lastSelected = this;
+ return true;
+ }
+
+ if (this.checkWireDrag()) {
+ this.createIntermediateNode();
+ return true;
+ }
+
+ return false;
+ }
+
+ private checkWireSelection(): boolean {
+ return !simulationArea.shiftDown &&
+ simulationArea.mouseDown &&
+ !simulationArea.selected &&
+ this.checkWithin(simulationArea.mouseDownX, simulationArea.mouseDownY);
+ }
+
+ private checkWireDrag(): boolean {
+ return simulationArea.mouseDown &&
+ simulationArea.lastSelected === this &&
+ !this.checkWithin(simulationArea.mouseX, simulationArea.mouseY);
+ }
+
+ private createIntermediateNode(): void {
+ const n = new Node(
+ simulationArea.mouseDownX,
+ simulationArea.mouseDownY,
+ 2,
+ this.scope.root
+ );
+ n.clicked = true;
+ n.wasClicked = true;
+ simulationArea.lastSelected = n;
+ this.converge(n);
+ }
+
+ private handleNodeAlignment(): boolean {
+ if (this.type === 'horizontal') {
+ return this.alignNodesAlongYAxis();
+ }
+ if (this.type === 'vertical') {
+ return this.alignNodesAlongXAxis();
+ }
+ return false;
+ }
+
+ private alignNodesAlongYAxis(): boolean {
+ return this.checkAndCreateNode(
+ this.node1.absY(),
+ this.y1,
+ () => new Node(this.node1.absX(), this.y1, 2, this.scope.root),
+ this.node2.absY(),
+ this.y2,
+ () => new Node(this.node2.absX(), this.y2, 2, this.scope.root)
+ );
+ }
+
+ private alignNodesAlongXAxis(): boolean {
+ return this.checkAndCreateNode(
+ this.node1.absX(),
+ this.x1,
+ () => new Node(this.x1, this.node1.absY(), 2, this.scope.root),
+ this.node2.absX(),
+ this.x2,
+ () => new Node(this.x2, this.node2.absY(), 2, this.scope.root)
+ );
+ }
+
+ private checkAndCreateNode(
+ current1: number,
+ expected1: number,
+ createNode1: () => Node,
+ current2: number,
+ expected2: number,
+ createNode2: () => Node
+ ): boolean {
+ if (current1 !== expected1) {
+ this.converge(createNode1());
+ return true;
+ }
+ if (current2 !== expected2) {
+ this.converge(createNode2());
+ return true;
+ }
+ return false;
+ }
+
+ private getWireColor(): string {
+ if (simulationArea.lastSelected === this) {
+ return colors['color_wire_sel'];
+ }
+ if (this.node1.value === undefined || this.node2.value === undefined) {
+ return colors['color_wire_lose'];
+ }
+ if (this.node1.bitWidth === 1) {
+ return [
+ colors['color_wire_lose'],
+ colors['color_wire_con'],
+ colors['color_wire_pow'],
+ ][this.node1.value - WireValue.LOOSE];
+ }
+ return colors['color_wire'];
+ }
+}
\ No newline at end of file
diff --git a/v1/src/simulator/vendor/canvas2svg.js b/v1/src/simulator/vendor/canvas2svg.js
deleted file mode 100644
index 73dae81d..00000000
--- a/v1/src/simulator/vendor/canvas2svg.js
+++ /dev/null
@@ -1,1469 +0,0 @@
-/*!!
- * Canvas 2 Svg v1.0.19
- * A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document.
- *
- * Licensed under the MIT license:
- * http://www.opensource.org/licenses/mit-license.php
- *
- * Author:
- * Kerry Liu
- *
- * Copyright (c) 2014 Gliffy Inc.
- */
-
-;(function () {
- 'use strict'
-
- var STYLES, ctx, CanvasGradient, CanvasPattern, namedEntities
-
- //helper function to format a string
- function format(str, args) {
- var keys = Object.keys(args),
- i
- for (i = 0; i < keys.length; i++) {
- str = str.replace(
- new RegExp('\\{' + keys[i] + '\\}', 'gi'),
- args[keys[i]]
- )
- }
- return str
- }
-
- //helper function that generates a random string
- function randomString(holder) {
- var chars, randomstring, i
- if (!holder) {
- throw new Error(
- 'cannot create a random attribute name for an undefined object'
- )
- }
- chars = 'ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'
- randomstring = ''
- do {
- randomstring = ''
- for (i = 0; i < 12; i++) {
- randomstring += chars[Math.floor(Math.random() * chars.length)]
- }
- } while (holder[randomstring])
- return randomstring
- }
-
- //helper function to map named to numbered entities
- function createNamedToNumberedLookup(items, radix) {
- var i,
- entity,
- lookup = {},
- base10,
- base16
- items = items.split(',')
- radix = radix || 10
- // Map from named to numbered entities.
- for (i = 0; i < items.length; i += 2) {
- entity = '&' + items[i + 1] + ';'
- base10 = parseInt(items[i], radix)
- lookup[entity] = '' + base10 + ';'
- }
- //FF and IE need to create a regex from hex values ie == \xa0
- lookup['\\xa0'] = ' '
- return lookup
- }
-
- //helper function to map canvas-textAlign to svg-textAnchor
- function getTextAnchor(textAlign) {
- //TODO: support rtl languages
- var mapping = {
- left: 'start',
- right: 'end',
- center: 'middle',
- start: 'start',
- end: 'end',
- }
- return mapping[textAlign] || mapping.start
- }
-
- //helper function to map canvas-textBaseline to svg-dominantBaseline
- function getDominantBaseline(textBaseline) {
- //INFO: not supported in all browsers
- var mapping = {
- alphabetic: 'alphabetic',
- hanging: 'hanging',
- top: 'text-before-edge',
- bottom: 'text-after-edge',
- middle: 'central',
- }
- return mapping[textBaseline] || mapping.alphabetic
- }
-
- // Unpack entities lookup where the numbers are in radix 32 to reduce the size
- // entity mapping courtesy of tinymce
- namedEntities = createNamedToNumberedLookup(
- '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
- '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
- '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
- '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
- '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
- '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
- '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
- '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
- '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
- '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
- 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
- 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
- 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
- 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
- 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
- '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
- '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
- '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
- '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
- '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
- 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
- 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
- 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
- '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
- '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro',
- 32
- )
-
- //Some basic mappings for attributes and default values.
- STYLES = {
- strokeStyle: {
- svgAttr: 'stroke', //corresponding svg attribute
- canvas: '#000000', //canvas default
- svg: 'none', //svg default
- apply: 'stroke', //apply on stroke() or fill()
- },
- fillStyle: {
- svgAttr: 'fill',
- canvas: '#000000',
- svg: null, //svg default is black, but we need to special case this to handle canvas stroke without fill
- apply: 'fill',
- },
- lineCap: {
- svgAttr: 'stroke-linecap',
- canvas: 'butt',
- svg: 'butt',
- apply: 'stroke',
- },
- lineJoin: {
- svgAttr: 'stroke-linejoin',
- canvas: 'miter',
- svg: 'miter',
- apply: 'stroke',
- },
- miterLimit: {
- svgAttr: 'stroke-miterlimit',
- canvas: 10,
- svg: 4,
- apply: 'stroke',
- },
- lineWidth: {
- svgAttr: 'stroke-width',
- canvas: 1,
- svg: 1,
- apply: 'stroke',
- },
- globalAlpha: {
- svgAttr: 'opacity',
- canvas: 1,
- svg: 1,
- apply: 'fill stroke',
- },
- font: {
- //font converts to multiple svg attributes, there is custom logic for this
- canvas: '10px sans-serif',
- },
- shadowColor: {
- canvas: '#000000',
- },
- shadowOffsetX: {
- canvas: 0,
- },
- shadowOffsetY: {
- canvas: 0,
- },
- shadowBlur: {
- canvas: 0,
- },
- textAlign: {
- canvas: 'start',
- },
- textBaseline: {
- canvas: 'alphabetic',
- },
- lineDash: {
- svgAttr: 'stroke-dasharray',
- canvas: [],
- svg: null,
- apply: 'stroke',
- },
- }
-
- /**
- *
- * @param gradientNode - reference to the gradient
- * @constructor
- */
- CanvasGradient = function (gradientNode, ctx) {
- this.__root = gradientNode
- this.__ctx = ctx
- }
-
- /**
- * Adds a color stop to the gradient root
- */
- CanvasGradient.prototype.addColorStop = function (offset, color) {
- var stop = this.__ctx.__createElement('stop'),
- regex,
- matches
- stop.setAttribute('offset', offset)
- if (color.indexOf('rgba') !== -1) {
- //separate alpha value, since webkit can't handle it
- regex =
- /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi
- matches = regex.exec(color)
- stop.setAttribute(
- 'stop-color',
- format('rgb({r},{g},{b})', {
- r: matches[1],
- g: matches[2],
- b: matches[3],
- })
- )
- stop.setAttribute('stop-opacity', matches[4])
- } else {
- stop.setAttribute('stop-color', color)
- }
- this.__root.appendChild(stop)
- }
-
- CanvasPattern = function (pattern, ctx) {
- this.__root = pattern
- this.__ctx = ctx
- }
-
- /**
- * The mock canvas context
- * @param o - options include:
- * ctx - existing Context2D to wrap around
- * width - width of your canvas (defaults to 500)
- * height - height of your canvas (defaults to 500)
- * enableMirroring - enables canvas mirroring (get image data) (defaults to false)
- * document - the document object (defaults to the current document)
- */
- ctx = function (o) {
- var defaultOptions = {
- width: 500,
- height: 500,
- enableMirroring: false,
- },
- options
-
- //keep support for this way of calling C2S: new C2S(width,height)
- if (arguments.length > 1) {
- options = defaultOptions
- options.width = arguments[0]
- options.height = arguments[1]
- } else if (!o) {
- options = defaultOptions
- } else {
- options = o
- }
-
- if (!(this instanceof ctx)) {
- //did someone call this without new?
- return new ctx(options)
- }
-
- //setup options
- this.width = options.width || defaultOptions.width
- this.height = options.height || defaultOptions.height
- this.enableMirroring =
- options.enableMirroring !== undefined
- ? options.enableMirroring
- : defaultOptions.enableMirroring
-
- this.canvas = this ///point back to this instance!
- this.__document = options.document || document
-
- // allow passing in an existing context to wrap around
- // if a context is passed in, we know a canvas already exist
- if (options.ctx) {
- this.__ctx = options.ctx
- } else {
- this.__canvas = this.__document.createElement('canvas')
- this.__ctx = this.__canvas.getContext('2d')
- }
-
- this.__setDefaultStyles()
- this.__stack = [this.__getStyleState()]
- this.__groupStack = []
-
- //the root svg element
- this.__root = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'svg'
- )
- this.__root.setAttribute('version', 1.1)
- this.__root.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
- this.__root.setAttributeNS(
- 'http://www.w3.org/2000/xmlns/',
- 'xmlns:xlink',
- 'http://www.w3.org/1999/xlink'
- )
- this.__root.setAttribute('width', this.width)
- this.__root.setAttribute('height', this.height)
-
- //make sure we don't generate the same ids in defs
- this.__ids = {}
-
- //defs tag
- this.__defs = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'defs'
- )
- this.__root.appendChild(this.__defs)
-
- //also add a group child. the svg element can't use the transform attribute
- this.__currentElement = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'g'
- )
- this.__root.appendChild(this.__currentElement)
- }
-
- /**
- * Creates the specified svg element
- * @private
- */
- ctx.prototype.__createElement = function (
- elementName,
- properties,
- resetFill
- ) {
- if (typeof properties === 'undefined') {
- properties = {}
- }
-
- var element = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- elementName
- ),
- keys = Object.keys(properties),
- i,
- key
- if (resetFill) {
- //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black.
- element.setAttribute('fill', 'none')
- element.setAttribute('stroke', 'none')
- }
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- element.setAttribute(key, properties[key])
- }
- return element
- }
-
- /**
- * Applies default canvas styles to the context
- * @private
- */
- ctx.prototype.__setDefaultStyles = function () {
- //default 2d canvas context properties see:http://www.w3.org/TR/2dcontext/
- var keys = Object.keys(STYLES),
- i,
- key
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- this[key] = STYLES[key].canvas
- }
- }
-
- /**
- * Applies styles on restore
- * @param styleState
- * @private
- */
- ctx.prototype.__applyStyleState = function (styleState) {
- var keys = Object.keys(styleState),
- i,
- key
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- this[key] = styleState[key]
- }
- }
-
- /**
- * Gets the current style state
- * @return {Object}
- * @private
- */
- ctx.prototype.__getStyleState = function () {
- var i,
- styleState = {},
- keys = Object.keys(STYLES),
- key
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- styleState[key] = this[key]
- }
- return styleState
- }
-
- /**
- * Apples the current styles to the current SVG element. On "ctx.fill" or "ctx.stroke"
- * @param type
- * @private
- */
- ctx.prototype.__applyStyleToCurrentElement = function (type) {
- var currentElement = this.__currentElement
- var currentStyleGroup = this.__currentElementsToStyle
- if (currentStyleGroup) {
- currentElement.setAttribute(type, '')
- currentElement = currentStyleGroup.element
- currentStyleGroup.children.forEach(function (node) {
- node.setAttribute(type, '')
- })
- }
-
- var keys = Object.keys(STYLES),
- i,
- style,
- value,
- id,
- regex,
- matches
- for (i = 0; i < keys.length; i++) {
- style = STYLES[keys[i]]
- value = this[keys[i]]
- if (style.apply) {
- //is this a gradient or pattern?
- if (value instanceof CanvasPattern) {
- //pattern
- if (value.__ctx) {
- //copy over defs
- while (value.__ctx.__defs.childNodes.length) {
- id =
- value.__ctx.__defs.childNodes[0].getAttribute(
- 'id'
- )
- this.__ids[id] = id
- this.__defs.appendChild(
- value.__ctx.__defs.childNodes[0]
- )
- }
- }
- currentElement.setAttribute(
- style.apply,
- format('url(#{id})', {
- id: value.__root.getAttribute('id'),
- })
- )
- } else if (value instanceof CanvasGradient) {
- //gradient
- currentElement.setAttribute(
- style.apply,
- format('url(#{id})', {
- id: value.__root.getAttribute('id'),
- })
- )
- } else if (
- style.apply.indexOf(type) !== -1 &&
- style.svg !== value
- ) {
- if (
- (style.svgAttr === 'stroke' ||
- style.svgAttr === 'fill') &&
- value.indexOf('rgba') !== -1
- ) {
- //separate alpha value, since illustrator can't handle it
- regex =
- /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi
- matches = regex.exec(value)
- currentElement.setAttribute(
- style.svgAttr,
- format('rgb({r},{g},{b})', {
- r: matches[1],
- g: matches[2],
- b: matches[3],
- })
- )
- //should take globalAlpha here
- var opacity = matches[4]
- var globalAlpha = this.globalAlpha
- if (globalAlpha != null) {
- opacity *= globalAlpha
- }
- currentElement.setAttribute(
- style.svgAttr + '-opacity',
- opacity
- )
- } else {
- var attr = style.svgAttr
- if (keys[i] === 'globalAlpha') {
- attr = type + '-' + style.svgAttr
- if (currentElement.getAttribute(attr)) {
- //fill-opacity or stroke-opacity has already been set by stroke or fill.
- continue
- }
- }
- //otherwise only update attribute if right type, and not svg default
- currentElement.setAttribute(attr, value)
- }
- }
- }
- }
- }
-
- /**
- * Will return the closest group or svg node. May return the current element.
- * @private
- */
- ctx.prototype.__closestGroupOrSvg = function (node) {
- node = node || this.__currentElement
- if (node.nodeName === 'g' || node.nodeName === 'svg') {
- return node
- } else {
- return this.__closestGroupOrSvg(node.parentNode)
- }
- }
-
- /**
- * Returns the serialized value of the svg so far
- * @param fixNamedEntities - Standalone SVG doesn't support named entities, which document.createTextNode encodes.
- * If true, we attempt to find all named entities and encode it as a numeric entity.
- * @return serialized svg
- */
- ctx.prototype.getSerializedSvg = function (fixNamedEntities) {
- var serialized = new XMLSerializer().serializeToString(this.__root),
- keys,
- i,
- key,
- value,
- regexp,
- xmlns
-
- //IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
- xmlns =
- /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi
- if (xmlns.test(serialized)) {
- serialized = serialized.replace(
- 'xmlns="http://www.w3.org/2000/svg',
- 'xmlns:xlink="http://www.w3.org/1999/xlink'
- )
- }
-
- if (fixNamedEntities) {
- keys = Object.keys(namedEntities)
- //loop over each named entity and replace with the proper equivalent.
- for (i = 0; i < keys.length; i++) {
- key = keys[i]
- value = namedEntities[key]
- regexp = new RegExp(key, 'gi')
- if (regexp.test(serialized)) {
- serialized = serialized.replace(regexp, value)
- }
- }
- }
-
- return serialized
- }
-
- /**
- * Returns the root svg
- * @return
- */
- ctx.prototype.getSvg = function () {
- return this.__root
- }
- /**
- * Will generate a group tag.
- */
- ctx.prototype.save = function () {
- var group = this.__createElement('g')
- var parent = this.__closestGroupOrSvg()
- this.__groupStack.push(parent)
- parent.appendChild(group)
- this.__currentElement = group
- this.__stack.push(this.__getStyleState())
- }
- /**
- * Sets current element to parent, or just root if already root
- */
- ctx.prototype.restore = function () {
- this.__currentElement = this.__groupStack.pop()
- this.__currentElementsToStyle = null
- //Clearing canvas will make the poped group invalid, currentElement is set to the root group node.
- if (!this.__currentElement) {
- this.__currentElement = this.__root.childNodes[1]
- }
- var state = this.__stack.pop()
- this.__applyStyleState(state)
- }
-
- /**
- * Helper method to add transform
- * @private
- */
- ctx.prototype.__addTransform = function (t) {
- //if the current element has siblings, add another group
- var parent = this.__closestGroupOrSvg()
- if (parent.childNodes.length > 0) {
- if (this.__currentElement.nodeName === 'path') {
- if (!this.__currentElementsToStyle)
- this.__currentElementsToStyle = {
- element: parent,
- children: [],
- }
- this.__currentElementsToStyle.children.push(
- this.__currentElement
- )
- this.__applyCurrentDefaultPath()
- }
-
- var group = this.__createElement('g')
- parent.appendChild(group)
- this.__currentElement = group
- }
-
- var transform = this.__currentElement.getAttribute('transform')
- if (transform) {
- transform += ' '
- } else {
- transform = ''
- }
- transform += t
- this.__currentElement.setAttribute('transform', transform)
- }
-
- /**
- * scales the current element
- */
- ctx.prototype.scale = function (x, y) {
- if (y === undefined) {
- y = x
- }
- this.__addTransform(format('scale({x},{y})', { x: x, y: y }))
- }
-
- /**
- * rotates the current element
- */
- ctx.prototype.rotate = function (angle) {
- var degrees = (angle * 180) / Math.PI
- this.__addTransform(
- format('rotate({angle},{cx},{cy})', {
- angle: degrees,
- cx: 0,
- cy: 0,
- })
- )
- }
-
- /**
- * translates the current element
- */
- ctx.prototype.translate = function (x, y) {
- this.__addTransform(format('translate({x},{y})', { x: x, y: y }))
- }
-
- /**
- * applies a transform to the current element
- */
- ctx.prototype.transform = function (a, b, c, d, e, f) {
- this.__addTransform(
- format('matrix({a},{b},{c},{d},{e},{f})', {
- a: a,
- b: b,
- c: c,
- d: d,
- e: e,
- f: f,
- })
- )
- }
-
- /**
- * Create a new Path Element
- */
- ctx.prototype.beginPath = function () {
- var path, parent
-
- // Note that there is only one current default path, it is not part of the drawing state.
- // See also: https://html.spec.whatwg.org/multipage/scripting.html#current-default-path
- this.__currentDefaultPath = ''
- this.__currentPosition = {}
-
- path = this.__createElement('path', {}, true)
- parent = this.__closestGroupOrSvg()
- parent.appendChild(path)
- this.__currentElement = path
- }
-
- /**
- * Helper function to apply currentDefaultPath to current path element
- * @private
- */
- ctx.prototype.__applyCurrentDefaultPath = function () {
- var currentElement = this.__currentElement
- if (currentElement.nodeName === 'path') {
- currentElement.setAttribute('d', this.__currentDefaultPath)
- } else {
- console.error(
- 'Attempted to apply path command to node',
- currentElement.nodeName
- )
- }
- }
-
- /**
- * Helper function to add path command
- * @private
- */
- ctx.prototype.__addPathCommand = function (command) {
- this.__currentDefaultPath += ' '
- this.__currentDefaultPath += command
- }
-
- /**
- * Adds the move command to the current path element,
- * if the currentPathElement is not empty create a new path element
- */
- ctx.prototype.moveTo = function (x, y) {
- if (this.__currentElement.nodeName !== 'path') {
- this.beginPath()
- }
-
- // creates a new subpath with the given point
- this.__currentPosition = { x: x, y: y }
- this.__addPathCommand(format('M {x} {y}', { x: x, y: y }))
- }
-
- /**
- * Closes the current path
- */
- ctx.prototype.closePath = function () {
- if (this.__currentDefaultPath) {
- this.__addPathCommand('Z')
- }
- }
-
- /**
- * Adds a line to command
- */
- ctx.prototype.lineTo = function (x, y) {
- this.__currentPosition = { x: x, y: y }
- if (this.__currentDefaultPath.indexOf('M') > -1) {
- this.__addPathCommand(format('L {x} {y}', { x: x, y: y }))
- } else {
- this.__addPathCommand(format('M {x} {y}', { x: x, y: y }))
- }
- }
-
- /**
- * Add a bezier command
- */
- ctx.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
- this.__currentPosition = { x: x, y: y }
- this.__addPathCommand(
- format('C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}', {
- cp1x: cp1x,
- cp1y: cp1y,
- cp2x: cp2x,
- cp2y: cp2y,
- x: x,
- y: y,
- })
- )
- }
-
- /**
- * Adds a quadratic curve to command
- */
- ctx.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
- this.__currentPosition = { x: x, y: y }
- this.__addPathCommand(
- format('Q {cpx} {cpy} {x} {y}', { cpx: cpx, cpy: cpy, x: x, y: y })
- )
- }
-
- /**
- * Return a new normalized vector of given vector
- */
- var normalize = function (vector) {
- var len = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1])
- return [vector[0] / len, vector[1] / len]
- }
-
- /**
- * Adds the arcTo to the current path
- *
- * @see http://www.w3.org/TR/2015/WD-2dcontext-20150514/#dom-context-2d-arcto
- */
- ctx.prototype.arcTo = function (x1, y1, x2, y2, radius) {
- // Let the point (x0, y0) be the last point in the subpath.
- var x0 = this.__currentPosition && this.__currentPosition.x
- var y0 = this.__currentPosition && this.__currentPosition.y
-
- // First ensure there is a subpath for (x1, y1).
- if (typeof x0 == 'undefined' || typeof y0 == 'undefined') {
- return
- }
-
- // Negative values for radius must cause the implementation to throw an IndexSizeError exception.
- if (radius < 0) {
- throw new Error(
- 'IndexSizeError: The radius provided (' +
- radius +
- ') is negative.'
- )
- }
-
- // If the point (x0, y0) is equal to the point (x1, y1),
- // or if the point (x1, y1) is equal to the point (x2, y2),
- // or if the radius radius is zero,
- // then the method must add the point (x1, y1) to the subpath,
- // and connect that point to the previous point (x0, y0) by a straight line.
- if (
- (x0 === x1 && y0 === y1) ||
- (x1 === x2 && y1 === y2) ||
- radius === 0
- ) {
- this.lineTo(x1, y1)
- return
- }
-
- // Otherwise, if the points (x0, y0), (x1, y1), and (x2, y2) all lie on a single straight line,
- // then the method must add the point (x1, y1) to the subpath,
- // and connect that point to the previous point (x0, y0) by a straight line.
- var unit_vec_p1_p0 = normalize([x0 - x1, y0 - y1])
- var unit_vec_p1_p2 = normalize([x2 - x1, y2 - y1])
- if (
- unit_vec_p1_p0[0] * unit_vec_p1_p2[1] ===
- unit_vec_p1_p0[1] * unit_vec_p1_p2[0]
- ) {
- this.lineTo(x1, y1)
- return
- }
-
- // Otherwise, let The Arc be the shortest arc given by circumference of the circle that has radius radius,
- // and that has one point tangent to the half-infinite line that crosses the point (x0, y0) and ends at the point (x1, y1),
- // and that has a different point tangent to the half-infinite line that ends at the point (x1, y1), and crosses the point (x2, y2).
- // The points at which this circle touches these two lines are called the start and end tangent points respectively.
-
- // note that both vectors are unit vectors, so the length is 1
- var cos =
- unit_vec_p1_p0[0] * unit_vec_p1_p2[0] +
- unit_vec_p1_p0[1] * unit_vec_p1_p2[1]
- var theta = Math.acos(Math.abs(cos))
-
- // Calculate origin
- var unit_vec_p1_origin = normalize([
- unit_vec_p1_p0[0] + unit_vec_p1_p2[0],
- unit_vec_p1_p0[1] + unit_vec_p1_p2[1],
- ])
- var len_p1_origin = radius / Math.sin(theta / 2)
- var x = x1 + len_p1_origin * unit_vec_p1_origin[0]
- var y = y1 + len_p1_origin * unit_vec_p1_origin[1]
-
- // Calculate start angle and end angle
- // rotate 90deg clockwise (note that y axis points to its down)
- var unit_vec_origin_start_tangent = [
- -unit_vec_p1_p0[1],
- unit_vec_p1_p0[0],
- ]
- // rotate 90deg counter clockwise (note that y axis points to its down)
- var unit_vec_origin_end_tangent = [
- unit_vec_p1_p2[1],
- -unit_vec_p1_p2[0],
- ]
- var getAngle = function (vector) {
- // get angle (clockwise) between vector and (1, 0)
- var x = vector[0]
- var y = vector[1]
- if (y >= 0) {
- // note that y axis points to its down
- return Math.acos(x)
- } else {
- return -Math.acos(x)
- }
- }
- var startAngle = getAngle(unit_vec_origin_start_tangent)
- var endAngle = getAngle(unit_vec_origin_end_tangent)
-
- // Connect the point (x0, y0) to the start tangent point by a straight line
- this.lineTo(
- x + unit_vec_origin_start_tangent[0] * radius,
- y + unit_vec_origin_start_tangent[1] * radius
- )
-
- // Connect the start tangent point to the end tangent point by arc
- // and adding the end tangent point to the subpath.
- this.arc(x, y, radius, startAngle, endAngle)
- }
-
- /**
- * Sets the stroke property on the current element
- */
- ctx.prototype.stroke = function () {
- if (this.__currentElement.nodeName === 'path') {
- this.__currentElement.setAttribute(
- 'paint-order',
- 'fill stroke markers'
- )
- }
- this.__applyCurrentDefaultPath()
- this.__applyStyleToCurrentElement('stroke')
- }
-
- /**
- * Sets fill properties on the current element
- */
- ctx.prototype.fill = function () {
- if (this.__currentElement.nodeName === 'path') {
- this.__currentElement.setAttribute(
- 'paint-order',
- 'stroke fill markers'
- )
- }
- this.__applyCurrentDefaultPath()
- this.__applyStyleToCurrentElement('fill')
- }
-
- /**
- * Adds a rectangle to the path.
- */
- ctx.prototype.rect = function (x, y, width, height) {
- if (this.__currentElement.nodeName !== 'path') {
- this.beginPath()
- }
- this.moveTo(x, y)
- this.lineTo(x + width, y)
- this.lineTo(x + width, y + height)
- this.lineTo(x, y + height)
- this.lineTo(x, y)
- this.closePath()
- }
-
- /**
- * adds a rectangle element
- */
- ctx.prototype.fillRect = function (x, y, width, height) {
- var rect, parent
- rect = this.__createElement(
- 'rect',
- {
- x: x,
- y: y,
- width: width,
- height: height,
- },
- true
- )
- parent = this.__closestGroupOrSvg()
- parent.appendChild(rect)
- this.__currentElement = rect
- this.__applyStyleToCurrentElement('fill')
- }
-
- /**
- * Draws a rectangle with no fill
- * @param x
- * @param y
- * @param width
- * @param height
- */
- ctx.prototype.strokeRect = function (x, y, width, height) {
- var rect, parent
- rect = this.__createElement(
- 'rect',
- {
- x: x,
- y: y,
- width: width,
- height: height,
- },
- true
- )
- parent = this.__closestGroupOrSvg()
- parent.appendChild(rect)
- this.__currentElement = rect
- this.__applyStyleToCurrentElement('stroke')
- }
-
- /**
- * Clear entire canvas:
- * 1. save current transforms
- * 2. remove all the childNodes of the root g element
- */
- ctx.prototype.__clearCanvas = function () {
- var current = this.__closestGroupOrSvg(),
- transform = current.getAttribute('transform')
- var rootGroup = this.__root.childNodes[1]
- var childNodes = rootGroup.childNodes
- for (var i = childNodes.length - 1; i >= 0; i--) {
- if (childNodes[i]) {
- rootGroup.removeChild(childNodes[i])
- }
- }
- this.__currentElement = rootGroup
- //reset __groupStack as all the child group nodes are all removed.
- this.__groupStack = []
- if (transform) {
- this.__addTransform(transform)
- }
- }
-
- /**
- * "Clears" a canvas by just drawing a white rectangle in the current group.
- */
- ctx.prototype.clearRect = function (x, y, width, height) {
- //clear entire canvas
- if (
- x === 0 &&
- y === 0 &&
- width === this.width &&
- height === this.height
- ) {
- this.__clearCanvas()
- return
- }
- var rect,
- parent = this.__closestGroupOrSvg()
- rect = this.__createElement(
- 'rect',
- {
- x: x,
- y: y,
- width: width,
- height: height,
- fill: '#FFFFFF',
- },
- true
- )
- parent.appendChild(rect)
- }
-
- /**
- * Adds a linear gradient to a defs tag.
- * Returns a canvas gradient object that has a reference to it's parent def
- */
- ctx.prototype.createLinearGradient = function (x1, y1, x2, y2) {
- var grad = this.__createElement(
- 'linearGradient',
- {
- id: randomString(this.__ids),
- x1: x1 + 'px',
- x2: x2 + 'px',
- y1: y1 + 'px',
- y2: y2 + 'px',
- gradientUnits: 'userSpaceOnUse',
- },
- false
- )
- this.__defs.appendChild(grad)
- return new CanvasGradient(grad, this)
- }
-
- /**
- * Adds a radial gradient to a defs tag.
- * Returns a canvas gradient object that has a reference to it's parent def
- */
- ctx.prototype.createRadialGradient = function (x0, y0, r0, x1, y1, r1) {
- var grad = this.__createElement(
- 'radialGradient',
- {
- id: randomString(this.__ids),
- cx: x1 + 'px',
- cy: y1 + 'px',
- r: r1 + 'px',
- fx: x0 + 'px',
- fy: y0 + 'px',
- gradientUnits: 'userSpaceOnUse',
- },
- false
- )
- this.__defs.appendChild(grad)
- return new CanvasGradient(grad, this)
- }
-
- /**
- * Parses the font string and returns svg mapping
- * @private
- */
- ctx.prototype.__parseFont = function () {
- var regex =
- /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\'\"\sa-z0-9]+?)\s*$/i
- var fontPart = regex.exec(this.font)
- var data = {
- style: fontPart[1] || 'normal',
- size: fontPart[4] || '10px',
- family: fontPart[6] || 'sans-serif',
- weight: fontPart[3] || 'normal',
- decoration: fontPart[2] || 'normal',
- href: null,
- }
-
- //canvas doesn't support underline natively, but we can pass this attribute
- if (this.__fontUnderline === 'underline') {
- data.decoration = 'underline'
- }
-
- //canvas also doesn't support linking, but we can pass this as well
- if (this.__fontHref) {
- data.href = this.__fontHref
- }
-
- return data
- }
-
- /**
- * Helper to link text fragments
- * @param font
- * @param element
- * @return {*}
- * @private
- */
- ctx.prototype.__wrapTextLink = function (font, element) {
- if (font.href) {
- var a = this.__createElement('a')
- a.setAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'xlink:href',
- font.href
- )
- a.appendChild(element)
- return a
- }
- return element
- }
-
- /**
- * Fills or strokes text
- * @param text
- * @param x
- * @param y
- * @param action - stroke or fill
- * @private
- */
- ctx.prototype.__applyText = function (text, x, y, action) {
- var font = this.__parseFont(),
- parent = this.__closestGroupOrSvg(),
- textElement = this.__createElement(
- 'text',
- {
- 'font-family': font.family,
- 'font-size': font.size,
- 'font-style': font.style,
- 'font-weight': font.weight,
- 'text-decoration': font.decoration,
- x: x,
- y: y,
- 'text-anchor': getTextAnchor(this.textAlign),
- 'dominant-baseline': getDominantBaseline(this.textBaseline),
- },
- true
- )
-
- textElement.appendChild(this.__document.createTextNode(text))
- this.__currentElement = textElement
- this.__applyStyleToCurrentElement(action)
- parent.appendChild(this.__wrapTextLink(font, textElement))
- }
-
- /**
- * Creates a text element
- * @param text
- * @param x
- * @param y
- */
- ctx.prototype.fillText = function (text, x, y) {
- this.__applyText(text, x, y, 'fill')
- }
-
- /**
- * Strokes text
- * @param text
- * @param x
- * @param y
- */
- ctx.prototype.strokeText = function (text, x, y) {
- this.__applyText(text, x, y, 'stroke')
- }
-
- /**
- * No need to implement this for svg.
- * @param text
- * @return {TextMetrics}
- */
- ctx.prototype.measureText = function (text) {
- this.__ctx.font = this.font
- return this.__ctx.measureText(text)
- }
-
- /**
- * Arc command!
- */
- ctx.prototype.arc = function (
- x,
- y,
- radius,
- startAngle,
- endAngle,
- counterClockwise
- ) {
- // in canvas no circle is drawn if no angle is provided.
- if (startAngle === endAngle) {
- return
- }
- startAngle = startAngle % (2 * Math.PI)
- endAngle = endAngle % (2 * Math.PI)
- if (startAngle === endAngle) {
- //circle time! subtract some of the angle so svg is happy (svg elliptical arc can't draw a full circle)
- endAngle =
- (endAngle + 2 * Math.PI - 0.001 * (counterClockwise ? -1 : 1)) %
- (2 * Math.PI)
- }
- var endX = x + radius * Math.cos(endAngle),
- endY = y + radius * Math.sin(endAngle),
- startX = x + radius * Math.cos(startAngle),
- startY = y + radius * Math.sin(startAngle),
- sweepFlag = counterClockwise ? 0 : 1,
- largeArcFlag = 0,
- diff = endAngle - startAngle
-
- // https://github.com/gliffy/canvas2svg/issues/4
- if (diff < 0) {
- diff += 2 * Math.PI
- }
-
- if (counterClockwise) {
- largeArcFlag = diff > Math.PI ? 0 : 1
- } else {
- largeArcFlag = diff > Math.PI ? 1 : 0
- }
-
- this.lineTo(startX, startY)
- this.__addPathCommand(
- format(
- 'A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}',
- {
- rx: radius,
- ry: radius,
- xAxisRotation: 0,
- largeArcFlag: largeArcFlag,
- sweepFlag: sweepFlag,
- endX: endX,
- endY: endY,
- }
- )
- )
-
- this.__currentPosition = { x: endX, y: endY }
- }
-
- /**
- * Generates a ClipPath from the clip command.
- */
- ctx.prototype.clip = function () {
- var group = this.__closestGroupOrSvg(),
- clipPath = this.__createElement('clipPath'),
- id = randomString(this.__ids),
- newGroup = this.__createElement('g')
-
- this.__applyCurrentDefaultPath()
- group.removeChild(this.__currentElement)
- clipPath.setAttribute('id', id)
- clipPath.appendChild(this.__currentElement)
-
- this.__defs.appendChild(clipPath)
-
- //set the clip path to this group
- group.setAttribute('clip-path', format('url(#{id})', { id: id }))
-
- //clip paths can be scaled and transformed, we need to add another wrapper group to avoid later transformations
- // to this path
- group.appendChild(newGroup)
-
- this.__currentElement = newGroup
- }
-
- /**
- * Draws a canvas, image or mock context to this canvas.
- * Note that all svg dom manipulation uses node.childNodes rather than node.children for IE support.
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage
- */
- ctx.prototype.drawImage = function () {
- //convert arguments to a real array
- var args = Array.prototype.slice.call(arguments),
- image = args[0],
- dx,
- dy,
- dw,
- dh,
- sx = 0,
- sy = 0,
- sw,
- sh,
- parent,
- svg,
- defs,
- group,
- currentElement,
- svgImage,
- canvas,
- context,
- id
-
- if (args.length === 3) {
- dx = args[1]
- dy = args[2]
- sw = image.width
- sh = image.height
- dw = sw
- dh = sh
- } else if (args.length === 5) {
- dx = args[1]
- dy = args[2]
- dw = args[3]
- dh = args[4]
- sw = image.width
- sh = image.height
- } else if (args.length === 9) {
- sx = args[1]
- sy = args[2]
- sw = args[3]
- sh = args[4]
- dx = args[5]
- dy = args[6]
- dw = args[7]
- dh = args[8]
- } else {
- throw new Error(
- 'Invalid number of arguments passed to drawImage: ' +
- arguments.length
- )
- }
-
- parent = this.__closestGroupOrSvg()
- currentElement = this.__currentElement
- var translateDirective = 'translate(' + dx + ', ' + dy + ')'
- if (image instanceof ctx) {
- //canvas2svg mock canvas context. In the future we may want to clone nodes instead.
- //also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context.
- svg = image.getSvg().cloneNode(true)
- if (svg.childNodes && svg.childNodes.length > 1) {
- defs = svg.childNodes[0]
- while (defs.childNodes.length) {
- id = defs.childNodes[0].getAttribute('id')
- this.__ids[id] = id
- this.__defs.appendChild(defs.childNodes[0])
- }
- group = svg.childNodes[1]
- if (group) {
- //save original transform
- var originTransform = group.getAttribute('transform')
- var transformDirective
- if (originTransform) {
- transformDirective =
- originTransform + ' ' + translateDirective
- } else {
- transformDirective = translateDirective
- }
- group.setAttribute('transform', transformDirective)
- parent.appendChild(group)
- }
- }
- } else if (image.nodeName === 'CANVAS' || image.nodeName === 'IMG') {
- //canvas or image
- svgImage = this.__createElement('image')
- svgImage.setAttribute('width', dw)
- svgImage.setAttribute('height', dh)
- svgImage.setAttribute('preserveAspectRatio', 'none')
-
- if (sx || sy || sw !== image.width || sh !== image.height) {
- //crop the image using a temporary canvas
- canvas = this.__document.createElement('canvas')
- canvas.width = dw
- canvas.height = dh
- context = canvas.getContext('2d')
- context.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh)
- image = canvas
- }
- svgImage.setAttribute('transform', translateDirective)
- svgImage.setAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'xlink:href',
- image.nodeName === 'CANVAS'
- ? image.toDataURL()
- : image.getAttribute('src')
- )
- parent.appendChild(svgImage)
- }
- }
-
- /**
- * Generates a pattern tag
- */
- ctx.prototype.createPattern = function (image, repetition) {
- var pattern = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'pattern'
- ),
- id = randomString(this.__ids),
- img
- pattern.setAttribute('id', id)
- pattern.setAttribute('width', image.width)
- pattern.setAttribute('height', image.height)
- if (image.nodeName === 'CANVAS' || image.nodeName === 'IMG') {
- img = this.__document.createElementNS(
- 'http://www.w3.org/2000/svg',
- 'image'
- )
- img.setAttribute('width', image.width)
- img.setAttribute('height', image.height)
- img.setAttributeNS(
- 'http://www.w3.org/1999/xlink',
- 'xlink:href',
- image.nodeName === 'CANVAS'
- ? image.toDataURL()
- : image.getAttribute('src')
- )
- pattern.appendChild(img)
- this.__defs.appendChild(pattern)
- } else if (image instanceof ctx) {
- pattern.appendChild(image.__root.childNodes[1])
- this.__defs.appendChild(pattern)
- }
- return new CanvasPattern(pattern, this)
- }
-
- ctx.prototype.setLineDash = function (dashArray) {
- if (dashArray && dashArray.length > 0) {
- this.lineDash = dashArray.join(',')
- } else {
- this.lineDash = null
- }
- }
-
- /**
- * Not yet implemented
- */
- ctx.prototype.drawFocusRing = function () {}
- ctx.prototype.createImageData = function () {}
- ctx.prototype.getImageData = function () {}
- ctx.prototype.putImageData = function () {}
- ctx.prototype.globalCompositeOperation = function () {}
- ctx.prototype.setTransform = function () {}
-
- //add options for alternative namespace
- if (typeof window === 'object') {
- window.C2S = ctx
- }
-
- // CommonJS/Browserify
- if (typeof module === 'object' && typeof module.exports === 'object') {
- module.exports = ctx
- }
-})()
diff --git a/v1/src/store/SimulatorStore/actions.ts b/v1/src/store/SimulatorStore/actions.ts
index e127bc5f..f5dee32b 100644
--- a/v1/src/store/SimulatorStore/actions.ts
+++ b/v1/src/store/SimulatorStore/actions.ts
@@ -5,12 +5,28 @@ export const useActions = defineStore('simulatorStore.actions', () => {
const state = useState()
function showTitle(): void {
- console.log(state.title)
+ }
+
+ function showMessage(message: string, type: 'error' | 'success') {
+ if (type === 'error') {
+ state.errorMessages.push(message)
+ } else {
+ state.successMessages.push(message)
+ }
+
+ setTimeout(() => {
+ if (type === 'error') {
+ state.errorMessages.shift()
+ } else {
+ state.successMessages.shift()
+ }
+ }, type === 'error' ? 1500 : 2500)
}
// Note you are free to define as many internal functions as you want.
// You only expose the functions that are returned.
return {
showTitle,
+ showMessage,
}
})
diff --git a/v1/src/store/SimulatorStore/state.ts b/v1/src/store/SimulatorStore/state.ts
index 1bad89ad..cc57592f 100644
--- a/v1/src/store/SimulatorStore/state.ts
+++ b/v1/src/store/SimulatorStore/state.ts
@@ -3,16 +3,20 @@ import { defineStore } from 'pinia'
// use camel case variable names
export interface State {
title: string
- activeCircuit:
- | Object
- | {
- id: number | string
- name: string
- }
- circuit_list: Array