LC3
: The main module representing the LC3 FSM. Functionality is split into smaller modules according to the von Neumann model.control
: An instance of the Control modulememory
: An instance of the Memory moduleprocessing
: An instance of the Processing moduleFetch()
: Loads the current instruction into IR and increments the PC.Execute()
: Executes the instruction code stored in IR by setting the control signals incontrol
,memory
, andprocessing
.
Control
: Contains the PC and IRlc3
: A reference to the parent.pc
: Aushort
for the PC.ir
: Aushort
for the IR.ldPC()
: Sets thepc
frompcmuxout
in the parent'sprocessing
gatePC()
: Sets the parent'sbus
to the PCldIR()
: Sets their
from the parent'sbus
Processing
: Contains the ALU, address adder, Muxes, registers, and condition codesMemory
: Contains the data of the LC-3's main memorymar
: Aushort
for the MAR.mdr
: Aushort
for the MDR.mem
: ADictionary<ushort, ushort>
that maps addresses to data.ldMAR()
: Setsmar
to thebus
.ldMDR()
: Setsmdr
to thebus
.gateMAR()
: Sets thebus
tomar
.gateMDR()
: Sets thebus
tomdr
.memEnR()
: Writes the data ofmem
at the address inmar
tomdr
.memEnW()
: Writes the data ofmdr
tomem
at the address inmar
Read(ushort mar)
: Used by the handler to directly read from memoryWrite(ushort mar, ushort mdr)
: Used by the handler to directly write to memory
Assembler
: Alex Chen's implementation of an LC-3 assembler. Converts assembly string code to short integer data, or shortcode.List<InstructionPass> secondPass
: A list of instructions that require a second pass.Dictionary<string, short> labels
: Maps labels to memory locationsDictionary<short, string> labelsReverse
: Maps memory locations to labelsDictionary<string, short> trapLookup
: Maps a TRAP instruction name to its starting location.HashSet<short> nonInstruction
: Tracks the memory locations used for pure data for debug purpses.OpLookup ops
: A lookup table for Ops by name and by code (TRAP subroutines use their full code for lookup since they have the same opcode).short trapVectorIndex
: The index on the TRAP vector table where the starting location of the next declared TRAP instruction will be stored.AssembleLines(params string[] lines)
: Assembles two passes for an array of lines at the current PC, clearing any instructions previously queued for second passing.FirstPass()
: Reads through the string code, handling instructions, Directives, and labels. If an instruction needs a second pass, we store it (with contextualpc
and lineindex
info) for second passing later.SecondPass()
: Handles all instructions stored for second pass, loading the instruction'spc
and lineindex
context info and then assembling it.Directive(string directive)
: Handles a named directive..BLKW
: Skips thepc
assembly context over a segment of memory locations..BREAK
: Records a breakpoint; the GUI will pause execution when the PC reaches this value.END
: Ends the first pass for the current file, calling the second pass on instructions handled so far and clearing labels..FILL
: Sets the data at the current memory location to the given value..SCOPE
: Creates a new scope with the given name. Clears the previous scope by calling second pass on instructions handled so far and then appending its name to the labels passed so far..STRINGZ
: Places the characters of the given string into a segment of memory locations the last of which will be set to0
..TRAP
: Declares a new TRAP subroutine with the given name, adding the current memory location to the TRAP vector table and adding a new Trap object to theops
table. Also creates a new scope with the given name.
lcs gui {program_file} [input_file] [output_file] - launches LC-Sharp in GUI mode
- Instructions
- A scrollable view of the LC-3's main memory.
- The current instruction about to be executed is highlighted.
- When an instruction is fetched, the view snaps to center on the instruction and highlights it. Note that for abstraction purposes, TRAP subroutines do not affect this view during execution.
- When scrolled, we dynamically regenerate the labels.
- Updates on every instruction
- Locations containing breakpoints are prefixed with
*
- Registers
- A state listing of the main registers, the condition codes, the PC, and the IR.
- Updates on every instruction
- Labels
- A listing of named memory addresses and their data
- Status
Idle
: The program is pausedRun All
: The program is currently running until halted.Run Step Once
: The program is currently running a single instruction.Run Step Over
: The program is currently running through a single subroutine call and will pause once the subroutine returns.Waiting
: The program is waiting to receive input.Halt
: The program is halted normally.Error
: The program is halted due to a bug detected by the emulator.
- Buttons
- Open Program: Opens a program from its source file
- Save Program: Saves the source of the program to a file
- Restart: Sets all registers to their default values.
- Run All: Executes instructions until the program is halted. Waits for input if needed.
- Run Step Once: Executes the current instruction. Waits for input if needed.
- Run Step Over: Stores the current address of the PC (one index ahead) and executes instructions until that point is reached. Waits for input if needed.
- Debug
- Set Scroll: A text view allowing the user to set the current scroll position
- Set PC: A text view allowing the user to set the PC and reset the FSM's status if it was halted for any reason.
- Assemble Debug Code: A text view allowing the user to assemble instructions directly into memory.
- Output
- A read-only text view containing the program's output.
- The DSR is checked during the main loop and any output is read from DDR and sent to this view.
- Input
- A text view containing the program's input.
- The KBSR is checked during the main loop and any input is read from this view and sent to the KBDR.
lcs cli {program_file} [input_file] [output_file] - launches LC-Sharp in headless (command-line) mode
- In CLI mode, the emulator runs the entire program with no GUI.
- Input
- If we have an input file, then we read all input from it. If it ends before the program is done taking input, then we throw an error.
- Otherwise, we get it through
ReadKey(true)
, which does not echo key presses (since the program should already do that).
- Output
- If we have an output file, then we make sure that the program's output matches the file contents.
- Output is printed to console
- Custom TRAP Subroutines support -
.TRAP
$ git clone --recurse-submodules https://github.com/3TUSK/LC-Sharp
$ cd LC-Sharp
$ dotnet publish --self-contained -r <TARGET_RUNTIME> -o ../LC-Sharp-Build LC-Sharp
# Change ../LC-Sharp-Build to something else for a different output directory
where <TARGET_RUNTIME>
specifies target platform, which may be the following, without limitation to:
win10-x64
for Windows 10 (64-bit)osx.10.14-x64
for macOS 10.14 Mojavelinux-x64
for most of Linux distro
A complete list of possible target platform may be found at https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
Alternatively, you may also directly import the whole solution into your IDE, for example Visual Studio Community or JetBrains Rider, and run it there.
- In LC-Sharp, the upper nibble (
[15:8]
) of Display Data Register (DDR,xFE06
) is also reserved. That said, character written in the whole DDR will be displayed on the screen.- In the original LC-3 ISA, only the lower nibble (
[7:0]
) has defined behavior; the behavior for[15:8]
is undefined. - This change is backward compatible, since the first unicode plane is "compatible" with ASCII.
- This effectively expands the range of support characters from ASCII to first 256 unicode planes (i.e. 0x0000 to 0xFFFF).
- No plan for further unicode support due to word size of 16 bit.
- In the original LC-3 ISA, only the lower nibble (