digsim-logic-simulator 0.4.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of digsim-logic-simulator might be problematic. Click here for more details.

Files changed (122) hide show
  1. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/LICENSE.md +1 -1
  2. {digsim-logic-simulator-0.4.0/src/digsim_logic_simulator.egg-info → digsim_logic_simulator-0.7.0}/PKG-INFO +17 -10
  3. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/README.md +5 -0
  4. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/pyproject.toml +10 -9
  5. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui/_top_bar.py +1 -1
  6. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_component_object.py +7 -4
  7. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_hexdigit_object.py +1 -1
  8. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/model/_model.py +13 -14
  9. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/model/_model_components.py +12 -15
  10. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/model/_model_objects.py +29 -23
  11. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/model/_model_settings.py +1 -5
  12. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/model/_model_shortcuts.py +3 -3
  13. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/settings/_component_settings.py +4 -4
  14. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/_circuit.py +20 -60
  15. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_bus_bits.py +2 -2
  16. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_buzzer.py +1 -1
  17. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_clock.py +1 -1
  18. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_dip_switch.py +1 -1
  19. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_gates.py +5 -5
  20. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_hexdigit.py +2 -2
  21. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_label_wire.py +3 -3
  22. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_logic_analyzer.py +1 -1
  23. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_note.py +1 -1
  24. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_static_value.py +1 -1
  25. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/atoms/_component.py +0 -39
  26. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/atoms/_port.py +5 -14
  27. digsim_logic_simulator-0.7.0/src/digsim/storage_model/__init__.py +7 -0
  28. digsim_logic_simulator-0.7.0/src/digsim/storage_model/_app.py +53 -0
  29. digsim_logic_simulator-0.7.0/src/digsim/storage_model/_circuit.py +118 -0
  30. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/utils/_yosys_netlist.py +1 -1
  31. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0/src/digsim_logic_simulator.egg-info}/PKG-INFO +17 -10
  32. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim_logic_simulator.egg-info/SOURCES.txt +3 -0
  33. digsim_logic_simulator-0.7.0/src/digsim_logic_simulator.egg-info/requires.txt +6 -0
  34. digsim-logic-simulator-0.4.0/src/digsim_logic_simulator.egg-info/requires.txt +0 -5
  35. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/MANIFEST.in +0 -0
  36. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/setup.cfg +0 -0
  37. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/__init__.py +0 -0
  38. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/__main__.py +0 -0
  39. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui/__init__.py +0 -0
  40. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui/_circuit_area.py +0 -0
  41. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui/_component_selection.py +0 -0
  42. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui/_main_window.py +0 -0
  43. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui/_utils.py +0 -0
  44. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui/_warning_dialog.py +0 -0
  45. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/__init__.py +0 -0
  46. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_bus_bit_object.py +0 -0
  47. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_buzzer_object.py +0 -0
  48. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_component_context_menu.py +0 -0
  49. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_component_port_item.py +0 -0
  50. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_dip_switch_object.py +0 -0
  51. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_gui_note_object.py +0 -0
  52. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_gui_object_factory.py +0 -0
  53. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_image_objects.py +0 -0
  54. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_label_object.py +0 -0
  55. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_logic_analyzer_object.py +0 -0
  56. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_seven_segment_object.py +0 -0
  57. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_shortcut_objects.py +0 -0
  58. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/_yosys_object.py +0 -0
  59. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/AND.png +0 -0
  60. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/Analyzer.png +0 -0
  61. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/BUF.png +0 -0
  62. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/Buzzer.png +0 -0
  63. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/Clock.png +0 -0
  64. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/DFF.png +0 -0
  65. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/DIP_SWITCH.png +0 -0
  66. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/FlipFlop.png +0 -0
  67. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/IC.png +0 -0
  68. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/LED_OFF.png +0 -0
  69. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/LED_ON.png +0 -0
  70. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/MUX.png +0 -0
  71. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/NAND.png +0 -0
  72. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/NOR.png +0 -0
  73. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/NOT.png +0 -0
  74. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/ONE.png +0 -0
  75. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/OR.png +0 -0
  76. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/PB.png +0 -0
  77. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/Switch_OFF.png +0 -0
  78. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/Switch_ON.png +0 -0
  79. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/XNOR.png +0 -0
  80. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/XOR.png +0 -0
  81. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/YOSYS.png +0 -0
  82. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/gui_objects/images/ZERO.png +0 -0
  83. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/images/app_icon.png +0 -0
  84. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/model/__init__.py +0 -0
  85. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/model/_model_new_wire.py +0 -0
  86. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/settings/__init__.py +0 -0
  87. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/settings/_gui_settings.py +0 -0
  88. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/app/settings/_shortcut_dialog.py +0 -0
  89. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/__init__.py +0 -0
  90. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/_waves_writer.py +0 -0
  91. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/__init__.py +0 -0
  92. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_button.py +0 -0
  93. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_flip_flops.py +0 -0
  94. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_ic.py +0 -0
  95. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_led.py +0 -0
  96. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_mem64kbyte.py +0 -0
  97. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_memstdout.py +0 -0
  98. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_on_off_switch.py +0 -0
  99. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_seven_segment.py +0 -0
  100. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_static_level.py +0 -0
  101. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_yosys_atoms.py +0 -0
  102. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/_yosys_component.py +0 -0
  103. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/atoms/__init__.py +0 -0
  104. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/atoms/_digsim_exception.py +0 -0
  105. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/ic/74162.json +0 -0
  106. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/circuit/components/ic/7448.json +0 -0
  107. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/synth/__init__.py +0 -0
  108. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/synth/__main__.py +0 -0
  109. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/synth/_synthesis.py +0 -0
  110. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim/utils/__init__.py +0 -0
  111. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim_logic_simulator.egg-info/dependency_links.txt +0 -0
  112. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/src/digsim_logic_simulator.egg-info/top_level.txt +0 -0
  113. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_gates.py +0 -0
  114. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_aldff.py +0 -0
  115. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_dff.py +0 -0
  116. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_dlatch.py +0 -0
  117. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_gates.py +0 -0
  118. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_latch.py +0 -0
  119. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_netlist.py +0 -0
  120. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_sdff.py +0 -0
  121. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_sr.py +0 -0
  122. {digsim-logic-simulator-0.4.0 → digsim_logic_simulator-0.7.0}/tests/test_yosys_synth.py +0 -0
@@ -1,6 +1,6 @@
1
1
  The Clear BSD License
2
2
 
3
- Copyright (c) 2023, Fredrik Andersson
3
+ Copyright (c) 2023-2024, Fredrik Andersson
4
4
  All rights reserved.
5
5
 
6
6
  Redistribution and use in source and binary forms, with or without
@@ -1,12 +1,12 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: digsim-logic-simulator
3
- Version: 0.4.0
3
+ Version: 0.7.0
4
4
  Summary: Interactive Digital Logic Simulator
5
5
  Author-email: Fredrik Andersson <freand@gmail.com>
6
6
  Maintainer-email: Fredrik Andersson <freand@gmail.com>
7
7
  License: The Clear BSD License
8
8
 
9
- Copyright (c) 2023, Fredrik Andersson
9
+ Copyright (c) 2023-2024, Fredrik Andersson
10
10
  All rights reserved.
11
11
 
12
12
  Redistribution and use in source and binary forms, with or without
@@ -41,20 +41,22 @@ Project-URL: homepage, https://github.com/freand76/digsim
41
41
  Keywords: educational,simulation,digital
42
42
  Classifier: Development Status :: 5 - Production/Stable
43
43
  Classifier: Programming Language :: Python :: 3
44
- Classifier: Programming Language :: Python :: 3.8
45
44
  Classifier: Programming Language :: Python :: 3.9
46
45
  Classifier: Programming Language :: Python :: 3.10
47
46
  Classifier: Programming Language :: Python :: 3.11
48
47
  Classifier: Programming Language :: Python :: 3.12
48
+ Classifier: Programming Language :: Python :: 3.13
49
49
  Classifier: Programming Language :: Python :: 3 :: Only
50
- Requires-Python: >=3.8
50
+ Requires-Python: >=3.9
51
51
  Description-Content-Type: text/markdown
52
52
  License-File: LICENSE.md
