Skip to content

Added new hardware mode in emulator#70

Merged
arghyabi merged 1 commit into
masterfrom
update_hw_mode_in_enulator
Apr 8, 2026
Merged

Added new hardware mode in emulator#70
arghyabi merged 1 commit into
masterfrom
update_hw_mode_in_enulator

Conversation

@arghyabi
Copy link
Copy Markdown
Owner

@arghyabi arghyabi commented Apr 8, 2026

No description provided.

Signed-off-by: Arghya Biswas <arghya@ialoy.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “hardware” execution mode to the emulator, allowing programs to run via generated microcode (micro-cycle stepping) in addition to the existing direct/instruction-level software execution path.

Changes:

  • Added a --mode {software,hardware} CLI switch and propagated mode selection into the GUI.
  • Implemented a new HardwareCPU that loads microcode banks + 7-seg ROM and steps micro-cycles with optional signal logging.
  • Updated GUI widgets/status to display mode, cycle labeling, console output, and hardware 7-seg raw segment patterns.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Emulator/main.py Adds CLI --mode and CLI execution output updates; passes mode into GUI.
Emulator/gui/widgets.py Supports rendering raw 7-seg patterns and improves cycle label text based on mode/cycle type.
Emulator/gui/main_window.py Adds mode indicator + console, wires CPU logging, and supports hardware 7-seg patterns in UI.
Emulator/core/software_cpu.py Renames CPU class to SoftwareCPU, adds execution logging hooks, and exposes mode metadata via getState().
Emulator/core/hardware_cpu.py New microcode-driven CPU implementation (micro-cycle stepping, signal logging, 7-seg ROM patterns).
Emulator/core/decoder.py Adjusts register-field decoding for 4-bit opcodes to match DDSS upper-nibble layout.
.gitignore Ignores .vscode/.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Emulator/main.py
Comment on lines +55 to +61
executed = cpu.run()

print(f"Loaded program: {args.program}")
print(f"Mode: {'Signed (-128 to +127)' if initialSignedMode else 'Unsigned (0 to 255)'}")
print("Program executed successfully")
print(f"Execution mode: {args.mode}")
print(f"Executed {executed} instruction cycles")
print(f"Program halted: {cpu.halted}")
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In CLI mode, cpu.run() returns a count of executed steps, but that means instruction-cycles in software mode and micro-cycles in hardware mode. Printing this unconditionally as “instruction cycles” is misleading; use args.mode/cpu.getState()['cycleType'] to label the count appropriately (or print both instructionCount and cycleCount for hardware).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit ba6c9ab. The CLI output now labels the counts appropriately based on mode:

  • Hardware mode: prints Executed N instructions (M micro-cycles) using getState()['instructionCount'] and getState()['cycleCount']
  • Software mode: prints Executed N instruction cycles using getState()['instructionCount']

Comment on lines 169 to +190
# Assembly code display
assemblyCodeFrame = tk.LabelFrame(codeFrame, text = "Assembly Code", font = ("Arial", 10, "bold"))
assemblyCodeFrame.pack(fill = "both",side = "right", expand = True, pady = 10)

self.assemblyTextbox = tk.Text(assemblyCodeFrame, width = 10, height = 15, font = ("Courier", 9))
assemblyCodeScrollbar = tk.Scrollbar(assemblyCodeFrame, orient = "vertical", command = self.assemblyTextbox.yview)
self.assemblyTextbox.configure(yscrollcommand = assemblyCodeScrollbar.set)

self.assemblyTextbox.pack(side = "left", fill = "both", expand = True)
assemblyCodeScrollbar.pack(side = "right", fill = "y")
self.assemblyTextbox.config(state = "disabled")

# Disassembly code display
disassemblyCodeFrame = tk.LabelFrame(codeFrame, text = "Disassembly Code", font = ("Arial", 10, "bold"))
disassemblyCodeFrame.pack(fill = "both", side = "right", expand = True, pady = 10)
self.disassemblyTextbox = tk.Text(disassemblyCodeFrame, width = 10, height = 15, font = ("Courier", 9))
disassemblyCodeScrollbar = tk.Scrollbar(disassemblyCodeFrame, orient = "vertical", command = self.disassemblyTextbox.yview)
self.disassemblyTextbox.configure(yscrollcommand = disassemblyCodeScrollbar.set)

self.disassemblyTextbox.pack(side = "left", fill = "both", expand = True)
disassemblyCodeScrollbar.pack(side = "right", fill = "y")
self.disassemblyTextbox.config(state = "disabled")
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assemblyTextbox/disassemblyTextbox are set to state="disabled", but Emulator/main.py writes to these widgets directly during startup program load. Writing to a disabled tk.Text raises TclError; either don’t disable by default, or centralize updates via helper methods that temporarily set state="normal" before delete/insert.

Copilot uses AI. Check for mistakes.
if signals.get('MdI'):
self.memoryAddress = self.bus & 0x0F

if signals.get('MeI') and signals.get('MdI'):
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RAM writes are currently gated on MeI and MdI being asserted in the same micro-cycle. The microcode asserts MdI (address latch) and later asserts MeI (write enable) in different cycles (e.g. InsSAV), so stores will never write. Latch memoryAddress when MdI is high, and perform the write when MeI is high (using the latched address).

Suggested change
if signals.get('MeI') and signals.get('MdI'):
if signals.get('MeI'):

Copilot uses AI. Check for mistakes.
Comment on lines +340 to +347
if signals.get('Seg7E') or signals.get('SpO') or signals.get('SpL'):
self._update_seven_segment_patterns()

if signals.get('SpUd'):
self.signedMode = False
else:
self.signedMode = True

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

signedMode is forced to True whenever SpUd is not asserted. Since the current microcode never drives SpUd high, this will override setSignedMode(False) and make unsigned mode unusable in hardware mode. Consider only updating signedMode when SpUd is explicitly driven (or treat it as a latched state), and compute 7-seg patterns after the final signedMode for the cycle is known.

Suggested change
if signals.get('Seg7E') or signals.get('SpO') or signals.get('SpL'):
self._update_seven_segment_patterns()
if signals.get('SpUd'):
self.signedMode = False
else:
self.signedMode = True
if signals.get('SpUd'):
self.signedMode = False
if signals.get('Seg7E') or signals.get('SpO') or signals.get('SpL'):
self._update_seven_segment_patterns()

Copilot uses AI. Check for mistakes.
Comment on lines +296 to +301
def _apply_control_signals(self, signals):
if signals.get('SpO') or signals.get('Seg7E') or signals.get('SpL'):
self.outputEnabled = True
self.sevenSegmentPatterns = None

if signals.get('rAI'):
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.sevenSegmentPatterns is reset to None every micro-step, so the GUI will usually fall back to setValue() (software segment patterns) instead of rendering the hardware ROM-driven patterns. Keep the last computed patterns until the display value/mode changes (or recompute patterns every step from sevenSegmentValue + signedMode).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants