Skip to content

fix(gsoc'24): updates and bug fixes from the main simulator #314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified src/assets/img/assignment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,24 @@
"decrease_width": "Decrease Width",
"increase_width": "Increase Width",
"reset": "Reset"
},
"tutorial_guide": {
"circuit_elements_panel": "Circuit Elements panel",
"circuit_elements_panel_desc": "This is where you can find all the circuit elements that are offered to build amazing circuits.",
"properties_panel": "Properties Panel",
"properties_panel_desc": "This panel lets you change element properties as they are selected. When no elements are selected, the panel displays project properties.",
"quick_access_panel": "Quick Access Panel",
"quick_access_panel_desc": "This movable panel offers to perform some actions like Save Online, Open, Download quickly. Hover over the icons and see for yourself",
"circuit_tabs": "Circuit Tabs",
"circuit_tabs_desc": "This section displays all the circuits you have in your project. You can easily add and delete circuits.",
"timing_diagram_panel": "Timing Diagram Panel (Waveform)",
"timing_diagram_panel_desc": "This panel displays the waveform created by circuits and can be used for resolving race conditions and debugging circuits.",
"test_bench_panel": "Test Bench Panel",
"test_bench_panel_desc": "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.",
"report_system": "Report System",
"report_system_desc": "You can report any issues/bugs you face through this issue reporting button there and then quickly.",
"restart_tutorial": "Restart tutorial anytime",
"restart_tutorial_desc": "You can restart this tutorial anytime by clicking on \"Tutorial Guide\" under this dropdown."
}
}
}
18 changes: 18 additions & 0 deletions src/locales/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,24 @@
"decrease_width": "चौड़ाई घटाएं",
"increase_width": "चौड़ाई बढ़ाएँ",
"reset": "रिसेट करें"
},
"tutorial_guide": {
"circuit_elements_panel": "सर्किट तत्व पैनल",
"circuit_elements_panel_desc": "यहां आपको अद्भुत सर्किट बनाने के लिए प्रस्तुत किए गए सभी सर्किट तत्व मिलेंगे।",
"properties_panel": "गुण पैनल",
"properties_panel_desc": "यह पैनल आपको तत्व गुणों को बदलने देता है जैसे कि वे चयनित होते हैं। जब कोई तत्व चयनित नहीं होते हैं, तो पैनल परियोजना गुण दिखाता है।",
"quick_access_panel": "त्वरित पहुंच पैनल",
"quick_access_panel_desc": "यह स्थानांतरणीय पैनल ऑनलाइन सहेजने, खोलने, डाउनलोड करने जैसे कुछ कार्यों को त्वरित रूप से करने की पेशकश करता है। आइकनों पर होवर करें और स्वयं देखें",
"circuit_tabs": "सर्किट टैब",
"circuit_tabs_desc": "इस खंड में आपके पास अपनी परियोजना में मौजूद सभी सर्किट्स दिखाई देते हैं। आप आसानी से सर्किट जोड़ और हटा सकते हैं।",
"timing_diagram_panel": "समय आरेख पैनल (वेवफॉर्म)",
"timing_diagram_panel_desc": "यह पैनल सर्किट्स द्वारा बनाए गए वेवफॉर्म को प्रदर्शित करता है और सर्किट्स को डीबग करने और रेस स्थितियों को हल करने के लिए इस्तेमाल किया जा सकता है।",
"test_bench_panel": "परीक्षण बेंच पैनल",
"test_bench_panel_desc": "यह पैनल आपको अपने सर्किट की सहीता का परीक्षण करने में मदद करता है, जिसमें विभिन्न परीक्षण मामलों के तहत आपके सर्किट का प्रतिक्रिया देखकर, एक सम्पूर्ण और प्रभावी सत्यापन प्रक्रिया सुनिश्चित की जाती है।",
"report_system": "रिपोर्ट प्रणाली",
"report_system_desc": "आप इस मुद्दा रिपोर्टिंग बटन के माध्यम से जो भी मुद्दे / बग्स का सामना करते हैं, उन्हें तत्परता से रिपोर्ट कर सकते हैं।",
"restart_tutorial": "ट्यूटोरियल को कभी भी पुनः शुरू करें",
"restart_tutorial_desc": "आप इस ड्रॉपडाउन के तहत \"ट्यूटोरियल गाइड\" पर क्लिक करके इस ट्यूटोरियल को कभी भी पुनः शुरू कर सकते हैं।"
}
}
}
2 changes: 1 addition & 1 deletion src/simulator/src/combinationalAnalysis.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore'
export function createCombinationalAnalysisPrompt(scope = globalScope) {
scheduleBackup()
SimulatorStore().dialogBox.combinationalanalysis_dialog = true
}
}
77 changes: 77 additions & 0 deletions src/simulator/src/contention.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* @class
* ContentionPendingData
*
* Data structure to store pending contentions in the circuit.
**/
export default class ContentionPendingData {
constructor() {
// Map<Node, Set<Node>>
this.contentionPendingMap = new Map();
this.totalContentions = 0;
}

// Adds
add(ourNode, theirNode) {
if (this.contentionPendingMap.has(ourNode)) {
if (!this.contentionPendingMap.get(ourNode).has(theirNode)) this.totalContentions++;
this.contentionPendingMap.get(ourNode).add(theirNode);
return;
}

this.totalContentions++;
this.contentionPendingMap.set(ourNode, new Set([theirNode]));
}

has(ourNode) {
return this.contentionPendingMap.has(ourNode);
}

// Removes contention entry ourNode -> theirNode.
remove(ourNode, theirNode) {
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 contentionPending entries for ourNode.
// Since ourNode is strictly a NODE_OUTPUT, we should remove all contentions for the node when the
// node resolves.
removeContentionsForNode(ourNode, removalFunction) {
if (!this.contentionPendingMap.has(ourNode)) return;

const contentionsForOurNode = this.contentionPendingMap.get(ourNode);
for (const theirNode of contentionsForOurNode) removalFunction.call(this, ourNode, theirNode);
}

removeAllContentionsForNode(ourNode) {
this.removeContentionsForNode(ourNode, this.remove);
}

removeIfResolvedAllContentionsForNode(ourNode) {
this.removeContentionsForNode(ourNode, this.removeIfResolved);
}

// Removes contention entry ourNode -> theirNode if the contention between them has resolved.
removeIfResolved(ourNode, theirNode) {
if (ourNode.bitWidth === theirNode.bitWidth && (ourNode.value === theirNode.value || ourNode.value === undefined))
this.remove(ourNode, theirNode);
}

size() {
return this.totalContentions;
}

// Returns a list of [ourNode, theirNode] for all contentions.
nodes() {
var items = [];
for (const [ourNode, contentionSet] of this.contentionPendingMap) {
for (const theirNode of contentionSet) items.push([ourNode, theirNode]);
}

return items;
}

}
8 changes: 7 additions & 1 deletion src/simulator/src/data/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,13 @@ export async function generateSaveData(name, setName = true) {
}

completed[id] = true
update(scopeList[id], true) // For any pending integrity checks on subcircuits

// 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.
update(scopeList[id], true); // For any pending integrity checks on subcircuits
data.scopes.push(backUp(scopeList[id]))
}

Expand Down
28 changes: 19 additions & 9 deletions src/simulator/src/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { showError } from './utils'
import miniMapArea from './minimap'
import { resetup } from './setup'
import { verilogModeGet } from './Verilog2CV'
import ContentionPendingData from './contention';
import { renderOrder, updateOrder } from './metadata'

/**
Expand Down Expand Up @@ -405,16 +406,16 @@ 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()
simulationArea.simulationQueue.reset()
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
Expand All @@ -426,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
Expand Down
2 changes: 1 addition & 1 deletion src/simulator/src/modules/AndGate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 7 additions & 3 deletions src/simulator/src/modules/ControlledInverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,14 @@ export default class ControlledInverter extends CircuitElement {
((~this.inp1.value >>> 0) << (32 - this.bitWidth)) >>>
(32 - this.bitWidth)
simulationArea.simulationQueue.add(this.output1)
} else if (
this.output1.value !== undefined &&
!simulationArea.contentionPending.has(this.output1)
) {
this.output1.value = undefined;
simulationArea.simulationQueue.add(this.output1);
}
if (this.state.value === 0) {
this.output1.value = undefined
}
simulationArea.contentionPending.removeAllContentionsForNode(this.output1);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/simulator/src/modules/DigitalLed.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export default class DigitalLed extends CircuitElement {
// Calling base class constructor
super(x, y, scope, 'UP', 1)
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
Expand Down
2 changes: 1 addition & 1 deletion src/simulator/src/modules/NotGate.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,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'
2 changes: 1 addition & 1 deletion src/simulator/src/modules/OrGate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export default class OrGate extends CircuitElement {
}

OrGate.prototype.tooltipText =
'Or Gate Tooltip : Implements logical disjunction';
'Or Gate ToolTip : Implements logical disjunction';

OrGate.prototype.changeInputSize = changeInputSize;

Expand Down
3 changes: 2 additions & 1 deletion src/simulator/src/modules/PriorityEncoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,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

Expand Down
1 change: 1 addition & 0 deletions src/simulator/src/modules/RGBLed.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default class RGBLed extends CircuitElement {
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)
Expand Down
7 changes: 3 additions & 4 deletions src/simulator/src/modules/TriState.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,17 @@ export default class TriState extends CircuitElement {

if (this.state.value === 1) {
if (this.output1.value !== this.inp1.value) {
this.output1.value = this.inp1.value // >>>0)<<(32-this.bitWidth))>>>(32-this.bitWidth);
this.output1.value = this.inp1.value
simulationArea.simulationQueue.add(this.output1)
}
simulationArea.contentionPending = simulationArea.contentionPending.filter(x => x !== this);
} else if (
this.output1.value !== undefined &&
!simulationArea.contentionPending.includes(this)
!simulationArea.contentionPending.has(this.output1)
) {
this.output1.value = undefined
simulationArea.simulationQueue.add(this.output1)
}
simulationArea.contentionPending = simulationArea.contentionPending.filter(x => x !== this);
simulationArea.contentionPending.removeAllContentionsForNode(this.output1);
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/simulator/src/modules/VariableLed.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default class VariableLed extends CircuitElement {
super(x, y, scope, 'UP', 8)
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
Expand Down
2 changes: 1 addition & 1 deletion src/simulator/src/modules/XorGate.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,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
Expand Down
Loading
Loading