53
- Requires-Dist: pyvcd>=0.3.0
54
- Requires-Dist: pyside6>=6.6.0
55
- Requires-Dist: pexpect==4.8.0
56
- Requires-Dist: qtawesome
57
- Requires-Dist: yowasp-yosys==0.36.0.8.post620
53
+ Requires-Dist: pyvcd>=0.4.1
54
+ Requires-Dist: pyside6>=6.9.0
55
+ Requires-Dist: pexpect==4.9.0
56
+ Requires-Dist: pydantic==2.11.4
57
+ Requires-Dist: qtawesome==1.4.0
58
+ Requires-Dist: yowasp-yosys==0.53.0.0.post912
59
+ Dynamic: license-file
58
60
 
59
61
  # DigSim - Interactive Digital Logic Simulator
60
62
 
@@ -135,6 +137,11 @@ Then the following package must be installed:
135
137
  > gtkwave sr.vcd
136
138
  ```
137
139
 
140
+ ### Examples of writing pytest/python test benches for synthesized verilog code
141
+ ```
142
+ > pytest examples/pytest_tb
143
+ ```
144
+
138
145
  ## Yosys synthesis helper tool
139
146
 
140
147
  ```
@@ -77,6 +77,11 @@ Then the following package must be installed:
77
77
  > gtkwave sr.vcd
78
78
  ```
79
79
 
80
+ ### Examples of writing pytest/python test benches for synthesized verilog code
81
+ ```
82
+ > pytest examples/pytest_tb
83
+ ```
84
+
80
85
  ## Yosys synthesis helper tool
81
86
 
82
87
  ```
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "digsim-logic-simulator"
7
7
  description = "Interactive Digital Logic Simulator"
8
- version = "0.4.0"
8
+ version = "0.7.0"
9
9
  authors = [{name = "Fredrik Andersson", email = "freand@gmail.com"}]
10
10
  maintainers = [{name = "Fredrik Andersson", email = "freand@gmail.com"}]
11
11
  readme = "README.md"
@@ -15,28 +15,29 @@ urls = { homepage = "https://github.com/freand76/digsim" }
15
15
  classifiers = [
16
16
  "Development Status :: 5 - Production/Stable",
17
17
  "Programming Language :: Python :: 3",
18
- "Programming Language :: Python :: 3.8",
19
18
  "Programming Language :: Python :: 3.9",
20
19
  "Programming Language :: Python :: 3.10",
21
20
  "Programming Language :: Python :: 3.11",
22
21
  "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
23
  "Programming Language :: Python :: 3 :: Only",
24
24
  ]
25
25
 
26
- requires-python = ">=3.8"
26
+ requires-python = ">=3.9"
27
27
  dependencies = [
28
- "pyvcd>=0.3.0",
29
- "pyside6>=6.6.0",
30
- "pexpect==4.8.0",
31
- "qtawesome",
32
- "yowasp-yosys==0.36.0.8.post620",
28
+ "pyvcd>=0.4.1",
29
+ "pyside6>=6.9.0",
30
+ "pexpect==4.9.0",
31
+ "pydantic==2.11.4",
32
+ "qtawesome==1.4.0",
33
+ "yowasp-yosys==0.53.0.0.post912",
33
34
  ]
34
35
 
35
36
  keywords = ["educational", "simulation", "digital"]
36
37
 
37
38
  [tool.ruff]
38
39
  line-length = 99
39
- target-version = "py38"
40
+ target-version = "py39"
40
41
 
41
42
  show-fixes = true
42
43
  output-format = "full"
@@ -259,7 +259,7 @@ class LoadSaveWidget(QFrame):
259
259
  self._redo_button.setToolTip("Redo")
260
260
  self.layout().addWidget(self._redo_button)
261
261
  self._settings_button = QPushButton("", self)
262
- self._settings_button.setIcon(qta.icon("fa.cog"))
262
+ self._settings_button.setIcon(qta.icon("mdi.cog"))
263
263
  self._settings_button.clicked.connect(self._settings_dialog)
264
264
  self._settings_button.setToolTip("Settings")
265
265
  self.layout().addWidget(self._settings_button)
@@ -9,6 +9,8 @@ from PySide6.QtCore import QPoint, QRect, QSize, Qt
9
9
  from PySide6.QtGui import QFont, QFontMetrics, QPen
10
10
  from PySide6.QtWidgets import QGraphicsItem, QGraphicsRectItem
11
11
 
12
+ from digsim.storage_model import GuiPositionDataClass
13
+
12
14
  from ._component_context_menu import ComponentContextMenu
13
15
  from ._component_port_item import PortGraphicsItem
14
16
 
@@ -149,7 +151,7 @@ class ComponentObject(QGraphicsRectItem):
149
151
  if port.width == 1:
150
152
  self._port_dict[port]["name"] = port.name()
151
153
  else:
152
- self._port_dict[port]["name"] = f"{port.name()}[{port.width-1}:0]"
154
+ self._port_dict[port]["name"] = f"{port.name()}[{port.width - 1}:0]"
153
155
  item = PortGraphicsItem(self._app_model, self, port)
154
156
  self._port_dict[port]["item"] = item
155
157
  self.update_ports()
@@ -365,6 +367,7 @@ class ComponentObject(QGraphicsRectItem):
365
367
  """Set zlevel"""
366
368
  self.setZValue(level)
367
369
 
368
- def to_dict(self):
369
- """Return position as dict"""
370
- return {"x": int(self._save_pos.x()), "y": int(self._save_pos.y()), "z": self.zlevel}
370
+ def to_gui_dataclass(self):
371
+ return GuiPositionDataClass(
372
+ x=int(self._save_pos.x()), y=int(self._save_pos.y()), z=int(self.zlevel)
373
+ )
@@ -22,7 +22,7 @@ class HexDigitObject(SevenSegmentObject):
22
22
  def setup_size(self):
23
23
  """Setup the size of the component"""
24
24
  self.digits = self.component.get_digits()
25
- str_pixels_w, _ = self.get_string_metrics(f"val[{4*self.digits-1}:0]")
25
+ str_pixels_w, _ = self.get_string_metrics(f"val[{4 * self.digits - 1}:0]")
26
26
  self.digit_left = self.inport_x_pos() + str_pixels_w + self.PORT_TO_RECT_MARGIN
27
27
  self.digit_top = self.RECT_TO_DIGIT_RECT_MARGIN
28
28
  self.width = (
@@ -3,7 +3,6 @@
3
3
 
4
4
  """An application model for a GUI simulated circuit"""
5
5
 
6
- import json
7
6
  import queue
8
7
  import time
9
8
  from pathlib import Path
@@ -12,6 +11,7 @@ from PySide6.QtCore import QThread, Signal
12
11
 
13
12
  from digsim.app.gui_objects import ComponentObject
14
13
  from digsim.circuit.components.atoms import Component
14
+ from digsim.storage_model import AppFileDataClass
15
15
 
16
16
  from ._model_objects import ModelObjects
17
17
  from ._model_settings import ModelSettings
@@ -155,28 +155,27 @@ class AppModel(QThread):
155
155
  def save_circuit(self, path):
156
156
  """Save the circuit with GUI information"""
157
157
  circuit_folder = str(Path(path).parent)
158
- circuit_dict = self.objects.circuit_to_dict(circuit_folder)
159
- shortcuts_dict = self.shortcuts.to_dict()
160
- circuit_dict.update(shortcuts_dict)
161
- settings_dict = self.settings.to_dict()
162
- circuit_dict.update(settings_dict)
163
- json_object = json.dumps(circuit_dict, indent=4)
164
- with open(path, mode="w", encoding="utf-8") as json_file:
165
- json_file.write(json_object)
158
+ model_dataclass = self.objects.circuit_to_model(circuit_folder)
159
+ appfile_dataclass = AppFileDataClass(
160
+ circuit=model_dataclass.circuit,
161
+ gui=model_dataclass.gui,
162
+ shortcuts=self.shortcuts.to_dict(),
163
+ settings=self.settings.get_all(),
164
+ )
165
+ appfile_dataclass.save(path)
166
166
  self._changed = False
167
167
  self.sig_control_notify.emit()
168
168
 
169
169
  def load_circuit(self, path):
170
170
  """Load a circuit with GUI information"""
171
171
  self._model_clear()
172
- with open(path, mode="r", encoding="utf-8") as json_file:
173
- circuit_dict = json.load(json_file)
172
+ app_file_dc = AppFileDataClass.load(path)
174
173
  circuit_folder = str(Path(path).parent)
175
174
  if len(circuit_folder) == 0:
176
175
  circuit_folder = "."
177
- exception_str_list = self.objects.dict_to_circuit(circuit_dict, circuit_folder)
178
- self.shortcuts.from_dict(circuit_dict)
179
- self.settings.from_dict(circuit_dict)
176
+ exception_str_list = self.objects.model_to_circuit(app_file_dc, circuit_folder)
177
+ self.shortcuts.from_dict(app_file_dc.shortcuts)
178
+ self.settings.from_dict(app_file_dc.settings)
180
179
  self.model_init()
181
180
  self._changed = False
182
181
  self.objects.reset_undo_stack()
@@ -1,4 +1,4 @@
1
- # Copyright (c) Fredrik Andersson, 2023
1
+ # Copyright (c) Fredrik Andersson, 2023-2024
2
2
  # All rights reserved
3
3
 
4
4
  """Handle component objects in the model"""
@@ -7,6 +7,7 @@ import digsim.circuit.components
7
7
  from digsim.app.gui_objects import ComponentObject
8
8
  from digsim.circuit.components import Buzzer
9
9
  from digsim.circuit.components.atoms import CallbackComponent
10
+ from digsim.storage_model import GuiPositionDataClass
10
11
 
11
12
 
12
13
  class ModelComponents:
@@ -149,20 +150,16 @@ class ModelComponents:
149
150
  self._circuit.delete_component(component_object.component)
150
151
  self._app_model.sig_delete_component.emit(component_object)
151
152
 
152
- def create_from_dict(self, circuit_dict):
153
+ def add_gui_positions(self, gui_dc_dict):
153
154
  """Create model components from circuit_dict"""
154
155
  for comp in self._circuit.get_toplevel_components():
155
- gui_dict = circuit_dict.get("gui", {})
156
- component_dict = gui_dict.get(comp.name(), {})
157
- x = component_dict.get("x", 100)
158
- y = component_dict.get("y", 100)
159
- z = component_dict.get("z", 0)
160
- component_object = self._add_object(comp, x, y)
161
- component_object.zlevel = z
162
-
163
- def get_circuit_dict(self):
164
- """Create model components dict"""
165
- model_components_dict = {"gui": {}}
156
+ gui_dc = gui_dc_dict.get(comp.name(), GuiPositionDataClass())
157
+ component_object = self._add_object(comp, gui_dc.x, gui_dc.y)
158
+ component_object.zlevel = gui_dc.z
159
+
160
+ def get_gui_dict(self):
161
+ """Return gui dict from component objects"""
162
+ gui_dict = {}
166
163
  for comp, comp_object in self.get_dict().items():
167
- model_components_dict["gui"][comp.name()] = comp_object.to_dict()
168
- return model_components_dict
164
+ gui_dict[comp.name()] = comp_object.to_gui_dataclass()
165
+ return gui_dict
@@ -5,6 +5,7 @@
5
5
 
6
6
  from digsim.circuit import Circuit
7
7
  from digsim.circuit.components.atoms import DigsimException
8
+ from digsim.storage_model import AppFileDataClass, ModelDataClass
8
9
 
9
10
  from ._model_components import ModelComponents
10
11
  from ._model_new_wire import NewWire
@@ -72,32 +73,37 @@ class ModelObjects:
72
73
  self._app_model.model_changed()
73
74
  self._app_model.sig_delete_wires.emit()
74
75
 
75
- def circuit_to_dict(self, circuit_folder):
76
- """Convert circuit and objects to dict"""
77
- circuit_dict = self.circuit.to_dict(circuit_folder)
78
- model_components_dict = self.components.get_circuit_dict()
79
- circuit_dict.update(model_components_dict)
80
- return circuit_dict
76
+ def model_to_circuit(self, model_dc, circuit_folder):
77
+ if isinstance(model_dc, AppFileDataClass):
78
+ # Loaded model
79
+ dc = ModelDataClass.from_app_file_dc(model_dc)
80
+ else:
81
+ dc = model_dc
81
82
 
82
- def dict_to_circuit(self, circuit_dict, circuit_folder):
83
- """Convert dict to circuit and objects"""
84
- exception_str_list = []
85
83
  try:
86
- exception_str_list = self.circuit.from_dict(
87
- circuit_dict, circuit_folder, component_exceptions=False, connect_exceptions=False
84
+ # Create circuit
85
+ exception_str_list = self.circuit.from_dataclass(
86
+ dc.circuit,
87
+ circuit_folder,
88
+ component_exceptions=False,
89
+ connect_exceptions=False,
88
90
  )
91
+ # Add component positions
92
+ self.components.add_gui_positions(dc.gui)
89
93
  except DigsimException as exc:
90
94
  self.sig_error.emit(f"Circuit error: {str(exc)}")
91
95
  return exception_str_list
92
-
93
- # Create GUI components
94
- self.components.create_from_dict(circuit_dict)
95
-
96
96
  return exception_str_list
97
97
 
98
- def _restore_state(self, state):
98
+ def circuit_to_model(self, circuit_folder):
99
+ model_dc = ModelDataClass(
100
+ circuit=self.circuit.to_dataclass(circuit_folder), gui=self.components.get_gui_dict()
101
+ )
102
+ return model_dc
103
+
104
+ def _restore_state(self, model_dc):
99
105
  self.clear()
100
- exception_str_list = self.dict_to_circuit(state, "/")
106
+ exception_str_list = self.model_to_circuit(model_dc, None)
101
107
  self._app_model.model_init()
102
108
  self._app_model.model_changed()
103
109
  if len(exception_str_list) > 0:
@@ -111,7 +117,7 @@ class ModelObjects:
111
117
 
112
118
  def push_undo_state(self, clear_redo_stack=True):
113
119
  """Push undo state to stack"""
114
- self._undo_stack.append(self.circuit_to_dict("/"))
120
+ self._undo_stack.append(self.circuit_to_model("/"))
115
121
  if clear_redo_stack:
116
122
  self._redo_stack = []
117
123
  self._app_model.sig_control_notify.emit()
@@ -124,14 +130,14 @@ class ModelObjects:
124
130
 
125
131
  def push_redo_state(self):
126
132
  """Push redo state to stack"""
127
- self._redo_stack.append(self.circuit_to_dict("/"))
133
+ self._redo_stack.append(self.circuit_to_model("/"))
128
134
 
129
135
  def undo(self):
130
136
  """Undo to last saved state"""
131
137
  if len(self._undo_stack) > 0:
132
138
  self.push_redo_state()
133
- state = self._undo_stack.pop()
134
- self._restore_state(state)
139
+ model_dc = self._undo_stack.pop()
140
+ self._restore_state(model_dc)
135
141
  self._app_model.sig_control_notify.emit()
136
142
  self._app_model.sig_synchronize_gui.emit()
137
143
 
@@ -139,8 +145,8 @@ class ModelObjects:
139
145
  """Undo to last saved state"""
140
146
  if len(self._redo_stack) > 0:
141
147
  self.push_undo_state(clear_redo_stack=False)
142
- state = self._redo_stack.pop()
143
- self._restore_state(state)
148
+ model_dc = self._redo_stack.pop()
149
+ self._restore_state(model_dc)
144
150
  self._app_model.sig_control_notify.emit()
145
151
  self._app_model.sig_synchronize_gui.emit()
146
152
 
@@ -1,4 +1,4 @@
1
- # Copyright (c) Fredrik Andersson, 2023
1
+ # Copyright (c) Fredrik Andersson, 2023-2024
2
2
  # All rights reserved
3
3
 
4
4
  """Handle settings in the model"""
@@ -25,10 +25,6 @@ class ModelSettings:
25
25
  """Return settings dict"""
26
26
  return self._settings
27
27
 
28
- def to_dict(self):
29
- """Return settings dict to save"""
30
- return {"settings": self._settings}
31
-
32
28
  def from_dict(self, circuit_dict):
33
29
  """Get settings from circuit dict"""
34
30
  for key, data in circuit_dict.get("settings", {}).items():
@@ -1,4 +1,4 @@
1
- # Copyright (c) Fredrik Andersson, 2023
1
+ # Copyright (c) Fredrik Andersson, 2023-2024
2
2
  # All rights reserved
3
3
 
4
4
  """Handle shortcuts in the model"""
@@ -72,9 +72,9 @@ class ModelShortcuts:
72
72
 
73
73
  def to_dict(self):
74
74
  """Generate dict from shortcuts"""
75
- shortcuts_dict = {"shortcuts": {}}
75
+ shortcuts_dict = {}
76
76
  for key, component in self._shortcut_component.items():
77
- shortcuts_dict["shortcuts"][key] = component.name()
77
+ shortcuts_dict[key] = component.name()
78
78
  return shortcuts_dict
79
79
 
80
80
  def from_dict(self, model_dict):
@@ -358,9 +358,9 @@ class ComponentSettingsDialog(QDialog):
358
358
  widget = ComponentSettingsCheckBoxWidthBool(
359
359
  self, parameter, parameter_dict, self._settings
360
360
  )
361
- elif parameter_dict["type"] == int:
361
+ elif parameter_dict["type"] == "int":
362
362
  widget = ComponentSettingsSlider(self, parameter, parameter_dict, self._settings)
363
- elif parameter_dict["type"] == str:
363
+ elif parameter_dict["type"] == "str":
364
364
  single_line = parameter_dict.get("single_line", False)
365
365
  if single_line:
366
366
  widget = ComponentSettingSingleLineText(
@@ -368,7 +368,7 @@ class ComponentSettingsDialog(QDialog):
368
368
  )
369
369
  else:
370
370
  widget = ComponentSettingText(self, parameter, parameter_dict, self._settings)
371
- elif parameter_dict["type"] == bool:
371
+ elif parameter_dict["type"] == "bool":
372
372
  widget = ComponentSettingsCheckBox(self, parameter, parameter_dict, self._settings)
373
373
  elif parameter_dict["type"] == "intrange":
374
374
  widget = ComponentSettingsIntRangeSlider(
@@ -382,7 +382,7 @@ class ComponentSettingsDialog(QDialog):
382
382
  widget = ComponentSettingsNameSelector(
383
383
  self, parameter, parameter_dict, self._settings
384
384
  )
385
- elif parameter_dict["type"] == list:
385
+ elif parameter_dict["type"] == "list":
386
386
  widget = ComponentSettingsListSelector(
387
387
  self, parameter, parameter_dict, self._settings
388
388
  )
@@ -5,11 +5,12 @@
5
5
  Module that handles the circuit simulation of components
6
6
  """
7
7
 
8
- import json
9
8
  import os
10
9
 
10
+ from digsim.storage_model import CircuitDataClass, CircuitFileDataClass
11
+
11
12
  from ._waves_writer import WavesWriter
12
- from .components.atoms import Component, DigsimException
13
+ from .components.atoms import DigsimException
13
14
 
14
15
 
15
16
  class CircuitError(DigsimException):
@@ -70,6 +71,11 @@ class Circuit:
70
71
  else:
71
72
  self._vcd = None
72
73
 
74
+ @property
75
+ def name(self):
76
+ """Get the circuit name"""
77
+ return self._name
78
+
73
79
  @property
74
80
  def time_ns(self):
75
81
  """Get the current simulation time (ns)"""
@@ -243,65 +249,24 @@ class Circuit:
243
249
  return comp
244
250
  raise CircuitError(f"Component '{component_name}' not found")
245
251
 
246
- def _connect_from_dict(self, source, dest):
247
- source_component_name = source.split(".")[0]
248
- source_port_name = source.split(".")[1]
249
- dest_component_name = dest.split(".")[0]
250
- dest_port_name = dest.split(".")[1]
251
-
252
- source_component = self.get_component(source_component_name)
253
- dest_componment = self.get_component(dest_component_name)
254
- source_component.port(source_port_name).wire = dest_componment.port(dest_port_name)
255
-
256
- def to_dict(self, folder=None):
252
+ def to_dataclass(self, folder=None):
257
253
  """Generate dict from circuit, used when storing circuit"""
258
254
  if self._name is None:
259
255
  raise CircuitError("Circuit must have a name")
260
-
261
256
  self._folder = folder
262
- components_list = []
263
- for comp in self.get_toplevel_components():
264
- components_list.append(comp.to_dict())
257
+ return CircuitDataClass.from_circuit(self)
265
258
 
266
- connection_list = []
267
- for comp in self.get_toplevel_components():
268
- for port in comp.ports:
269
- port_conn_list = port.to_dict_list()
270
- connection_list.extend(port_conn_list)
271
-
272
- circuit_dict = {
273
- "circuit": {
274
- "name": self._name,
275
- "components": components_list,
276
- "wires": connection_list,
277
- }
278
- }
279
-
280
- return circuit_dict
281
-
282
- def from_dict(
283
- self, circuit_dict, folder=None, component_exceptions=True, connect_exceptions=True
259
+ def from_dataclass(
260
+ self, circuit_dc, folder=None, component_exceptions=True, connect_exceptions=True
284
261
  ):
285
262
  """Clear circuit and add components from dict"""
286
263
  self._folder = folder
287
264
  self.clear()
288
- if "circuit" not in circuit_dict:
289
- raise CircuitError("No 'circuit' in JSON")
290
- json_circuit = circuit_dict["circuit"]
291
- if "name" not in json_circuit:
292
- raise CircuitError("No 'circuit/name' in JSON")
293
- self._name = json_circuit["name"]
294
- if "components" not in json_circuit:
295
- raise CircuitError("No 'circuit/components' in JSON")
296
- json_components = json_circuit["components"]
297
- if "wires" not in json_circuit:
298
- raise CircuitError("No 'circuit/connections' in JSON")
299
- json_connections = json_circuit["wires"]
300
265
 
301
266
  exception_str_list = []
302
- for json_component in json_components:
267
+ for component in circuit_dc.components:
303
268
  try:
304
- Component.from_dict(self, json_component)
269
+ component.create(self)
305
270
  except DigsimException as exc:
306
271
  if component_exceptions:
307
272
  raise exc
@@ -310,9 +275,9 @@ class Circuit:
310
275
  if component_exceptions:
311
276
  raise exc
312
277
  exception_str_list.append(f"{str(exc.__class__.__name__)}:{str(exc)}")
313
- for json_connection in json_connections:
278
+ for wire in circuit_dc.wires:
314
279
  try:
315
- self._connect_from_dict(json_connection["src"], json_connection["dst"])
280
+ wire.connect(self)
316
281
  except DigsimException as exc:
317
282
  if connect_exceptions:
318
283
  raise exc
@@ -322,15 +287,10 @@ class Circuit:
322
287
 
323
288
  def to_json_file(self, filename):
324
289
  """Store circuit in json file"""
325
- circuit_dict = self.to_dict()
326
- json_object = json.dumps(circuit_dict, indent=4)
327
-
328
- with open(filename, mode="w", encoding="utf-8") as json_file:
329
- json_file.write(json_object)
290
+ circuitfile_dc = CircuitFileDataClass(circuit=self.to_dataclass())
291
+ circuitfile_dc.save(filename)
330
292
 
331
293
  def from_json_file(self, filename, folder=None):
332
294
  """Load circuit from json file"""
333
- self._folder = folder
334
- with open(filename, mode="r", encoding="utf-8") as json_file:
335
- circuit_dict = json.load(json_file)
336
- self.from_dict(circuit_dict, folder)
295
+ file_dc = CircuitFileDataClass.load(filename)
296
+ self.from_dataclass(file_dc.circuit, folder)
@@ -29,7 +29,7 @@ class Bus2Wires(Component):
29
29
  def get_parameters(cls):
30
30
  return {
31
31
  "width": {
32
- "type": int,
32
+ "type": "int",
33
33
  "min": 2,
34
34
  "max": 32,
35
35
  "default": 2,
@@ -59,7 +59,7 @@ class Wires2Bus(Component):
59
59
  def get_parameters(cls):
60
60
  return {
61
61
  "width": {
62
- "type": int,
62
+ "type": "int",
63
63
  "min": 2,
64
64
  "max": 32,
65
65
  "default": 2,
@@ -36,7 +36,7 @@ class Buzzer(CallbackComponent):
36
36
  def get_parameters(cls):
37
37
  return {
38
38
  "tone": {
39
- "type": list,
39
+ "type": "list",
40
40
  "items": ["A", "B", "C", "D", "E", "F", "G"],
41
41
  "default": "A",
42
42
  "description": "Buzzer tone",
@@ -44,7 +44,7 @@ class Clock(CallbackComponent):
44
44
  def get_parameters(cls):
45
45
  return {
46
46
  "frequency": {
47
- "type": int,
47
+ "type": "int",
48
48
  "min": 1,
49
49
  "max": 50,
50
50
  "default": 1,
@@ -64,7 +64,7 @@ class DipSwitch(CallbackComponent):
64
64
  def get_parameters(cls):
65
65
  return {
66
66
  "bits": {
67
- "type": int,
67
+ "type": "int",
68
68
  "min": 2,
69
69
  "max": 8,
70
70
  "default": 8,