Eight Bit Computer

Welcome to the documentation for the 8 bit computer project!

Overview

Usage

Setup

Inputting Programs

Running and Resetting

Modules

Register

A register stores an 8 bit number. In the computer registers are connected to the bus and can read a value from the bus or assert a value onto the bus. They also provide an output which is the currently stored value.

As well as the data oriented ACC, A, B and C registers, the control oriented instruction register, stack pointer and memory address register are all just registers. The memory address register only needs to read from the bus and not assert values onto it so it’s slightly simpler.

Interface and Operation

This is the interface of a register:

_images/register_block.png

This is how it operates:

Name Bit width Description
data 8 Reads bits from, or asserts bits onto this connection
contents 8 Always outputs the current value held in the register
clock 1 Clock signal from the clock module
input_enable 1 While high, the register stores the value on data on a rising clock edge
output_enable 1 While high, the register asserts it’s content onto data

Implementation

  • A 74HCT377 is used to store the contents of the register.
  • A 74HCT245 is used to provide a tri-state output to allow asserting values onto the bus, or not.
  • LEDs with current limiting resistors are used to display the current contents.
  • A 74HCT04 is used to invert the incoming input_enable and output_enable signals to drive the active low inputs on the 74HCT377 and 74HCT245.

The electronics are laid out on the breadboard like so:

_images/register_bus_left_bb.png

Due to the central bus in the layout of the computer it’s convenient to also have a version where the connection to the bus is on the right:

_images/register_bus_right_bb.png

An input only register like the memory address register is simpler:

_images/register_input_only_right_bb.png

2:1 Selector

The 2:1 selector outputs one of two 8 bit inputs. Also known as a multiplexer.

Interface and Operation

This is the interface of a 2:1 selector:

_images/two_to_one_block.png

This is how it operates:

Name Bit width Description
A 8 First input
B 8 Second input
out 8 Output, either A or B.
A/B 1 When low, A is output, when high, B is output

Implementation

  • Two 74HCT157s are used to choose between the two inputs.
  • LEDs with current limiting resistors are used to display the output.

Due to 2:1 selectors being required in different parts of the computer, the layout on the breadboard of A, B and out sometimes need to differ.

This is the A B out layout:

_images/two_to_one_A_B_O_bb.png

This is the out A B layout:

_images/two_to_one_O_A_B_bb.png

Different coloured wires are used in the Fritzing images above to help track the A, B and out bits. When creating the computer only green wire was available :(.

Program Counter

The program counter stores an eight bit number used to track the current position/instruction in program memory.

It’s similar to a regular register but has some extra functionality:

  • It can add one to it’s current value.
  • It’s value can be asynchronously reset to 0.

Interface and Operation

This is the interface to the program counter:

_images/program_counter_block.png

This is how it operates:

Name Bit width Description
data 8 Reads bits from, or asserts bits onto this connection.
contents 8 Always outputs the current value held in the program counter.
clock 1 Clock signal from the clock module.
input_enable 1 While high, the program counter stores the value on data on a rising clock edge.
count 1 While high, the program counter increments the stored value by one on a rising clock edge.
output_enable 1 While high, the program counter asserts it’s content onto data.

Implementation

  • Two 74HCT161s are used to store, increment and clear the 8 bit value.
  • A 74HCT245 is used to provide a tri-state output to allow asserting values onto the bus, or not.
  • A 74HCT04 is used to invert the incoming input_enable, output_enable and count signals to drive the active low inputs on the 74HCT161s and 74HCT245.
  • LEDs with current limiting resistors are used to display the current contents.

The electronics are laid out on the breadboard like so:

_images/program_counter_bb.png

Clock

The clock produces signals that synchronise the operation of all the other modules in the computer.

It can drive the operation of the computer step by step for debugging or at an arbitrary speed.

Interface and Operation

This is the interface to the clock:

_images/clock_block.png

And this is how it operates:

Name Bit width Description
auto/manual 1 When low, the clock signals are advanced manually with manual_input. When high, clock signals are advanced automatically.
manual_clock_input 1 High/low transitions here will advance the clock signals.
halt 1 While high, bring both of the clock signals low and stop them advancing.
reset 1 While high, bring both of the clock signals low and stop them advancing.
data_clock 1 Alternates between high and low, driving the data transitions in the computer.
control_clock 1 Alternates between high and low, driving the control signal transitions in the computer.
Control and Data Clocks

Typically the clocks in other computers invert data_clock to create control_clock, like this:

_images/inverted_data_clock.png

This is not suitable for this computer due to some restrictions on the 74HCT161 used in the Program Counter. Here is the note from the datasheet:

Note

  1. The High-to-Low transition of PE or TE on the ’HC/HCT161 and the ’HC/HCT163 should only occur while CP is HIGH for conventional operation.
  2. The Low-to-High transition of SPE on the ’HC/HCT161 and SPE or MR on the ’HC/HCT163 should only occur while CP is HIGH for conventional operation.

This means:

  • PE going from high to low (i.e. disabling counting) must happen while data_clock is high.
  • SPE going from low to high (i.e. disabling parallel load mode) must happen while data_clock is high.

The inverted clock method doesn’t satisfy this constraint as control signal changes (which happen a short delay after the rising edge of control_clock) would occur after data_clock had gone low. The delay is introduced by the EEPROMs in the Control Unit settling after a new instruction/flag/micro-step value goes onto their address lines. This demonstrates the problem using the PE control (_SPE is the same):

_images/inverted_data_clock_problem.png

To satisfy this constraint, the two clock signals proceed like this:

_images/offset_clock_signals.png

This means data_clock is still high when PE/count_enable changes:

_images/offset_clock_signals_fix.png
Halt and reset

Once halt or reset go high, both data_clock and control_clock immediately go low. Once halt and reset go low again after either becomes high, data_clock should be the first to go high and the then sequence continues. This is to ensure correct timing gaps are left when operation of the computer resumes.

Implementation

Even duty cycle

The 555 astable circuit used does not always output a signal with an even duty cycle. To fix this, the output from the 555 is fed into the clock of a JK flip flop configured to toggle. This halves the frequency of the astable output but guarantees it’s at a 50% duty cycle.

Block diagram

Logically the clock is implemented as follows:

_images/clock_schematic_ideal.png

From left to right:

  • Manual and 555 clock signals.
  • Feed the 555 into a JK flip flop configured to toggle to achieve even duty cycle.
  • Multiplex to choose the manual or auto clock.
  • Halt and reset signals - effectively do the same thing - stop the clock.
  • Safe Clock Enable. This ensures correct timing of the clock after reset is released.
  • Two JK flip flops configured to toggle, one fed with the inverse of the gated clock signal to be the delayed signal for the control clock.

However, in reality the layout is equivalent, but a little more complex due to implementation details in the other chips (active low inputs) and trying to make the best use of space and gates available on chips:

_images/clock_schematic_reality.png
Hardware

The following electronics are used:

  • A 555 and accompanying resistors and capacitors to generate the auto clock signal.
  • A 74HCT109 to get an even duty cycle from the 555.
  • A 74HCT157 to multiplex between the manual and auto clock signals.
  • A 74HCT02 and 74HCT00 to create the safe clock gate and some additional signal inverting.
  • Another 74HCT109 to provide the last 2 toggles for the clocks.

The components are laid out on the breadboard like so:

_images/clock_bb.png

RAM

The RAM provides 256 bytes of program memory (instruction bytes) and 256 bytes of data memory (global variables and the stack).

Interface and Operation

This is the interface of the RAM:

_images/ram_block.png

This is how it operates:

Name Bit width Description
input_enable 1 While high, the data on data_in will be stored at the currently selected address on a rising clock edge.
output_enable 1 While high, the RAM asserts the data at the currently selected address onto data_out.
data_clock 1 Clock signal from the clock module (data_clock).
setup_clock 1 Clock signal from the manual setup switch.
run_setup 1 When low, the RAM is in setup mode, when high, run mode.
control_unit_select_data_memory 1 Program/data memory selection switch from the control unit.
setup_select_data_memory 1 Program/data memory selection switch from the manual setup switch.
data_in 8 Data to be stored is read from here.
data_out 8 Data at current address is output here.
address 8 Index in memory to read from or write to.

Implementation

Combined Input/Output pins

Unlike the 74LS189 chip that Ben Eater uses for his RAM, the 6116SA used in this computer has combined input and output pins. This means that care is required not to apply signals to those pins at incorrect times. A tri state buffer is used on the input to achieve this. The connections from the input/output pins on the RAM chip and the 74HCT245 tri state buffers are arranged like this:

_images/input_output_buffers.png
Timing for Safely Writing Data

Most of the time the RAM chip is in read mode. This means that the chip is asserting the data stored in the address currently specified on the address pins to the input/output pins. When it’s time to write, the chip needs to switch to write mode. To simplify control circuitry, only the write enable (active low) input on the 6116SA is used to control switching between read and write mode (output enable (active low) is available on the chip as well).

It takes time for the chip to switch modes and the pins to change from output to input. This time is referred to as tWHZ in the data-sheet and the following note applies:

Note

  1. During this period, the I/O pins are in the output state and the input signals must not be applied.

According to the data-sheet tWHZ is at most 7ns for the 6116SA15 being used.

As well as the time taken for the pins to change state, we need to ensure that the overall write pulse width is a certain length due to another note in the data-sheet (which applies because _OE will indeed be low):

Note

  1. _OE is continuously HIGH. If _OE is LOW during a _WE controlled write cycle, the write pulse width must be the larger of tWP or (tWHZ + tDW) to allow the I/O drivers to turn off and data to be placed on the bus for the required tDW. If _OE is HIGH during a _WE controlled write cycle, this requirement does not apply and the write pulse is the specified tWP. For a _CS controlled write cycle, _OE may be LOW with no degradation to tCW.

tWP is listed as 12ns, but tWHZ + tDW (7ns + 12ns) is greater at 19ns so the write pulse needs to be at least that long.

The chip is also not edge triggered - it will write data to the specified address as long as it is in write mode. This means that we need to do our own edge detection and keep the write pulse as short as possible. See the Edge Detection section for more details.

Once the write is finished, the chip can go instantly back into read mode (as tDH is 0ns).

So with all this in mind, this is how the desired control signals would look (assuming a write is to take place).

_images/ideal_ram_write_control.png

The output enable on the 74HCT245 and write enable on the 6116SA are active low so the final circuit looks like this:

_images/write_signal_timing.png

(This can be seen in Falstad Circuit Simulator by loading the saved session)

From left to right:

  • The capacitor, resistor and inverting Schmitt trigger on the bottom form the edge detector that produces a low pulse when a rising edge is detected.
  • The three inverting Schmitt triggers on top serve to delay and invert the clock signal (using propagation delay).
  • The two OR gates ensure that once the low pulse from the detected rising edge finishes, both control signals go high at the same time.

The propagation delay of the inverting Schmitt triggers (inside a 74HCT14) is approximately 20ns, to a maximum of approximately 40ns. With the 3 Schmitt triggers on top, the inversion of the now positive clock is delayed between 60ns and 120ns.

The resistor and capacitor values are chosen so that the time from the voltage between the capacitor and the resistor going high, to the voltage going below the negative going threshold of the Schmitt trigger is at least 112ns. That is:

  • 120ns for the longest possible delay for the top three Schmitt triggers.
  • Subtract 20ns for the shortest propagation delay from the edge detect Schmitt trigger.
  • 12ns to satisfy tDW

The 7ns required for tWHZ is amply catered for by the chained Schmitt triggers.

The final control signals look like this:

_images/ram_write_signals.png
Run/Setup Mode

The RAM needs to accessed by the computer while running (run mode) and by the user during setup (setup mode). To achieve this, the follwing inputs to the RAM all need to be driven by either the computer itself, or the user:

  • data_in
  • address
  • input_enable
  • select_data_memory
  • clock

The run_setup switch decides which input will be fed to the RAM.

data_in and address are connected to 2:1 Selectors.

The remaining input_enable, prog_data_mem_select and clock are all connected to a 74HCT157 Quad 2 to 1 line data selector. They are set up as follows:

_images/run_setup_mode.png

From left to right:

  • Multiplexers to select between run and setup control signals
  • Safe Clock Enable
  • Outputs to the rest of the RAM.

When in run mode:

  • data_in - connected to the bus.
  • address - connected to the output of the memory address register.
  • input_enable - connected to ram_in from the Control Unit.
  • select_data_memory - connected to ram_sel_data_mem from the Control Unit.
  • clock - connected to data_clock from the Clock.

When in setup mode, all of the above are connected to switches that the user controls, apart from input_enable which is held high.

Hardware

The following electronics are used:

  • A 6166SA15 RAM chip to hold all the data.
  • 2 x 74HCT245 for controlling input and output to and from the RAMs IO pins.
  • A 74HCT157 to choose between the inputs in run and setup mode.
  • A 74HCT02 containing NOR gates to build the Safe Clock Enable.
  • A 74HCT08 containing AND gates to build the Safe Clock Enable and isolate the resistor and capacitor circuit from the other logic gates.
  • A 74HCT14 containing Schmitt triggers to edge detect and delay the clock.
  • A 74HCT32 for the OR gates that are used in the edge detection and delay circuit.

They are laid out on the breadboards as follows:

_images/ram_bb.png

Control Unit

The control unit interprets the instruction byte and flag bits. It sets control signals in the correct sequence to operate the other modules in the computer to complete the current instruction. Steps in the sequence are kept in order with an internal microcode step counter.

Interface and Operation

This is the interface of the Control Unit:

_images/control_unit_block.png

This is how it operates:

Name Bit width Description
instruction_byte 8 Specifies the current instruction.
flags 4 The flag bits from the ALU, control conditional instructions.
clock 1 The control_clock from the clock module.
reset 1 While high, sets the microcode step count to 0.
acc_in 1 Instructs the accumulator register to store the value on the bus.
acc_out 1 Instructs the accumulator register to assert it’s content onto the bus.
a_in 1 Instructs the A register to store the value on the bus.
a_out 1 Instructs the A register to assert it’s content onto the bus.
b_in 1 Instructs the B register to store the value on the bus.
b_out 1 Instructs the B register to assert it’s content onto the bus.
c_in 1 Instructs the C register to store the value on the bus.
c_out 1 Instructs the C register to assert it’s content onto the bus.
alu_store_result 1 Instructs the ALU to store the current result.
alu_store_flags 1 Instructs the ALU to store the current flags.
alu_out 1 Instructs the ALU register to assert it’s stored result onto the bus.
alu_a_is_bus 1 When low, the A input to the ALU is the accumulator register, when high, its the bus.
alu_s0 1 The S0 input for selecting ALU operations.
alu_s1 1 The S1 input for selecting ALU operations.
alu_s2 1 The S2 input for selecting ALU operations.
alu_s3 1 The S3 input for selecting ALU operations.
alu_m 1 The M input for the ALU.
alu_c_in 1 The carry in input for the ALU.
mar_in 1 Instructs the memory address register to store the value on the bus.
ram_in 1 Instructs the RAM to store the value on the bus.
ram_out 1 Instructs the RAM to assert it’s content onto the bus.
ram_sel_data_mem 1 When low, the RAM will operate on program memory, when high, data memory.
sp_in 1 Instructs the stack pointer to store the value on the bus.
sp_out 1 Instructs the stack pointer to assert it’s content onto the bus.
pc_in 1 Instructs the program counter to store the value on the bus.
pc_out 1 Instructs the program counter to assert it’s content onto the bus.
pc_count 1 Instructs the program counter to increment it’s value by one.
ir_in 1 Instructs the instruction register to store the value on the bus.
cu_step_reset 1 Resets the microcode step counter to 0.
clock_halt 1 Halts the clock module (and thus the entire computer).

A single instruction needs multiple steps (data transfers between modules, or operations on data by a module) to complete. See the Micro Code section for more details.

Implementation

EEPROMs

The control signals to set are decided by a large combinatorial logic setup. The instruction byte, flag bits and microcode step bits form the input and the varying control signals are the output.

There are 4 EEPROM chips, they are all fed the same input as an address. Each EEPROM is programmed so that at the address corresponding to the input bits, 8 of the control signals are stored as data. Each EEPROM holds an 8 bit wide “slice” of the output control signals.

This is visible in the logic block diagram:

_images/logic_block.png

The EEPROMs are in a vertical line, all fed the same inputs and each EEPROM outputs it’s own slice.

Mirror Registers

As per the video by James Bates, mirror registers are used to store the instruction byte and flag bits on a rising control_clock. This is so that the control signals remain constant when the data_clock rises.

The instruction byte and flags bits partly determine the control signals, having the control signals change while the clock is rising could lead to unpredictable results.

The circled area below demonstrates the problem. The rising data clock and control signals change at almost same time. The EEPROM outputs settling and whatever propagation delay happens to have accumulated elsewhere in the computer affect the exact timing:

_images/instruction_change_problem.png

With the mirror register we can control the time that the control signals change to be at a safe distance from the rising data_clock edge:

_images/instruction_change_fixed.png
Microcode Steps

A 4 bit counter is used to keep track of the microcode steps in each instruction. There are a maximum of 8 steps in any one instruction so only 3 bits are used. The count is increased on each rising control_clock. The control unit can reset the count before the 8th step is reached to save executing “empty” micro cycles. This is achieved synchronously enabling the parallel load functionality of the 74HCT161. For more details about the microcode steps see the Micro Code section.

Hardware

The following electronics are used:

  • A 74HCT377 is used for the mirror instruction register.
  • A 74HCT173 is used for the mirror flag bits.
  • A 74HCT04 is used to invert the incoming control signal that causes the counter to reset and the master reset signal.
  • A 74HCT161 is used to provide the counting, loading, and resetting behaviour (much like the program counter).
  • A 74HCT138 is used to convert the 3 bit binary number of the microcode step to an individual signal for each step (purely for aesthetic/blinky blinky reasons :))
  • 4 x AT28C256 EEPROM chips are used to hold the combinational logic/microcode.
  • LEDs and resistors are used to provide display of the data.

They are laid out as follows:

  • Step counter, mirror flags and mirror instruction byte.
  • Display of the above and microcode step format conversion.
  • EEPROMs 2 and 3
  • EEPROMs 0 and 1
  • Control signal output and display.
_images/control_unit_bb.png

Arithmetic Logic Unit

The Arithmetic Logic Unit (ALU) performs arithmetical and logical operations using one or both of it’s inputs. The result is stored internally when desired and the value of that internal storage is also output when desired.

As well as calculating the result, pieces of information (flags) about the result or the two inputs are also stored internally when desired and the state of that internal storage is always output.

Interface and Operation

This is the interface of the ALU:

_images/alu_block.png

This is how it operates:

Name Bit width Description
carry_in 1 If high, supply a carry in to the arithmetical operation. For subtraction operations this becomes an active low borrow_in.
M 1 Choose between arithmetical and logical operations.
S0-3 4 Specify which arithmetical or logical operation.
store_result 1 While high, the result of the operation will be stored internally on a rising clock egde.
store_flags 1 While high, flags resulting from the current operation/inputs/result will be stored internally on a rising clock egde.
output_stored_result 1 Assert the value of the stored result onto the result_stored connection.
clock 1 A rising edge triggers result and flag storage if enabled.
A 8 The A input to the operation.
B 8 The B input to the operation.
result_live 8 The result of the current operation with the current inputs.
result_stored 8 The value of the stored result while output_stored_result is high, not connected otherwise.
flags_live 4 Flags resulting from the current operation/inputs/result.
flags_stored 4 The value of the stored flags.

carry_in, M, and S0-3 are used to select from the available operations (from the datasheet).:

_images/operation_select.jpg

Not all of the operations are available for use in the computer, see the Language section for more details on which are available.

The output flags are:

Name Description
zero The output of the ALU is zero (All bits 0)
negative The output of the ALU is negative (when the 8 bits are read in 2’s compliment form. Also the same as the most significant bit being 1)
carry_borrow If the operation was an addition and the value is high, there was a carry bit, if low, no carry. If the operation was a subtraction and the value is low, there was a borrow, if high, no borrow.
equality When the ALU is in the appropriate mode, this flag indicates the A and B inputs are equal.

For the comparison operators, the datasheet states that :

Note

The ‘LS181 or ‘S181’ can be used as a comparator. The A = B output is internally decoded from the function outputs (F0, F1, F2, F3) so that when two words of equal magnitude are applied at the A and B inputs, it will assume a high level to indicate equality (A=B). The ALU must be in subtract mode with Cn = H when performing this comparison.

When using active high data this doesn’t seem to be the case, the carry input needs to be low so that the ALU is in A MINUS B MINUS 1 mode. This endes up making the comparison table below the above message in the datasheet as follows:

INPUT Cn OUTPUT C n+4 ACTIVE HIGH DATA
L L A <= B
L H A > B
H L A < B
H H A >= B

Implementation

The logical arrangement of the ALU is like this:

_images/alu_logic_layout.png

A Safe Clock Enable circuit is only required in the Logisim version. It’s natively implemented in the 74HCT377 and 74HCT173 chips.

OR gates are used to OR all the bits together and then the result inverted to calculate the zero flag.

The most significant bit of the output is the negative flag.

The carry_borrow flag and the equality flag are output from the ALU (the carryborrow flag is inverted).

The following electronics are used:

  • 2 x 74LS181 are used for the arithmetic and logic operations.
  • A 74CHT00 is used to AND the two A=B outputs (unecessary due to A=B outputs being open collector) and invert carry_borrow_out.
  • A 74HCT173 is used to store the flags.
  • 2 x 74HCT32s are used to OR all the bits to check if it’s zero.
  • A 74HCT04 is used to invert the result of the OR zero check, the store_flags control signal and the carry_borrow input signal.
  • A 74HCT245 is used to provide tri-state buffering for result_stored to go onto the bus.
  • A 74HCT377 stores the result of the operation from result_live.
  • Another 74HCT04 is used to invert the store_result and output_stored_result signals as this inputs are active low.

The ALU resides on three breadboards. From top to bottom:

  • ALU chips
  • Zero checking and flag storage
  • Result storage and output
_images/alu_bb.png

Language

The language of the computer is broadly defined with the following terms:

Name Description
Assembly / Assembly code Collective name for operations in sequence to form a program. The input to the assembler.
Token A set of characters separated from other characters by spaces at the beginning and end. E.g the assembly line LOAD [#123] B has 3 tokens: LOAD [#123] and B.
Operation A specific, simple step that the computer can perform. E.g. add the value in a given register to the accumulator, or copy a value in one register to another.
Operation code / Op code A unique code used to identify an operation, e.g. AND, JUMP, or ADD.
Operation Argument A value passed to an operation to specify it’s behaviour. E.g. passing B to the ADD operation to specify that the value in register B should be added to the accumulator register.
Instruction A fully specified operation, e.g. a copy from B to C or setting the A register to a value. Effectively a line of assembly.
Instruction byte A byte that uniquely identifies an instruction.
Machine code Collective name for the bytes in program memory that form the instructions and constants of a program. The assembler generates machine code.
Machine code byte A byte that makes up machine code. Could be an instruction or an constant value.
Microcode The pattern of bits that determine the control signals to operate the computer to complete an instruction. The Control Unit contains microcode.
Microcode Step A single transfer of data via the bus or action of a module occurring on a rising clock edge. The smallest, most specific level of control. An instruction is completed by doing a number of microcode steps.

See the language table (or download it) for a complete listing of all the machine code and operations with their arguments. The table is sortable by clicking on the headers (but it’s a little slow).

Assembly

Assembly code provides a way to specify instructions for the computer to perform in a more human readable from than machine code

Assembly operations and arguments to specify their behaviour can be saved in an assembly file and passed to an assembler to convert them to machine code that the computer can then execute.

These are the operations and other assembly constructs that can be used to create a valid assembly file.

Arithmetic Operations

ADD

The ADD operation adds the value held in the specified module (or a constant) to the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • ADD A
  • ADD B
  • ADD C
  • ADD CONST
ADDC

The ADDC operation adds the value held in the specified module (or a constant) to the accumulator. If the carry flag is high, an additional 1 is added. The ALU flags generated by this operation are stored.

The possible usages are:

  • ADDC A
  • ADDC B
  • ADDC C
  • ADDC CONST
SUB

The SUB operation subtracts the value held in the specified module (or a constant) from the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • SUB A
  • SUB B
  • SUB C
  • SUB CONST
SUBB

The SUBB operation subtracts the value held in the specified module (or a constant) from the accumulator. If the borrow flag is high an additional 1 is subtracted. The ALU flags generated by this operation are stored.

The possible usages are:

  • SUBB A
  • SUBB B
  • SUBB C
  • SUBB CONST
LSHIFT

The LSHIFT operation moves all the bits in the specified module one place to the left (toward the most significant bit) in place. A zero is added in the rightmost (least significant bit) place. The ALU flags generated by this operation are stored.

The possible usages are:

  • LSHIFT ACC
  • LSHIFT A
  • LSHIFT B
  • LSHIFT C
LSHIFTC

The LSHIFTC operation moves all the bits in the specified module one place to the left (toward the most significant bit) in place. If the carry flag is high, a 1 is added in the rightmost (least significant bit) place. If the flag is low, the rightmost place is left as 0. The ALU flags generated by this operation are stored.

The possible usages are:

  • LSHIFT ACC
  • LSHIFT A
  • LSHIFT B
  • LSHIFT C
INCR

The INCR operation adds one to the given argument (in place). The ALU flags generated by this operation are stored.

The possible usages are:

  • INCR ACC
  • INCR A
  • INCR B
  • INCR C
DECR

The DECR operation subracts one from the given argument (in place). The ALU flags generated by this operation are stored.

The possible usages are:

  • DECR ACC
  • DECR A
  • DECR B
  • DECR C

Data Operations

COPY

The COPY operation copies the value from a source module to a destination module. This overwrites the current value of the destination register. It requires a single machine code byte in program memory.

It is used by specifying the source module as the first argument and the destination module as the second.

The possible usages are:

  • COPY ACC A
  • COPY ACC B
  • COPY ACC C
  • COPY ACC SP
  • COPY A ACC
  • COPY A B
  • COPY A C
  • COPY A SP
  • COPY B ACC
  • COPY B A
  • COPY B C
  • COPY B SP
  • COPY C ACC
  • COPY C A
  • COPY C B
  • COPY C SP
  • COPY PC ACC
  • COPY PC A
  • COPY PC B
  • COPY PC C
  • COPY PC SP
  • COPY SP ACC
  • COPY SP A
  • COPY SP B
  • COPY SP C
LOAD

The LOAD operation loads a value from data memory into a module.

It is used by specifying the position in memory as the first argument and the destination module as the second. The position in memory can be a module or a constant and is encased in square parentheses.

The possible usages are:

  • LOAD [ACC] ACC
  • LOAD [ACC] A
  • LOAD [ACC] B
  • LOAD [ACC] C
  • LOAD [A] ACC
  • LOAD [A] A
  • LOAD [A] B
  • LOAD [A] C
  • LOAD [B] ACC
  • LOAD [B] A
  • LOAD [B] B
  • LOAD [B] C
  • LOAD [C] ACC
  • LOAD [C] A
  • LOAD [C] B
  • LOAD [C] C
  • LOAD [PC] ACC
  • LOAD [PC] A
  • LOAD [PC] B
  • LOAD [PC] C
  • LOAD [SP] ACC
  • LOAD [SP] A
  • LOAD [SP] B
  • LOAD [SP] C
  • LOAD [CONST] ACC
  • LOAD [CONST] A
  • LOAD [CONST] B
  • LOAD [CONST] C
STORE

The STORE operation stores a value from a module in memory.

It is used by specifying the module as the first argument and the location in memory as the second. The location in memory can be a module or a constant and is encased in square parentheses.

The possible usages are:

  • STORE ACC [ACC]
  • STORE ACC [A]
  • STORE ACC [B]
  • STORE ACC [C]
  • STORE ACC [PC]
  • STORE ACC [SP]
  • STORE ACC [CONST]
  • STORE A [ACC]
  • STORE A [A]
  • STORE A [B]
  • STORE A [C]
  • STORE A [PC]
  • STORE A [SP]
  • STORE A [CONST]
  • STORE B [ACC]
  • STORE B [A]
  • STORE B [B]
  • STORE B [C]
  • STORE B [PC]
  • STORE B [SP]
  • STORE B [CONST]
  • STORE C [ACC]
  • STORE C [A]
  • STORE C [B]
  • STORE C [C]
  • STORE C [PC]
  • STORE C [SP]
  • STORE C [CONST]
  • STORE PC [ACC]
  • STORE PC [A]
  • STORE PC [B]
  • STORE PC [C]
  • STORE PC [PC]
  • STORE PC [SP]
  • STORE PC [CONST]
PROGLOAD

The PROGLOAD operation loads a value from program memory into the ACC module.

It is used by specifying the position in program memory as the single argument. The position in memory can be a module or a constant and is encased in square parentheses.

The possible usages are:

  • PROGLOAD [ACC]
  • PROGLOAD [A]
  • PROGLOAD [B]
  • PROGLOAD [C]
  • PROGLOAD [PC]
  • PROGLOAD [SP]
  • PROGLOAD [CONST]
PROGSTORE

The PROGSTORE operation stores the value in the ACC module into program memory.

It is used by specifying the position in program memory as the single argument. The position in memory can be a module or a constant and is encased in square parentheses.

The possible usages are:

  • PROGSTORE [ACC]
  • PROGSTORE [A]
  • PROGSTORE [B]
  • PROGSTORE [C]
  • PROGSTORE [PC]
  • PROGSTORE [SP]
  • PROGSTORE [CONST]
PUSH

The PUSH operation takes a value in a module and add it to the top of the stack.

The stack grows downwards in memory, starting at address 255. The SP module is used to keep track of the top of the stack. The value in SP points at the current top of the stack. SP should be initialised to 0 so that the first push will put the value at address 255. The push first decrements SP, then stores the value in memory at the new value of SP.

The flags generated while decrementing SP are not stored.

The push operation is used by specifying the module to push onto the stack as the first and only argument.

The possible usages are:

  • PUSH ACC
  • PUSH A
  • PUSH B
  • PUSH C
  • PUSH PC
POP

The POP operation takes the value from the top of the stack and copies it to a module.

The value currently at top of the stack is pointed to by SP. A pop will first copy the value at the top of the stack into a module, then increment SP (the stack grows downwards in memory from address 255).

The flags generated while incrementing SP are not stored.

The pop is used by specifying the module to pop the value off the stack into as the first and only argument.

The possible usages are:

  • POP ACC
  • POP A
  • POP B
  • POP C
SET

The SET operation will set a module in the computer to a given constant value.

It is used by specifying a module as the first argument, then the value to set it to as a constant.

It requires two machine code bytes in program memory. Consider the SET_ZERO operation if the constant is zero.

The possible usages are:

  • SET ACC CONST
  • SET A CONST
  • SET B CONST
  • SET C CONST
  • SET SP CONST
SET_ZERO

The SET_ZERO operation will set a module in the computer to zero.

The ALU flags generated by this operation are not stored.

It is used by specifying a module as the first and only argument.

The possible usages are:

  • SET_ZERO ACC
  • SET_ZERO A
  • SET_ZERO B
  • SET_ZERO C

Program Control Operations

NOOP

The NOOP does nothing - no module transfers occur on the bus for one instruction cycle.

The possible usages are:

  • NOOP
JUMP

The JUMP operation will set the program counter to a value.

The possible usages are:

  • JUMP ACC
  • JUMP A
  • JUMP B
  • JUMP C
  • JUMP SP
  • JUMP CONST
  • JUMP [ACC]
  • JUMP [A]
  • JUMP [B]
  • JUMP [C]
  • JUMP [SP]
  • JUMP [PC]
  • JUMP [CONST]
JUMP_IF_LT_ACC

The JUMP_IF_LT_ACC operation will set the program counter (jump) to the value of a given constant (second argument) if the value of the first argument (module or constant) is less than the accumulator.

The instruction generates and stores (clobbers) the ALU flags.

The possible usages are:

  • JUMP_IF_LT_ACC A CONST
  • JUMP_IF_LT_ACC B CONST
  • JUMP_IF_LT_ACC C CONST
  • JUMP_IF_LT_ACC PC CONST
  • JUMP_IF_LT_ACC SP CONST
  • JUMP_IF_LT_ACC CONST CONST
JUMP_IF_LTE_ACC

The JUMP_IF_LTE_ACC operation will set the program counter (jump) to the value of a given constant (second argument) if the value of the first argument (module or constant) is less than or equal to the accumulator.

The instruction generates and stores (clobbers) the ALU flags.

The possible usages are:

  • JUMP_IF_LTE_ACC A CONST
  • JUMP_IF_LTE_ACC B CONST
  • JUMP_IF_LTE_ACC C CONST
  • JUMP_IF_LTE_ACC PC CONST
  • JUMP_IF_LTE_ACC SP CONST
  • JUMP_IF_LTE_ACC CONST CONST
JUMP_IF_EQ_ACC

The JUMP_IF_EQ_ACC operation will set the program counter (jump) to the value of a given constant (second argument) if the value of the first argument (module or constant) is equal to the accumulator.

The instruction generates and stores (clobbers) the ALU flags.

The possible usages are:

  • JUMP_IF_EQ_ACC A CONST
  • JUMP_IF_EQ_ACC B CONST
  • JUMP_IF_EQ_ACC C CONST
  • JUMP_IF_EQ_ACC PC CONST
  • JUMP_IF_EQ_ACC SP CONST
  • JUMP_IF_EQ_ACC CONST CONST
JUMP_IF_GTE_ACC

The JUMP_IF_GTE_ACC operation will set the program counter (jump) to the value of a given constant (second argument) if the value of the first argument (module or constant) is greater than or equal to the accumulator.

The instruction generates and stores (clobbers) the ALU flags.

The possible usages are:

  • JUMP_IF_GTE_ACC A CONST
  • JUMP_IF_GTE_ACC B CONST
  • JUMP_IF_GTE_ACC C CONST
  • JUMP_IF_GTE_ACC PC CONST
  • JUMP_IF_GTE_ACC SP CONST
  • JUMP_IF_GTE_ACC CONST CONST
JUMP_IF_GT_ACC

The JUMP_IF_GT_ACC operation will set the program counter (jump) to the value of a given constant (second argument) if the value of the first argument (module or constant) is greater than the accumulator.

The instruction generates and stores (clobbers) the ALU flags.

The possible usages are:

  • JUMP_IF_GT_ACC A CONST
  • JUMP_IF_GT_ACC B CONST
  • JUMP_IF_GT_ACC C CONST
  • JUMP_IF_GT_ACC PC CONST
  • JUMP_IF_GT_ACC SP CONST
  • JUMP_IF_GT_ACC CONST CONST
JUMP_IF_EQ_ZERO

The JUMP_IF_EQ_ZERO operation will set the program counter (jump) to the value of a given constant (second argument) if the value of the first argument (a module) is equal to zero.

The instruction generates and stores (clobbers) the ALU flags.

The possible usages are:

  • JUMP_IF_EQ_ZERO ACC CONST
  • JUMP_IF_EQ_ZERO A CONST
  • JUMP_IF_EQ_ZERO B CONST
  • JUMP_IF_EQ_ZERO C CONST
  • JUMP_IF_EQ_ZERO PC CONST
  • JUMP_IF_EQ_ZERO SP CONST
JUMP_IF_POSITIVE_FLAG

The JUMP_IF_POSITIVE_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for resulted in a positive value (when read as 2’s compliment).

The possible usages are:

  • JUMP_IF_POSITIVE_FLAG CONST
JUMP_IF_NEGATIVE_FLAG

The JUMP_IF_NEGATIVE_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for resulted in a negative value (when read as 2’s compliment).

The possible usages are:

  • JUMP_IF_NEGATIVE_FLAG CONST
JUMP_IF_OVERFLOW_FLAG

The JUMP_IF_OVERFLOW_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for resulted in an overflow.

The possible usages are:

  • JUMP_IF_OVERFLOW_FLAG CONST
JUMP_IF_NOT_OVERFLOW_FLAG

The JUMP_IF_OVERFLOW_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for did not result in an overflow.

The possible usages are:

  • JUMP_IF_NOT_OVERFLOW_FLAG CONST
JUMP_IF_UNDERFLOW_FLAG

The JUMP_IF_UNDERFLOW_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for resulted in an underflow.

The possible usages are:

  • JUMP_IF_UNDERFLOW_FLAG CONST
JUMP_IF_NOT_UNDERFLOW_FLAG

The JUMP_IF_NOT_UNDERFLOW_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for did not result in an underflow.

The possible usages are:

  • JUMP_IF_NOT_UNDERFLOW_FLAG CONST
JUMP_IF_ZERO_FLAG

The JUMP_IF_ZERO_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for resulted in an answer of zero.

The possible usages are:

  • JUMP_IF_ZERO_FLAG CONST
JUMP_IF_NOT_ZERO_FLAG

The JUMP_IF_NOT_ZERO_FLAG operation will set the program counter to the value of a given constant if the last operation that the ALU flags were stored for resulted in a non zero answer.

The possible usages are:

  • JUMP_IF_NOT_ZERO_FLAG CONST
CALL

The CALL operation will push the current program counter (i.e. the next instruction to be executed) onto the stack, then set the program counter ( i.e. jump) to the value in the given module or constant.

The possible usages are:

  • CALL ACC
  • CALL A
  • CALL B
  • CALL C
  • CALL CONST
RETURN

The RETURN operation will pop the top of the stack into the program counter.

It expects to be used after having arrived at a section of assembly with the CALL instruction.

The possible usages are:

  • RETURN
HALT

The HALT operation halts execution of the computer by stopping the clock.

The possible usages are:

  • HALT

Logical Operations

NOT

The NOT operation inverts all the bits of the specified module in place. The ALU flags generated by this operation are stored.

The possible usages are:

  • NOT ACC
  • NOT A
  • NOT B
  • NOT C
AND

The AND operation performs a logical AND with the value held in the specified module (or a constant) and the accumulator. The result is stored in the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • AND A
  • AND B
  • AND C
  • AND CONST
NAND

The NAND operation performs a logical NAND with the value held in the specified module (or a constant) and the accumulator. The result is stored in the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • NAND A
  • NAND B
  • NAND C
  • NAND CONST
OR

The OR operation performs a logical OR with the value held in the specified module (or a constant) and the accumulator. The result is stored in the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • OR A
  • OR B
  • OR C
  • OR CONST
NOR

The NOR operation performs a logical NOR with the value held in the specified module (or a constant) and the accumulator. The result is stored in the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • NOR A
  • NOR B
  • NOR C
  • NOR CONST
XOR

The XOR operation performs a logical XOR with the value held in the specified module (or a constant) and the accumulator. The result is stored in the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • XOR A
  • XOR B
  • XOR C
  • XOR CONST
NXOR

The NXOR operation performs a logical NXOR (an XOR, then inverted) with the value held in the specified module (or a constant) and the accumulator. The result is stored in the accumulator. The ALU flags generated by this operation are stored.

The possible usages are:

  • NXOR A
  • NXOR B
  • NXOR C
  • NXOR CONST

Miscellaneous Operations

ROT_LEFT

The ROT_LEFT operation moves all the bits in the number one place to the left (most significant side), adding a 0 on the least significant side. If the most significant bit was a 1, then after the rotation this is set back on the least significant side.

This operation will generate and store (clobber) ALU flags.

The possible usages are:

  • ROT_LEFT ACC
  • ROT_LEFT A
  • ROT_LEFT B
  • ROT_LEFT C

Constants

Constants are values that the assembler will convert to machine code bytes for operations that require data in the machine code. For example, a jump to an explicit index in program memory, or setting a register to an explicit value.

There are 3 kinds of constants: labels, variables and numbers.

Labels

A label binds to the line of assembly that follows it. Once assembly is complete the label’s value is the index in program memory of the instruction byte that followed the label definition. E.g. If an assembly file looked like this:

    LOAD [#123] A
    ADD A

@label
    SET B #42

The value of @label would be 3. The instruction byte corresponding to SET B #42 is at program memory index 3. LOAD [#123] A takes 2 bytes, ADD A one, and SET B #42 is the byte after that.

Labels are typically used by jump operations.

A label is a token that starts with the @ character followed by any letter or an underscore, then any alphanumeric or an underscore. E.g.:

  • @label
  • @label_1
  • @_other_label

Labels must be unique.

A label is defined by putting it on a line by itself.

Variables

Variables are named aliases for indexes into data memory. They can be predeclared by putting them by themselves on a line or declared as they are used by using them as an argument.

The index for a given variable is determined by the assembler. As it parses assembly lines from the start of the file to the end, addresses are assigned to variables as they are encountered in the file. E.g. for the following assembly:

$variable1
COPY A ACC
LOAD [$variable2] A

variable1 is predeclared, variable2 is declared as it’s used. Once assembled, variable1 is an alias for 0, variable2 is an alias for 1.

A variable is a token that starts with the $ character followed by any letter or an underscore, then any alphanumeric or an underscore. E.g.:

  • $variable
  • $variable1
  • $_other_variable
Numbers

Numbers are integer values. In most cases they within the range -127 to 255 (inclusive). This range comes from the minimum and maximum values that 8 bits, or 8 bits with 2’s compliment encoding can hold.

A number is a token that starts with the # character and is followed by any valid Python integer definition. E.g.

  • #123 (decimal)
  • #-5 (decimal)
  • #0b00010010 (binary)
  • #-0b0101 (binary)
  • #0xA2 (hex)
  • #0o107 (octal)

Comments

Comments are parts of the assembly file ignored by the assembler.

A comment is anything after and including // on a line until the end of the line.

Machine Code

The computer is directly controlled by machine code. It is stored in program memory. The machine code is stored as 8 bit bytes.

Machine code consists of instruction bytes and constant bytes. Instruction bytes encode a particular instruction (e.g. copying the value in register A to register B), constant bytes encode a value that an operation may require (e.g. setting the A register to 42).

There are 256 possible instruction bytes, most of these are occupied by the instruction set. They are organised using the grouping described below. This is very much inspired by how James Bates organised his machine code.

See the language table (or download it) for a complete listing of all the machine code and operations with their arguments. The table is sortable by clicking on the headers (but it’s a little slow).

Instruction Groups

The first two bytes of an instruction byte always represent the instruction group. There are 4 groups:

Bit value Group Name
00...... Copy
01...... Load
10...... Store
11...... ALU

Sources and destinations

For copy, load and store instructions, the third to fifth, and sixth to eighth bytes are the source and destination respectively.

The table below only shows the source codes for brevity. The destination bits are the last 3 bits, e.g.: .....000 and have the same name and meaning.

Bit value Name Meaning
..000... ACC The accumulator register.
..001... A The A register.
..010... B The B register.
..011... C The C register.
..100... SP The stack pointer.
..101... PC The program counter
..110... SP+/- The stack pointer, preceded or followed by incrementing or decrementing it.
..111... CONST A constant value.

ALU Operations

There are 16 ALU operations and they are identified with bits 3-6 of the instruction byte when the operation group is ALU. The operations and codes are:

Bit value Name Meaning
110000.. ZERO The argument will be set to zero.
110001.. INCR The argument supplied will be incremented by 1.
110010.. DECR The argument supplied will be decremented by 1.
110011.. ADD The argument will be added to the accumulator.
110100.. ADDC The argument will be added to the accumulator and one will be added if the last add resulted in a carry.
110101.. SUB The argument will be subtracted from the accumulator.
110110.. SUBB The argument will be subtracted from the accumulator and one will be subtracted if the last subtraction resulted in a borrow.
110111.. AND The argument will be ANDed with the accumulator.
111000.. NAND The argument will be NANDed with the accumulator.
111001.. OR The argument will be ORed with the accumulator.
111010.. NOR The argument will be NORed with the accumulator.
111011.. XOR The argument will be XORed with the accumulator.
111100.. NXOR The argument will be NXORed with the accumulator.
111101.. NOT The argument will have all it’s bits inverted
111110.. LSHIFT All the bits in the argument will move one place to the left (toward the most significant bit)
111111.. LSHIFTC All the bits in the argument will move one place to the left (toward the most significant bit). If the last shift resulted in a carry then the least significant bit is set to 1.

ALU Arguments

ALU operations work on an argument. This is specified with bits 7 and 8 of the instruction byte when the operation group is ALU. The arguments and codes are:

Bit value Argument
11....00 ACC/CONST
11....01 A
11....10 B
11....11 C

Instruction byte gaps

Not all source and destination combinations are valid or make sense. For example, copying the value in Register A to Register A has no purpose. In these cases, those instructions are re purposed for other instructions.

These “instruction byte gaps” are:

Instruction byte(s) Explanation Used by
  • 00000000
  • 00001001
  • 00010010
  • 00011011
  • 00100100
  • 00101101
  • 00110110
  • 00111111
Copying a register to itself. JUMP_IF_XXX_FLAG
00110... Copy from SP+/-. Ambiguous. JUMP_IF_LT_ACC
00...110 Copy to SP+/-. Ambiguous. JUMP_IF_LTE_ACC
00...111 Copy to a constant. Constants cannot be written to. JUMP_IF_EQ_ACC
01...100 Loading into SP. SP has a dedicated register, instead a load to a register then copy. JUMP_IF_GTE_ACC
01...110 Loading into SP+/-. SP+/- cannot be written to. CALL
01...111 Loading into a constant. Constants cannot be written to. PROGRAM_LOAD
10110... Storing SP+/-. Ambiguous. JUMP_IF_GT_ACC
10100... Storing SP. SP has a dedicated register, instead copy to a register and store. JUMP_IF_EQ_ZERO
10111... Storing a constant value. Instead Set a register and store. PROGRAM_STORE

Fetch

To execute an instruction, the instruction byte must be loaded from program memory into the instruction register.

This is handled by the first two steps of every instruction which:

  • Load the program counter into the memory address register.
  • Load the instruction register with the data from program memory at increment the program counter ready for the next instruction.

Micro Code

Microcode is the encoding of what specific steps the computer should take to complete an instruction.

It is effectively a large combinational logic circuit where the inputs are the instruction byte, microcode step and flag bits and the outputs are the control signals to drive the modules. EEPROM chips are programmed and used to implement this combinational logic circuit. The same address is fed into 4 chips, differently programmed to get the 30 output bits.

Every instruction is comprised of up to six micro code steps. There are eight available but the first two are reserved for fetching the instruction byte itself. The steps are executed sequentially to perform the instruction. The microcode step counter controls the order of the sequence. The flags bits allow conditional operation based on a given instruction byte and step. An instruction can “surrender” it’s remaining steps and move onto the next instruction if it has completed all it’s necessary steps.

Address bits

The address bits for the EEPROM and their meanings are:

Bits Meaning
xxxxxxxx....... Instruction byte
........xxxx... Flags (Equal, Carry/Borrow, Negative, Zero)
............xxx Microcode step

Output bits

The output bits for the EEPROMs and their meanings (which will typically occur on the next rising data clock edge) are:

Bits Name Description
........ ........ ........ .......1 ACC_IN Enable input for the accumulator register.
........ ........ ........ ......1. ACC_OUT Enable output for the accumulator register.
........ ........ ........ .....1.. A_IN Enable input for the A register.
........ ........ ........ ....1... A_OUT Enable output for the A register.
........ ........ ........ ...1.... B_IN Enable input for the B register.
........ ........ ........ ..1..... B_OUT Enable output for the B register.
........ ........ ........ .1...... C_IN Enable input for the C register.
........ ........ ........ 1....... C_OUT Enable output for the C register.
........ ........ .......1 ........ ALU_STORE_RESULT Store the current output of the ALU.
........ ........ ......1. ........ ALU_STORE_FLAGS Store the current flags of the ALU..
........ ........ .....1.. ........ ALU_OUT Enable output for the ALU.
........ ........ ....1... ........ ALU_A_IS_BUS Set the A input of the ALU to be the bus (otherwise it is the content of the accumulator register).
........ ........ ...1.... ........ ALU_S0 Set the S0 function select input on the ALU.
........ ........ ..1..... ........ ALU_S1 Set the S1 function select input on the ALU.
........ ........ .1...... ........ ALU_S2 Set the S2 function select input on the ALU.
........ ........ 1....... ........ ALU_S3 Set the S3 function select input on the ALU.
........ .......1 ........ ........ ALU_M Set the M input on the ALU.
........ ......1. ........ ........ ALU_C_IN Set the carry in input on the ALU.
........ .....1.. ........ ........ MAR_IN Enable input for the memory address register.
........ ....1... ........ ........ RAM_IN Enable input for the RAM.
........ ...1.... ........ ........ RAM_OUT Enable output for the RAM.
........ ..1..... ........ ........ RAM_SEL_PROG_MEM Retrieve data from program memory rather than data memory.
........ .1...... ........ ........ SP_IN Enable input for the stack pointer.
........ 1....... ........ ........ SP_OUT Enable output for the stack pointer.
.......1 ........ ........ ........ PC_IN Enable input for the program counter.
......1. ........ ........ ........ PC_OUT Enable output for the program counter.
.....1.. ........ ........ ........ PC_COUNT Increment the value stored in the program counter.
....1... ........ ........ ........ IR_IN Enable input for the instruction register.
...1.... ........ ........ ........ CU_STEP_RESET Reset the step counter in the control unit.
..1..... ........ ........ ........ CLOCK_HALT Halt the computer.

Hardware

HCT vs. LS

Fanout

Materials and Tools

Edge Detection

Debouncing

Safe Clock Enable

Makes sure that when reset is released, only the next rising clock edge is passed on. If only an AND gate was used, a rising edge would pass through if the clock was already high, and (an inverted) reset signal went low.

Open Collector Outputs

Peripherals

EEPROM Programmer

The EEPROM programmer is used to read and write data from/to the EEPROM chips. It’s loosely based on the EEPROM Programmer by Ben Eater.

Hardware

The EEPROM programmer uses an Arduino Mega rather than a Nano as extra flash storage space was required to fit all the ROM bytes on the Arduino.

It is wired up as follows:

_images/eeprom_programmer_bb.png

The three buttons from left to right control:

  • Which ROM (0-3) to write to the EEPROM.
  • Which mode the programmer is in (read or write).
  • When to perform the read or write (the “Go” button).

The red LEDs indicate which ROM is selected (the leftmost LED is 0, the one to the right of that 1, and so on).

The green LEDs indicate which mode, the left LED means read mode, the right LED means write mode.

When reading, the contents of the EEPROM are sent over the Arduino Serial port to the monitor. When writing, updates on the progress of the write are sent over the Arduino Serial port to the monitor.

Software

The Arduino sketch to read and write the ROMS can be found in the Arduino section section of the project

Page Write

Unlike the smaller EEPROM used by Ben Eater, the larger AT28C256 EEPROM used in this computer writes bytes in 64 byte pages. This means that sequential writes of more than 64 bytes, too close together in time will eventually fail as the chip enters a write period and then subsequent writes will not be successful.

To avoid this it’s possible to:

  • Use the chips built in polling feature to detect the end of a write period.
  • Only write one page worth of bytes at a time.

This sketch uses the latter approach, and pauses longer than the maximum specified write period (10ms from the datasheet) between each page to let the write operation complete.

Maximum Array Size

The maximum array size on an Adruino is 32767 bytes. As the ROM is 32768 bytes this means the last byte of the array needs to be stored separately. This page was helpful to clarify this.

Large amounts of PROGMEM data

The PROGMEM macro in Arduino allows you to compile data into program memory rather than being declared as data in RAM as it typically is.

When storing large amounts of data this way the compiler needs extra instructions to place the data correctly so instead of using the typical PROGMEM macro, __attribute__ (( __section__(".fini1") )) needs to be used instead. The fini1 can be replaced with fini<int> for each large chunk. (This a vast simplification/assumption). A post on the Arduino forums helped clarify this.

The typical pgm_read_byte_near function also needs to be replaced with pgm_read_byte_far which needs an address returned by pgm_get_far_address which must be passed a compile time constant. This post on the AVRFreaks forums helped clarify this.

Address and Data Input

_images/address_data_input_bb.png

User Control

_images/user_control_bb.png

User Control Debounce

_images/user_control_debounce_bb.png

Software

Assembler

The assembler module is responsible for taking lines of assembly code and processing it to generate equivalent machine code.

It is passed a list of strings which are the lines of the assembly file. Each line is then processed and the information about the line stored in a dictionary.

During processing each line is checked to see if it’s a constant definition, if not, it’s treated as an assembly line and parsed into machine code bytes.

The line is passed to each operation to attempt to generate the machine code bytes. The operations can expect certain tokens on the line to be constants and are identified as such and returned to the assembler. The constants are then validated and identified and the machine code bytes added to the dictionary of information about the line of assembly.

With all the lines processed, machine code bytes generated and constants identified, the assembler checks for overall validity and structure The assembler then performs global operations that need to take the entire assembly code into account:

With these checks, assignments and resolutions complete, the final assembly line dictionaries are returned.

Command Line Tools

ebc-assemble

Assemble eight bit computer assembly files to machine code.

usage: ebc-assemble [-h] [-o OUTPUT_FILENAME_BASE] [-d OUTPUT_DIRECTORY]
                    [-f {logisim,arduino}]
                    asm_filepath
Positional Arguments
asm_filepath Path to the assembly file to assemble.
Named Arguments
-o, --output_filename_base
 Filename base for the assembled file. E.g. “myfile” or “fibonacci”. Do not include an extension.
-d, --output_directory
 Directory for the output filed. Defaults to current directory.
-f, --output_format
 

Possible choices: logisim, arduino

Format to write the assembled code in.

Default: “logisim”

ebc-gen-roms

Generate ROMs that contain the microcode.

usage: ebc-gen-roms [-h] [-o OUTPUT_DIR] [-p FILE_PREFIX]
                    [-f {logisim,arduino}]
Named Arguments
-o, --output_dir
 

Directory to write the ROMs into.

Default: “.”

-p, --file_prefix
 Prefix for the ROM files.
-f, --output_format
 

Possible choices: logisim, arduino

Format to write the ROMs in.

Default: “logisim”

eight_bit_computer package

Subpackages

eight_bit_computer.operations package
Submodules
eight_bit_computer.operations.add module

ADD Operation

eight_bit_computer.operations.add.generate_microcode_templates()[source]

Generate microcode for all the ADD instructions.

Returns:DataTemplates for all the ADD instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.add.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a ADD assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.addc_op module

The ADDC operation

Adds a value to the accumulator, adding an extra 1 if the overflow flag is set.

eight_bit_computer.operations.addc_op.generate_microcode_templates()[source]

Generate microcode for the ADDC instruction.

Returns:DataTemplates for all the ADDC instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.addc_op.generate_signatures()[source]

Generate all the argument signatures for the ADDC operation.

Returns:All possible signatures, See get_arg_def_template() for more information on an argument definition dictionary.
Return type:list(list(dict))
eight_bit_computer.operations.addc_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a ADDC with the given signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular ADDC operation to generate templates for.
Returns:DataTemplates that define the operation with this signature.
Return type:list(DataTemplate)
eight_bit_computer.operations.addc_op.get_calculation_control_steps(signature)[source]

Get control steps that calcuate the new value.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular ADDC operation to generate templates for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
Raises:ValueError – When the signature’s first argument type is not a module name or constant.
eight_bit_computer.operations.addc_op.generate_true_data_templates(instruction_byte_bitdefs, initial_control_steps)[source]

Create datatemplates for an ADDC where an extra bit is needed.

Parameters:
  • instruction_byte_bitdefs (list(str)) – List of the bitdefs that make up the instruction byte.
  • initial_control_steps (list(list(str))) – List of list of bitdefs that specify the control steps.
Returns:

: List of DataTemplates that describe the ADDC for this signature when the carry flag is high.

Return type:

list(DataTemplate)

eight_bit_computer.operations.addc_op.generate_false_data_templates(instruction_byte_bitdefs, initial_control_steps)[source]

Create datatemplates for an ADDC where an extra bit is not needed.

Parameters:
  • instruction_byte_bitdefs (list(str)) – List of the bitdefs that make up the instruction byte.
  • initial_control_steps (list(list(str))) – List of list of bitdefs that specify the control steps.
Returns:

: List of DataTemplates that describe the ADDC for this signature when the carry flag is low.

Return type:

list(DataTemplate)

eight_bit_computer.operations.addc_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular simple ALU operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.addc_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an ADDC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.and_op module

AND Operation

eight_bit_computer.operations.and_op.generate_microcode_templates()[source]

Generate microcode for all the AND instructions.

Returns:DataTemplates for all the AND instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.and_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a AND assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.call_op module

CALL Operation

Push the current program counter (i.e. the next instruction to be executed) onto the stack, then set the program counter (i.e. jump) to the value in the given argument (module or constant).

eight_bit_computer.operations.call_op.generate_microcode_templates()[source]

Generate microcode for all the CALL instructions.

Returns:DataTemplates for all the CALL instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.call_op.generate_signatures()[source]

Generate all the argument signatures for the CALL operation.

Returns:All possible signatures, See get_arg_def_template() for more information on an argument definition dictionary.
Return type:list(list(dict))
eight_bit_computer.operations.call_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a CALL with the given signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular CALL operation to generate templates for.
Returns:Datatemplates that define this CALL.
Return type:list(DataTemplate)
eight_bit_computer.operations.call_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular CALL operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.call_op.generate_control_steps(signature)[source]

Generate control steps for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular CALL operation to generate the control steps for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.call_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a CALL assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.copy_op module

The COPY operation.

Copies a value from one module into another.

eight_bit_computer.operations.copy_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.copy_op.generate_microcode_templates()[source]

Generate microcode for all the COPY operations.

Returns:DataTemplates for all the COPY microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.copy_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a copy with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular copy operation to generate templates for.
Returns:Datatemplates that define this copy.
Return type:list(DataTemplate)
eight_bit_computer.operations.copy_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular copy operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.copy_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a COPY assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.decr_op module

The DECR operation.

Subtracts one from the given argument (in place).

eight_bit_computer.operations.decr_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.decr_op.generate_microcode_templates()[source]

Generate microcode for all the DECR operations.

Returns:DataTemplates for all the DECR microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.decr_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define an DECR with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this not.
Return type:list(DataTemplate)
eight_bit_computer.operations.decr_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.decr_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an DECR assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.fetch module

The fetch steps added to the start of all operations.

eight_bit_computer.operations.fetch.generate_microcode_templates()[source]

Generate datatemplates for all the fetch steps.

Returns:Datatemplates that represent the fetch steps.
Return type:list(DataTemplate)
eight_bit_computer.operations.fetch.fetch_step_0()[source]

Create template for the first fetch step.

Returns:The first fetch step.
Return type:DataTemplate
eight_bit_computer.operations.fetch.fetch_step_1()[source]

Create template for the second fetch step.

Returns:The second fetch step.
Return type:DataTemplate
eight_bit_computer.operations.halt_op module

The HALT operation.

Halts execution of the computer by stopping the clock.

eight_bit_computer.operations.halt_op.generate_microcode_templates()[source]

Generate microcode for the HALT operation.

Returns:DataTemplates for all the HALT microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.halt_op.generate_instruction_byte_bitdefs()[source]

Generate bitdefs to specify the HALT instruction.

Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.halt_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an HALT assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.incr_op module

The INCR operation.

Adds one to the given argument (in place).

eight_bit_computer.operations.incr_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.incr_op.generate_microcode_templates()[source]

Generate microcode for all the INCR operations.

Returns:DataTemplates for all the INCR microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.incr_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define an INCR with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this incr.
Return type:list(DataTemplate)
eight_bit_computer.operations.incr_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.incr_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an INCR assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump module

JUMP Operation

eight_bit_computer.operations.jump.generate_microcode_templates()[source]

Generate microcode for all the JUMP instructions.

Returns:DataTemplates for all the JUMP instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump.generate_signatures()[source]

Generate all the argument signatures for the jump operation.

Returns:All possible signatures, See get_arg_def_template() for more information on an argument definition dictionary.
Return type:list(list(dict))
eight_bit_computer.operations.jump.generate_operation_templates(signature)[source]

Create the DataTemplates to define a JUMP with the given signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular JUMP operation to generate templates for.
Returns:Datatemplates that define this JUMP.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular JUMP operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.jump.generate_control_steps(signature)[source]

Generate control steps for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular JUMP operation to generate the control steps for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.jump.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a LOAD assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_comparison_base module

Base functionality for the the JUMP_IF_***_ACC operations.

Except JUMP_IF_EQ_ACC

eight_bit_computer.operations.jump_if_comparison_base.generate_microcode_templates(instruction_group, instruction_byte_const_bitdef, instruction_byte_arg_bitdef_dict, alu_flag_gen_bitdefs, true_flag_bitdefs, false_flag_bitdefs)[source]

Generate microcode for this JUMP_IF_***_ACC operations.

Parameters:
  • instruction_group (str) – Bitdef representing the instruction group for the instruction byte.
  • instruction_byte_const_bitdef (str) – Bitdef representing the part of the instruction byte that remains the same regardless of the arguments. Could be on the source side or the dest side.
  • (dist(str (instruction_byte_arg_bitdef_map) – str)): Dictionary that contains the bitdefs which map to the arguments used. On the complementary side (i.e. src vs. dest) to the side used by the instruction_byte_const_bitdef.
  • alu_flag_gen_bitdefs (list(str)) – List of bitdefs that make up the control flags for the ALU to generate the appropriate flags.
  • true_flag_bitdefs (list(str)) – List of bitdef that represent the flag state when the condition is true.
  • false_flag_bitdefs (list(str)) – List of bitdef that represent the flag state when the condition is false.
Returns:

DataTemplates for all the JUMP_IF_***_ACC microcode.

Return type:

list(DataTemplate)

eight_bit_computer.operations.jump_if_comparison_base.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.jump_if_comparison_base.generate_operation_templates(signature, instruction_group, instruction_byte_const_bitdef, instruction_byte_arg_bitdef_dict, alu_flag_gen_bitdefs, true_flag_bitdefs, false_flag_bitdefs)[source]

Create the DataTemplates to define a JUMP_IF_***_ACC with the given args.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
  • instruction_group (str) – Bitdef representing the instruction group for the instruction byte.
  • instruction_byte_const_bitdef (str) – Bitdef representing the part of the instruction byte that remains the same regardless of the arguments. Could be on the source side or the dest side.
  • (dist(str (instruction_byte_arg_bitdef_map) – str)): Dictionary that contains the bitdefs which map to the arguments used. On the complementary side (i.e. src vs. dest) to the side used by the instruction_byte_const_bitdef.
  • alu_flag_gen_bitdefs (list(str)) – List of bitdefs that make up the control flags for the ALU to generate the appropriate flags.
  • true_flag_bitdefs (list(str)) – List of bitdefs that represent the flag state when the condition is true.
  • false_flag_bitdefs (list(str)) – List of bitdefs that represent the flag state when the condition is false.
Returns:

Datatemplates that define this JUMP_IF_***_ACC operation.

Return type:

list(DataTemplate)

eight_bit_computer.operations.jump_if_comparison_base.generate_false_datatemplates(signature, instruction_group, instruction_byte_const_bitdef, instruction_byte_arg_bitdef_dict, alu_flag_gen_bitdefs, flag_bitdefs)[source]

Create DataTemplates to define a conditional jump if condition is false.

This is the case where no jump happens.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
  • instruction_group (str) – Bitdef representing the instruction group for the instruction byte.
  • instruction_byte_const_bitdef (str) – Bitdef representing the part of the instruction byte that remains the same regardless of the arguments. Could be on the source side or the dest side.
  • (dist(str (instruction_byte_arg_bitdef_map) – str)): Dictionary that contains the bitdefs which map to the arguments used. On the complementary side (i.e. src vs. dest) to the side used by the instruction_byte_const_bitdef.
  • alu_flag_gen_bitdefs (list(str)) – List of bitdefs that make up the control flags for the ALU to generate the appropriate flags.
  • flag_bitdefs (list(str)) – List of bitdef that represent the flag state when the condition is false.
Returns:

Datatemplates that define the “false half” of a JUMP_IF_***_ACC operation.

Return type:

list(DataTemplate)

eight_bit_computer.operations.jump_if_comparison_base.generate_nonconditional_steps(signature, alu_flag_gen_bitdefs)[source]

Generate the nonconditional control steps.

These steps generate the flags which then govern whether the jump happens or not.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular operation to generate steps for.
  • alu_flag_gen_bitdefs (list(str)) – List of bitdefs that make up the control flags for the ALU to generate the appropriate flags.
Returns:

List of list of bitdefs that represent the steps, and the control signals at each step.

Return type:

list(list(str))

eight_bit_computer.operations.jump_if_comparison_base.generate_instruction_byte_bitdefs(signature, instruction_group, instruction_byte_const_bitdef, instruction_byte_arg_bitdef_dict)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular operation to generate the instruction byte bitdefs for.
  • instruction_group (str) – Bitdef representing the instruction group for the instruction byte.
  • instruction_byte_const_bitdef (str) – Bitdef representing the part of the instruction byte that remains the same regardless of the arguments. Could be on the source side or the dest side.
  • (dist(str (instruction_byte_arg_bitdef_map) – str)): Dictionary that contains the bitdefs which map to the arguments used. On the complementary side (i.e. src vs. dest) to the side used by the instruction_byte_const_bitdef.
Returns:

Bitdefs that make up the instruction_byte

Return type:

list(str)

eight_bit_computer.operations.jump_if_comparison_base.generate_true_datatemplates(signature, instruction_group, instruction_byte_const_bitdef, instruction_byte_arg_bitdef_dict, alu_flag_gen_bitdefs, flag_bitdefs)[source]

Create DataTemplates to define a conditional jump if condition is true.

This is the case where no jump happens

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
  • instruction_group (str) – Bitdef representing the instruction group for the instruction byte.
  • instruction_byte_const_bitdef (str) – Bitdef representing the part of the instruction byte that remains the same regardless of the arguments. Could be on the source side or the dest side.
  • (dist(str (instruction_byte_arg_bitdef_map) – str)): Dictionary that contains the bitdefs which map to the arguments used. On the complementary side (i.e. src vs. dest) to the side used by the instruction_byte_const_bitdef.
  • alu_flag_gen_bitdefs (list(str)) – List of bitdefs that make up the control flags for the ALU to generate the appropriate flags.
  • flag_bitdefs (list(str)) – List of bitdef that represent the flag state when the condition is true.
Returns:

Datatemplates that define the “true half” of a JUMP_IF_***_ACC operation.

Return type:

list(DataTemplate)

eight_bit_computer.operations.jump_if_comparison_base.parse_line(line, name, instruction_group, instruction_byte_const_bitdef, instruction_byte_arg_bitdef_dict)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_***_ACC assembly line, return an empty list instead.

Parameters:
  • line (str) – Assembly line to be parsed.
  • name (str) – Name of the operation. E.g. JUMP_IF_LT_ACC.
  • instruction_group (str) – Bitdef representing the instruction group for the instruction byte.
  • instruction_byte_const_bitdef (str) – Bitdef representing the part of the instruction byte that remains the same regardless of the arguments. Could be on the source side or the dest side.
  • (dist(str (instruction_byte_arg_bitdef_map) – str)): Dictionary that contains the bitdefs which map to the arguments used. On the complementary side (i.e. src vs. dest) to the side used by the instruction_byte_const_bitdef.
Returns:

List of instruction byte template dictionaries or an empty list.

Return type:

list(dict)

eight_bit_computer.operations.jump_if_eq_acc_op module

The JUMP_IF_EQ_ACC operation.

Sets PC (jumps) to a constant if the module or constant passed as an argument is equal to the value in ACC.

This operation will generate and store (clobber) ALU flags.

eight_bit_computer.operations.jump_if_eq_acc_op.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_EQ_ACC operations.

Returns:DataTemplates for all the JUMP_IF_EQ_ACC microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_acc_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.jump_if_eq_acc_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a JUMP_IF_EQ_ACC with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this JUMP_IF_EQ_ACC.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_acc_op.generate_false_datatemplates(signature)[source]

Create DataTemplates to define a conditional jump if condition is false.

This is the case where no jump happens.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define the “false half” of the operation.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_acc_op.generate_nonconditional_steps(signature)[source]

Generate the nonconditional control steps.

These steps generate the flags which then govern whether the jump happens or not.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate steps for.
Returns:List of list of bitdefs that represent the steps, and the control signals at each step.
Return type:list(list(str))
eight_bit_computer.operations.jump_if_eq_acc_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.jump_if_eq_acc_op.generate_true_datatemplates(signature)[source]

Create DataTemplates to define a conditional jump if condition is true.

This is the case where no jump happens

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
Returns:Datatemplates that define the “true half” of a JUMP_IF_***_ACC operation.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_acc_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an JUMP_IF_EQ_ACC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_eq_zero_op module

The JUMP_IF_EQ_ZERO operation.

Sets PC (jumps) to a constant if the module passed as an argument is equal to zero.

This operation will generate and store (clobber) ALU flags.

eight_bit_computer.operations.jump_if_eq_zero_op.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_EQ_ZERO operations.

Returns:DataTemplates for all the JUMP_IF_EQ_ZERO microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_zero_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.jump_if_eq_zero_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a JUMP_IF_EQ_ZERO with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
Returns:Datatemplates that define this JUMP_IF_EQ_ZERO.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_zero_op.generate_false_datatemplates(signature)[source]

Create DataTemplates to define a conditional jump if condition is false.

This is the case where no jump happens.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
Returns:Datatemplates that define the “false half” of the operation.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_zero_op.generate_nonconditional_steps(signature)[source]

Generate the nonconditional control steps.

These steps generate the flags which then govern whether the jump happens or not.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate steps for.
Returns:List of list of bitdefs that represent the steps, and the control signals at each step.
Return type:list(list(str))
eight_bit_computer.operations.jump_if_eq_zero_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.jump_if_eq_zero_op.generate_true_datatemplates(signature)[source]

Create DataTemplates to define a conditional jump if condition is true.

This is the case where no jump happens

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
Returns:Datatemplates that define the “true half” of a JUMP_IF_***_ACC operation.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_eq_zero_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an JUMP_IF_EQ_ZERO assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_flag_base module
eight_bit_computer.operations.jump_if_flag_base.generate_microcode_templates(src_dest, true_flag_bitdef, false_flag_bitdef)[source]

Generate microcode for all the JUMP_IF_XXX_FLAG instructions.

Parameters:
  • src_dest (str) – Name of the module used for both the source and destination.
  • true_flag_bitdef (str) – Bitdef that represents the state of the flags if the condition is true, i.e. the operation should jump.
  • false_flag_bitdef (str) – Bitdef that represents the state of the flags if the condition is false, i.e. the operation should not jump and just execute the next instruction instead.
Returns:

DataTemplates for all the JUMP_IF_XXX_FLAG instructions.

Return type:

list(DataTemplate)

eight_bit_computer.operations.jump_if_flag_base.generate_instruction_byte_bitdefs(src_dest)[source]

Generate bitdefs to specify the instruction byte

Parameters:src_dest (str) – Name of the module used for both the source and destination.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.jump_if_flag_base.generate_true_control_steps()[source]

Generate control steps to carry out the jump.

Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.jump_if_flag_base.parse_line(line, src_dest, name)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_XXX_FLAG assembly line, return an empty list instead.

Parameters:
  • line (str) – Assembly line to be parsed.
  • src_dest (str) – Name of the module used for both the source and destination.
  • name (str) – Name of the Operation.
Returns:

List of machine code byte template dictionaries or an empty list.

Return type:

list(dict)

eight_bit_computer.operations.jump_if_flag_base.generate_signatures()[source]

Generate all the argument signatures for the JUMP_IF_XXX_FLAG operation.

Returns:All possible signatures, See get_arg_def_template() for more information on an argument definition dictionary.
Return type:list(list(dict))
eight_bit_computer.operations.jump_if_gt_acc_op module

The JUMP_IF_GT_ACC operation.

Sets PC (jumps) to a constant if the module passed as an argument is greater than the value in ACC.

This operation will generate and store (clobber) ALU flags.

eight_bit_computer.operations.jump_if_gt_acc_op.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_GT_ACC operations.

Returns:DataTemplates for all the JUMP_IF_GT_ACC microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_gt_acc_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an JUMP_IF_GT_ACC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_gte_acc_op module

The JUMP_IF_GTE_ACC operation.

Sets PC (jumps) to a constant if the module passed as an argument is greater than or equal to the value in ACC.

This operation will generate and store (clobber) ALU flags.

eight_bit_computer.operations.jump_if_gte_acc_op.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_GTE_ACC operations.

Returns:DataTemplates for all the JUMP_IF_GTE_ACC microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_gte_acc_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an JUMP_IF_GTE_ACC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_lt_acc_op module

The JUMP_IF_LT_ACC operation.

Sets PC (jumps) to a constant if the module passed as an argument is less than the value in ACC.

This operation will generate and store (clobber) ALU flags.

eight_bit_computer.operations.jump_if_lt_acc_op.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_LT_ACC operations.

Returns:DataTemplates for all the JUMP_IF_LT_ACC microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_lt_acc_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an JUMP_IF_LT_ACC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_lte_acc_op module

The JUMP_IF_LTE_ACC operation.

Sets PC (jumps) to a constant if the module passed as an argument is less than or equal to the value in ACC.

This operation will generate and store (clobber) ALU flags.

eight_bit_computer.operations.jump_if_lte_acc_op.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_LTE_ACC operations.

Returns:DataTemplates for all the JUMP_IF_LTE_ACC microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_lte_acc_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an JUMP_IF_LTE_ACC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_negative_flag module

JUMP_IF_NEGATIVE_FLAG operation

eight_bit_computer.operations.jump_if_negative_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_NEGATIVE_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_NEGATIVE_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_negative_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_NEGATIVE_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_not_overflow_flag module

JUMP_IF_NOT_OVERFLOW_FLAG operation

eight_bit_computer.operations.jump_if_not_overflow_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_NOT_OVERFLOW_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_NOT_OVERFLOW_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_not_overflow_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_NOT_OVERFLOW_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_not_underflow_flag module

JUMP_IF_NOT_UNDERFLOW_FLAG operation

eight_bit_computer.operations.jump_if_not_underflow_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_NOT_UNDERFLOW_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_NOT_UNDERFLOW_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_not_underflow_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_NOT_UNDERFLOW_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_not_zero_flag module

JUMP_IF_NOT_ZERO_FLAG operation

eight_bit_computer.operations.jump_if_not_zero_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_NOT_ZERO_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_NOT_ZERO_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_not_zero_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_NOT_ZERO_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_overflow_flag module

JUMP_IF_OVERFLOW_FLAG operation

eight_bit_computer.operations.jump_if_overflow_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_OVERFLOW_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_OVERFLOW_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_overflow_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_OVERFLOW_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_positive_flag module

JUMP_IF_POSITIVE_FLAG operation

eight_bit_computer.operations.jump_if_positive_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_POSITIVE_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_POSITIVE_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_positive_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_POSITIVE_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_underflow_flag module

JUMP_IF_UNDERFLOW_FLAG operation

eight_bit_computer.operations.jump_if_underflow_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_UNDERFLOW_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_UNDERFLOW_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_underflow_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_UNDERFLOW_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.jump_if_zero_flag module

JUMP_IF_ZERO_FLAG operation

eight_bit_computer.operations.jump_if_zero_flag.generate_microcode_templates()[source]

Generate microcode for all the JUMP_IF_ZERO_FLAG instructions.

Returns:DataTemplates for all the JUMP_IF_ZERO_FLAG instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.jump_if_zero_flag.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a JUMP_IF_ZERO_FLAG assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.load module

The LOAD operation.

Loads a value from data memory into a module.

eight_bit_computer.operations.load.generate_microcode_templates()[source]

Generate microcode for all the LOAD instructions.

Returns:DataTemplates for all the LOAD instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.load.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.load.generate_operation_templates(signature)[source]

Create the DataTemplates to define a load with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular load operation to generate templates for.
Returns:Datatemplates that define this load.
Return type:list(DataTemplate)
eight_bit_computer.operations.load.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular LOAD operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.load.generate_control_steps(signature)[source]

Generate control steps for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular load operation to generate the control steps for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.load.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a LOAD assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.lshift_op module

The LSHIFT operation.

Moves all the bits in the argument one place to the left (toward the most significant bit) in place. A zero is added in the rightmost (least significant bit) place.

eight_bit_computer.operations.lshift_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.lshift_op.generate_microcode_templates()[source]

Generate microcode for all the LSHIFT operations.

Returns:DataTemplates for all the LSHIFT microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.lshift_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define an LSHIFT with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this not.
Return type:list(DataTemplate)
eight_bit_computer.operations.lshift_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.lshift_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an LSHIFT assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.lshiftc_op module

The LSHIFTC operation.

Moves all the bits in the argument one place to the left (toward the most significant bit) in place. If the carry flag is high, a 1 is added in the rightmost (least significant bit) place. If the flag is low, the rightmost place is left as 0.

eight_bit_computer.operations.lshiftc_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.lshiftc_op.generate_microcode_templates()[source]

Generate microcode for all the LSHIFTC operations.

Returns:DataTemplates for all the LSHIFTC microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.lshiftc_op.generate_control_steps(signature, add_1)[source]

Generate the control steps for a given signature, adding 1 or not.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
  • add_1 (bool) – Whether or not the control steps should add 1 to the shifted result.
Returns:

List of list of control flags for the steps.

Return type:

list(list(str))

eight_bit_computer.operations.lshiftc_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.lshiftc_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an LSHIFTC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.nand_op module

NAND Operation

eight_bit_computer.operations.nand_op.generate_microcode_templates()[source]

Generate microcode for all the NAND instructions.

Returns:DataTemplates for all the NAND instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.nand_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a NAND assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.noop_op module

The NOOP operation.

Does nothing for one micro cycle.

eight_bit_computer.operations.noop_op.generate_microcode_templates()[source]

Generate microcode for the NOOP operation.

Returns:DataTemplates for all the NOOP microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.noop_op.generate_instruction_byte_bitdefs()[source]

Generate bitdefs to specify the NOOP instruction.

Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.noop_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an NOOP assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.nor_op module

NOR Operation

eight_bit_computer.operations.nor_op.generate_microcode_templates()[source]

Generate microcode for all the NOR instructions.

Returns:DataTemplates for all the NOR instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.nor_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a NOR assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.not_op module

The NOT operation.

Inverts all the bits in a register

eight_bit_computer.operations.not_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.not_op.generate_microcode_templates()[source]

Generate microcode for all the NOT operations.

Returns:DataTemplates for all the NOT microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.not_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a not with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this not.
Return type:list(DataTemplate)
eight_bit_computer.operations.not_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.not_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a NOT assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.nxor_op module

NXOR Operation

eight_bit_computer.operations.nxor_op.generate_microcode_templates()[source]

Generate microcode for all the NXOR instructions.

Returns:DataTemplates for all the NXOR instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.nxor_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a NXOR assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.operation_template module

Template for operation module

eight_bit_computer.operations.operation_template.generate_microcode_templates()[source]

Generate microcode for all the OP_TEMPLATE instructions.

Returns:DataTemplates for all the OP_TEMPLATE instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.operation_template.generate_signatures()[source]

Generate all the argument signatures for the OP_TEMPLATE operation.

Returns:All possible signatures, See get_arg_def_template() for more information on an argument definition dictionary.
Return type:list(list(dict))
eight_bit_computer.operations.operation_template.generate_operation_templates(signature)[source]

Create the DataTemplates to define a OP_TEMPLATE with the given signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular OP_TEMPLATE operation to generate templates for.
Returns:DataTemplates that define this OP_TEMPLATE.
Return type:list(DataTemplate)
eight_bit_computer.operations.operation_template.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular OP_TEMPLATE operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.operation_template.generate_control_steps(signature)[source]

Generate control steps for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular OP_TEMPLATE operation to generate the control steps for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.operation_template.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a OP_TEMPLATE assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.or_op module

OR Operation

eight_bit_computer.operations.or_op.generate_microcode_templates()[source]

Generate microcode for all the OR instructions.

Returns:DataTemplates for all the OR instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.or_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a OR assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.pop_op module

The POP operation.

Loads the value in memory pointed to by SP into a module, then increments SP.

This uses the ALU but the flags generated are not stored.

eight_bit_computer.operations.pop_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.pop_op.generate_microcode_templates()[source]

Generate microcode for all the POP operations.

Returns:DataTemplates for all the POP microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.pop_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a POP with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this pop.
Return type:list(DataTemplate)
eight_bit_computer.operations.pop_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.pop_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an POP assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.progload_op module

The PROGLOAD operation.

Loads a value from program memory into ACC.

eight_bit_computer.operations.progload_op.generate_microcode_templates()[source]

Generate microcode for all the PROGLOAD instructions.

Returns:DataTemplates for all the PROGLOAD instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.progload_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.progload_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a progload with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular progload operation to generate templates for.
Returns:Datatemplates that define this progload.
Return type:list(DataTemplate)
eight_bit_computer.operations.progload_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular PROGLOAD operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.progload_op.generate_control_steps(signature)[source]

Generate control steps for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular load operation to generate the control steps for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.progload_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a PROGLOAD assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.progstore_op module

The PROGSTORE operation.

Stores a value from a module into memory

eight_bit_computer.operations.progstore_op.generate_microcode_templates()[source]

Generate microcode for all the PROGSTORE instructions.

Returns:DataTemplates for all the PROGSTORE instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.progstore_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.progstore_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a progstore with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular progstore operation to generate templates for.
Returns:Datatemplates that define this progstore.
Return type:list(DataTemplate)
eight_bit_computer.operations.progstore_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular PROGSTORE operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.progstore_op.generate_control_steps(signature)[source]

Generate control steps for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular store operation to generate the control steps for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.progstore_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a STORE assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.push_op module

The PUSH operation.

Decrements PS, then stores a value from a module into memory at the new value of SP.

This uses the ALU but the flags generated are not stored.

eight_bit_computer.operations.push_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.push_op.generate_microcode_templates()[source]

Generate microcode for all the PUSH operations.

Returns:DataTemplates for all the PUSH microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.push_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a PUSH with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this push.
Return type:list(DataTemplate)
eight_bit_computer.operations.push_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.push_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an PUSH assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.return_op module

The RETURN operation.

Pops the top of the stack into the program counter.

Expects to be used after having arrived at a section of assembly with the CALL instruction.

eight_bit_computer.operations.return_op.generate_microcode_templates()[source]

Generate microcode for the RETURN operation.

Returns:DataTemplates for all the RETURN microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.return_op.generate_instruction_byte_bitdefs()[source]

Generate bitdefs to specify the RETURN instruction.

Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.return_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an RETURN assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.rot_left_op module

The ROT_LEFT operation.

Moves all the bits in the number one place to the left (most significant side). If the most significant bit was a 1, then after the rotation this is set back on the least significant side.

This operation will generate and store (clobber) ALU flags.

eight_bit_computer.operations.rot_left_op.generate_microcode_templates()[source]

Generate microcode for all the ROT_LEFT operations.

Returns:DataTemplates for all the ROT_LEFT microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.rot_left_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.rot_left_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a ROT_LEFT with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
Returns:Datatemplates that define this ROT_LEFT.
Return type:list(DataTemplate)
eight_bit_computer.operations.rot_left_op.generate_no_carry_datatemplates(signature)[source]

Create DataTemplates to define a rottate left with no carry.

This is the case where the most significant bit was a zero.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
Returns:Datatemplates that define the “no carry half” of a ROT_LEFT operation.
Return type:list(DataTemplate)
eight_bit_computer.operations.rot_left_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.rot_left_op.generate_with_carry_datatemplates(signature)[source]

Create DataTemplates to define a rottate left with a carry.

This is the case where the most significant bit was a one.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular operation to generate templates for.
Returns:Datatemplates that define the “carry half” of a ROT_LEFT operation.
Return type:list(DataTemplate)
eight_bit_computer.operations.rot_left_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an ROT_LEFT assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.set_op module

The set operation.

Sets a module to a certain value.

eight_bit_computer.operations.set_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.set_op.generate_microcode_templates()[source]

Generate datatemplates for all the SET operations.

Returns:All the datatemplates that make up the SET operation.
Return type:list(DataTemplate)
eight_bit_computer.operations.set_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular set operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction byte.
Return type:list(str)
eight_bit_computer.operations.set_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a SET assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
Raises:OperationParsingError – If the line was identifiably a SET operation but incorrectly specified.
eight_bit_computer.operations.set_zero_op module

The SET_ZERO operation.

Sets the given module to zero.

eight_bit_computer.operations.set_zero_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.set_zero_op.generate_microcode_templates()[source]

Generate microcode for all the SET_ZERO operations.

Returns:DataTemplates for all the SET_ZERO microcode.
Return type:list(DataTemplate)
eight_bit_computer.operations.set_zero_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define an SET_ZERO with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate templates for.
Returns:Datatemplates that define this set_zero.
Return type:list(DataTemplate)
eight_bit_computer.operations.set_zero_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular not operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.set_zero_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an SET_ZERO assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of instruction byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.simple_alu_op_base module

Base for simple ALU operations

eight_bit_computer.operations.simple_alu_op_base.generate_microcode_templates(alu_op, control_flags)[source]

Generate microcode for a the simple ALU instructions.

Parameters:
  • alu_op (str) – The ALU operation to perform - one of the ALU_OPERATIONS.
  • control_flags (list(str)) – List of ALU control flags for this simple ALU operation. One of the ALU_CONTROL_FLAGS.
Returns:

DataTemplates for all the simple ALU instructions.

Return type:

list(DataTemplate)

eight_bit_computer.operations.simple_alu_op_base.generate_signatures()[source]

Generate all the argument signatures for this simple ALU operation.

Returns:All possible signatures, See get_arg_def_template() for more information on an argument definition dictionary.
Return type:list(list(dict))
eight_bit_computer.operations.simple_alu_op_base.generate_operation_templates(signature, alu_op, control_flags)[source]

Create the DataTemplates to define a simple ALU with the given signature.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular simple ALU operation to generate templates for.
  • alu_op (str) – The ALU operation to perform - one of the ALU_OPERATIONS.
  • control_flags (list(str)) – List of ALU control flags for this ALU operation. One of the ALU_CONTROL_FLAGS.
Returns:

DataTemplates that define this simple ALU operation.

Return type:

list(DataTemplate)

eight_bit_computer.operations.simple_alu_op_base.generate_instruction_byte_bitdefs(signature, alu_op)[source]

Generate bitdefs to specify the instruction byte for this signature.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular simple ALU operation to generate the instruction byte bitdefs for.
  • alu_op (str) – The ALU operation to perform - one of the ALU_OPERATIONS.
Returns:

Bitdefs that make up the instruction_byte

Return type:

list(str)

eight_bit_computer.operations.simple_alu_op_base.generate_control_steps(signature, control_flags)[source]

Generate control steps for this signature.

Parameters:
  • signature (list(dict)) – List of argument definitions that specify which particular simple ALU operation to generate the control steps for.
  • control_flags (list(str)) – List of ALU control flags for this ALU operation. One of the ALU_CONTROL_FLAGS.
Returns:

List of list of bitdefs that specify the control steps.

Return type:

list(list(str))

eight_bit_computer.operations.simple_alu_op_base.parse_line(line, name, alu_op)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a simple ALU assembly line, return an empty list instead.

Parameters:
  • line (str) – Assembly line to be parsed.
  • name (str) – Name of the Operation.
  • alu_op (str) – The ALU operation to perform - one of the ALU_OPERATIONS.
Returns:

List of machine code byte template dictionaries or an empty list.

Return type:

list(dict)

eight_bit_computer.operations.store_op module

The STORE operation.

Stores a value from a module into memory

eight_bit_computer.operations.store_op.generate_microcode_templates()[source]

Generate microcode for all the STORE instructions.

Returns:DataTemplates for all the STORE instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.store_op.generate_signatures()[source]

Generate the definitions of all possible arguments passable.

Returns:All possible arguments. See get_arg_def_template() for more information.
Return type:list(list(dict))
eight_bit_computer.operations.store_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a store with the given args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular store operation to generate templates for.
Returns:Datatemplates that define this store.
Return type:list(DataTemplate)
eight_bit_computer.operations.store_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular STORE operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.store_op.generate_control_steps(signature)[source]

Generate control steps for these args.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular store operation to generate the control steps for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
eight_bit_computer.operations.store_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a STORE assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.sub_op module

SUB Operation

eight_bit_computer.operations.sub_op.generate_microcode_templates()[source]

Generate microcode for all the SUB instructions.

Returns:DataTemplates for all the SUB instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.sub_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a SUB assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.subb_op module

The SUBB operation

Subtracts a value from the accumulator, subtracting an extra 1 if the borrow flag is set.

eight_bit_computer.operations.subb_op.generate_microcode_templates()[source]

Generate microcode for the SUBB instruction.

Returns:DataTemplates for all the SUBB instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.subb_op.generate_signatures()[source]

Generate all the argument signatures for the SUBB operation.

Returns:All possible signatures, See get_arg_def_template() for more information on an argument definition dictionary.
Return type:list(list(dict))
eight_bit_computer.operations.subb_op.generate_operation_templates(signature)[source]

Create the DataTemplates to define a SUBB with the given signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular SUBB operation to generate templates for.
Returns:DataTemplates that define the operation with this signature.
Return type:list(DataTemplate)
eight_bit_computer.operations.subb_op.get_calculation_control_steps(signature)[source]

Get control steps that calcuate the new value.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular SUBB operation to generate templates for.
Returns:List of list of bitdefs that specify the control steps.
Return type:list(list(str))
Raises:ValueError – When the signature’s first argument type is not a module name or constant.
eight_bit_computer.operations.subb_op.generate_true_data_templates(instruction_byte_bitdefs, initial_control_steps)[source]

Create datatemplates for an SUBB where an extra bit is needed.

Parameters:
  • instruction_byte_bitdefs (list(str)) – List of the bitdefs that make up the instruction byte.
  • initial_control_steps (list(list(str))) – List of list of bitdefs that specify the control steps.
Returns:

: List of DataTemplates that describe the SUBB for this signature when the carry flag is high.

Return type:

list(DataTemplate)

eight_bit_computer.operations.subb_op.generate_false_data_templates(instruction_byte_bitdefs, initial_control_steps)[source]

Create datatemplates for an ADDC where an extra bit is not needed.

Parameters:
  • instruction_byte_bitdefs (list(str)) – List of the bitdefs that make up the instruction byte.
  • initial_control_steps (list(list(str))) – List of list of bitdefs that specify the control steps.
Returns:

: List of DataTemplates that describe the ADDC for this signature when the carry flag is low.

Return type:

list(DataTemplate)

eight_bit_computer.operations.subb_op.generate_instruction_byte_bitdefs(signature)[source]

Generate bitdefs to specify the instruction byte for this signature.

Parameters:signature (list(dict)) – List of argument definitions that specify which particular simple ALU operation to generate the instruction byte bitdefs for.
Returns:Bitdefs that make up the instruction_byte
Return type:list(str)
eight_bit_computer.operations.subb_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably an ADDC assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
eight_bit_computer.operations.xor_op module

XOR Operation

eight_bit_computer.operations.xor_op.generate_microcode_templates()[source]

Generate microcode for all the XOR instructions.

Returns:DataTemplates for all the XOR instructions.
Return type:list(DataTemplate)
eight_bit_computer.operations.xor_op.parse_line(line)[source]

Parse a line of assembly code to create machine code byte templates.

If a line is not identifiably a XOR assembly line, return an empty list instead.

Parameters:line (str) – Assembly line to be parsed.
Returns:List of machine code byte template dictionaries or an empty list.
Return type:list(dict)
Module contents

Operations in the assembly language

eight_bit_computer.operations.get_all_operations()[source]

Get a list of all the operations in the assembly language

Deferring the import to the function so that importing the operations module doesn’t mean automatically importing all the operations.

Returns:All the modules that represent operations in the assembly language
Return type:list(module)

Submodules

eight_bit_computer.assembler module

Process assembly code and output machine code.

eight_bit_computer.assembler.process_assembly_lines(lines)[source]

Parse, assemble and generate machine code.

Parameters:lines (list(str)) – The lines that made up the assembly file to be assembled.
Returns:The assembly file converted to an equivalent list of dictionaries with information about what each line was resolved to.
Return type:list(dict)
Raises:AssemblyError – If there was an error assembling the machine code.
eight_bit_computer.assembler.process_line(line)[source]

Process a single line of assembly.

Parameters:line (str) – The line of assembly to process. This line has already been cleaned (excess whitespace and comments removed).
Returns:A dictionary of information about this line. See the get_assembly_line_template() documentation for more information about what is in the dictionary.
Return type:dict
eight_bit_computer.assembler.get_variable_info_from_line(cleaned_line)[source]

Get variable info from the line (if any).

Looks ata line to determine whether or not it’s a variable definition.

Expects the passed in line to be a valid line of machine code. That is, the passed in line should be translatable to valid machine code.

Parameters:line (cleaned_line) – Line to parse.
Returns:Whether the line is a variable def, the variable defined, the value of the variable and it’s location.
Return type:(bool, str, int, int)
eight_bit_computer.assembler.clean_line(line)[source]

Clean a line of assembly ready for further processing.

Removes leading and trailing whitespace, comments, and excess whitespace between tokens.

Parameters:line (str) – The line to clean.
Returns:The cleaned line.
Return type:str
eight_bit_computer.assembler.remove_comments(line)[source]

Remove comments from a line.

A comment is anything on the line after and including an occurrence of //.

Parameters:line (str) – line to remove comments from.
Returns:The line with comments removed.
Return type:str
eight_bit_computer.assembler.remove_excess_whitespace(line)[source]

Remove excess whitespace from a line.

Parameters:line (str) – line to remove excess whitespace from.
Returns:The line with excess whitespace removed.
Return type:str
eight_bit_computer.assembler.machine_code_bytes_from_line(line)[source]

Get machine code bytes that describe this line.

Uses all the defined instructions and defers the work of parsing to them. See get_machine_code_byte_template() for information on machine code dictionaries from instructions.

Expects the passed in line to be a valid line of machine code. That is, the passed in line should be translatable to valid machine code.

Parameters:

line (str) – Line to parse.

Returns:

Machine code byte information dictionaries.

Return type:

list(dict)

Raises:
  • LineProcessingError – Failure to extract machine code or matching
  • multiple operations.
eight_bit_computer.assembler.validate_and_identify_constants(machine_code_bytes)[source]

Validate and identify constants from assembly code.

Assumed constants are returned from the instruction parsers. This function then validates them to make sure they are correct and determines what kind of constant they are.

See get_machine_code_byte_template() for information on machine code dictionaries from instructions.

This function modifies the passed in machine code templates list in place.

Parameters:machine_code_bytes (list(dict)) – The machine code byte dicts as returned by an instruction line parser.
Raises:LineProcessingError – Invalid constants were specified.
eight_bit_computer.assembler.assign_machine_code_byte_indexes(assembly_lines)[source]

Assign indexes to the machine code bytes.

This modifies the passed in list of assembly lines, adding data to it.

Parameters:
  • assembly_lines (list(dict)) – Lines of assembly to add label
  • to. (information) –
eight_bit_computer.assembler.assign_labels(assembly_lines)[source]

Assign labels to the lines for later reference

This modifies the passed in list of assembly lines, adding data to it.

Parameters:
  • assembly_lines (list(dict)) – Lines of assembly to add label
  • to. (information) –
eight_bit_computer.assembler.resolve_labels(assembly_lines)[source]

Resolve labels to indexes in the machine code bytes.

This modifies the passed in list of assembly line dictionaries.

Parameters:assembly_lines (list(dict)) – List of assembly lines to resolve label references in.
eight_bit_computer.assembler.create_label_map(assembly_lines)[source]

Create a map of labels to machine code byte indexes.

Parameters:assembly_lines (list(dict)) – List of assembly lines to create a label map for.
Returns:str): Dictionary of label names to machine code indexes.
Return type:dict(str
eight_bit_computer.assembler.resolve_numbers(assembly_lines)[source]

Resolve number constants to machine code byte values.

This modifies the passed in list of assembly line dictionaries.

Parameters:assembly_lines (list(dict)) – List of assembly lines to resolve numbers for.
eight_bit_computer.assembler.resolve_variables(assembly_lines)[source]

Resolve variable constants to indexes in data memory.

This modifies the passed in list of assembly line dictionaries.

Parameters:assembly_lines (list(dict)) – List of assembly lines to resolve variables in.
eight_bit_computer.assembler.create_variable_map(assembly_lines)[source]

Create a map of variables to indexes in data memory.

Parameters:assembly_lines (list(dict)) – List of assembly lines to create a variable map for.
Returns:str): Dictionary of variable names to machine code indexes.
Return type:dict(str
eight_bit_computer.assembly_summary module

Extract information from a list of assembly line info dictionaries.

eight_bit_computer.assembly_summary.generate_assembly_summary(asm_line_infos)[source]

Produce a summary that combines assembly and machine code.

The summary will be like this:

 1 $variable0              |
 2 @label1                 |
 3     LOAD [$variable1] A |  0 00 00000000 - @label1 255 FF 11111111
                           |  1 01 00000001 -           1 01 00000001 $variable1
 4                         |
 5 @label2                 |
 6     LOAD [$variable2] A |  2 02 00000010 - @label2 255 FF 11111111
                           |  3 03 00000011 -           2 02 00000010 $variable2
 7     JUMP @label1        |  4 04 00000100 -         255 FF 11111111
                           |  5 05 00000101 -           0 00 00000000 @label1
 8                         |
 9     STORE A [#123]      |  6 06 00000110 -         255 FF 11111111
                           |  7 07 00000111 -         123 7B 01111011 #123
10 @label3                 |
11     LOAD [$variable3] B |  8 08 00001000 - @label3 255 FF 11111111
                           |  9 09 00001001 -           3 03 00000011 $variable3
12     LOAD [$variable0] C | 10 0A 00001010 -         255 FF 11111111
                           | 11 0B 00001011 -           0 00 00000000 $variable0
13 $variable4              |
14 // comment
Parameters:asm_line_infos (list(dict)) – List of dictionaries of information about the parsed assembly.
Returns:Printable summary.
Return type:str
eight_bit_computer.assembly_summary.generate_assembly_summary_lines(asm_line_infos)[source]

Generate list of lines for an assembly summary

Parameters:asm_line_infos (list(dict)) – List of dictionaries of information about the parsed assembly.
Returns:List of lines for the summary.
Return type:list(str)
eight_bit_computer.assembly_summary.get_assembly_summary_data(asm_line_infos)[source]

Process assembly data to make formatting easier for the summary.

Parameters:asm_line_infos (list(dict)) – List of line info dictionaries as returned by process_assembly_lines() .
Returns:List of entries for the assembly summary print out
Return type:list
eight_bit_computer.assembly_summary.get_widest_column_values(assembly_summary_data)[source]

Find widest values in the columns of the output.

Required for the eventual printed table to line up correctly.

Parameters:assembly_summary_data (list(dict)) – List of dictionaries (as returned by get_assembly_summary_data()) with all the summary information data.
Returns:Mapping of columns for widest values.
Return type:dict
eight_bit_computer.assembly_validity module

Validity checks on the processed assembly lines

eight_bit_computer.assembly_validity.check_structure_validity(asm_line_infos)[source]

Check the processed assembly lines for consistency/correctness.

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
eight_bit_computer.assembly_validity.check_multiple_label_defs(asm_line_infos)[source]

Check if the same label been defined more than once.

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
Raises:AssemblyError – If the same label been defined more than once.
eight_bit_computer.assembly_validity.check_multiple_label_assignment(asm_line_infos)[source]

Check if a single line been assigned more than one label.

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
Raises:AssemblyError – If a single line been assigned more than one label.
eight_bit_computer.assembly_validity.check_undefined_label_ref(asm_line_infos)[source]

Check if an operation is using a label that hasn’t been defined.

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
Raises:AssemblyError – If an operation is using a label that hasn’t been defined.
eight_bit_computer.assembly_validity.check_multiple_variable_def(asm_line_infos)[source]

Has the same variable been defined multiple times.

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
Raises:AssemblyError – If a variable has been defined more than once.
eight_bit_computer.assembly_validity.check_undefined_variable_ref(asm_line_infos)[source]

Check instructions don’t reference undefined variables

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
Raises:AssemblyError – If a variable is referenced but not defined.
eight_bit_computer.assembly_validity.check_overlapping_variables(asm_line_infos)[source]

Check none of the defined variables overlap with each other.

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
Raises:AssemblyError – If two variables overlap in position with each other.
eight_bit_computer.assembly_validity.check_num_instruction_bytes(assembly_lines)[source]

Check there aren’t too many instruction_bytes.

Parameters:asm_line_infos (list(dict)) – List of dictionaries (conforming to get_assembly_line_template()) with information about all the lines in the assembly file.
Raises:AssemblyError – If there are more instruction bytes than will fit in program memory.
eight_bit_computer.bitdef module

The bitdef and associated functions.

A bitdef is a string made up of .s, 0s, and 1s.

  • . means that the bit at this position could be a 0 or a 1.
  • 0 means that the bit at this position is a 0.
  • 1 means that the bit at this position is a 1.

When indexing into a bitdef, indexes start at 0 and begin at the right hand side or least significant bit of the value. E.g.:

Index:  76543210
Bitdef: 010.1..1
eight_bit_computer.bitdef.same_length(bitdefs)[source]

Check if the passed in bitdefs are all the same length.

Parameters:list (bitdefs) – Bitdefs to check length of.
Returns:True if all the bitdefs are the same length, False otherwise
Return type:bool
eight_bit_computer.bitdef.length(bitdef)[source]

Calculate length of a bitdef.

Parameters:bitdef (str) – The bitdef to find the length of.
Returns:The length of the bitdef.
Return type:int
eight_bit_computer.bitdef.have_overlapping_bits(bitdefs)[source]

Check if the bitdefs have any bits set in the same position.

Example with overlap (bits at index 2 and 6 overlap):

  • 0...101.
  • 11...1..

Example with no overlap:

  • 11010...
  • ......11
Parameters:bitdefs (list(str)) – Bitdefs to check for overlaps.
Returns:Whether or not there were overlaps.
Return type:bool
eight_bit_computer.bitdef.merge(bitdefs)[source]

Merge the bitdefs to a single bitdef.

Bitdefs must

  • All be the same length.
  • Not have any bits defined in the same position.
Parameters:

bitdefs (list(str)) – Bitdefs to merge.

Returns:

The merged bitdef.

Return type:

str

Raises:
  • ValueError – If the bitdefs are not all the same length or have
  • overlapping bits.
eight_bit_computer.bitdef.collapse(bitdef)[source]

Collapse undefined bits into real bits to make new bitdefs.

The undefined bits are expanded in order, from left to right, with 0 first, then 1.

For example, 10.0. becomes:

  • 10000
  • 10001
  • 10100
  • 10101
Parameters:bitdef (str) – The bitdef to collapse.
Returns:The list of bitdefs the original bitdef has collapsed to.
Return type:list(str)
eight_bit_computer.bitdef.fill(bitdef, value)[source]

Fill undefined bits with a value.

For example 1..0100.1 becomes 111010011 when filled with 1s.

Parameters:
  • bitdef (str) – The bitdef to fill.
  • value (str) – The value to fill with, “0” or “1”.
Returns:

The filled bitdef.

Return type:

str

eight_bit_computer.bitdef.extract_bits(bitdef, end, start)[source]

Extract a region from the bitdef.

Indexes for start and end start at zero from the right or least significant bit.

For example, if the bitdef was 00101011 and the extraction end was 4 and start was 1 the result would be 0101:

Extracted bits:      xxxx
Index:            76543210
Bitdef:           00101011
Result:              0101
Parameters:
  • bitdef (str) – The bitdef to extract bits from.
  • end (int) – Index of the leftmost bit of the portion to extract.
  • start (int) – Index of the rightmost bit of the portion to extract.
Returns:

The extracted portion of the bitdef.

Return type:

str

Raises:

ValueError – If:

  • Extraction region is larger than bitdef.
  • Extraction end index is before extraction start index.
  • Extraction start index is less than 0.
eight_bit_computer.bitdef.remove_whitespace(input_string)[source]

Remove the whitespace from a string.

Parameters:input_string (str) – The string to remove whitespace from.
Returns:The string with the whitespace removed.
Return type:str
eight_bit_computer.bitdef.reverse_index(index, length)[source]

Reverse the passed in index as if the index direction was flipped.

Taking the string “hello” as an example the regular indexes for each letter are:

01234
hello

Reversing the indexes yields:

43210
hello

This allows easily indexing into a bitdef on bitdef indexing terms.

Parameters:
  • index (int) – The index position to reverse.
  • length (int) – The length of the array being indexed into.
Returns:

The reversed index.

Return type:

int

eight_bit_computer.cli module
eight_bit_computer.cli.assemble()[source]

Entry point for the command line assemble script.

eight_bit_computer.cli.get_assemble_parser()[source]

Generate arg parser for the ebc_assemble command line script.

Returns:The argument parser.
Return type:argparse.ArgumentParser
eight_bit_computer.cli.gen_roms()[source]

Entry point for the command line rom generation script.

eight_bit_computer.cli.get_gen_roms_parser()[source]

Generate arg parser for the gen_roms command line script.

Returns:The argument parser.
Return type:argparse.ArgumentParser
eight_bit_computer.data_structures module

Data structures use to pass information between functions.

class eight_bit_computer.data_structures.DataTemplate(address_range, data)

Bases: tuple

Some data and a range of addresses to store that data in

address_range

The range of addresses to store the data in. 0 and 1 are absolute values, X is either a 0 or 1 and the expectation is that the data will expand out to the parts of the address marked with an X. and example could be “0010XX001”.

Type:str
data

The data to be stored at the given addresses.

Type:str
address_range

Alias for field number 0

data

Alias for field number 1

class eight_bit_computer.data_structures.RomData(address, data)

Bases: tuple

Some data and an address to store it in

address

The address to store the data in.

Type:str
data

The data to be stored at the given address.

Type:int
address

Alias for field number 0

data

Alias for field number 1

eight_bit_computer.data_structures.get_summary_entry_template()[source]

Get a template to describe each line in an assembly summary

Keys have the following meanings:

  • has_assembly: Does this line of the summary have assembly code.
  • assembly: Information about the assembly in this summary line.
  • assembly/info: The assembly line information dictionary (as returned by get_assembly_line_template()) and filled in by the assembler.
  • has_mc_byte: Does this line of the summary have a machine code byte.
  • mc_byte: Information about the machine code byte on this line.
  • mc_byte/info: Machine code byte information dictionary (as returned by get_machine_code_byte_template() and filled by the assembly process).
  • mc_byte/has_label: Whether of not this machine code byte has an associated label.
  • mc_byte/label: The label of this machine code byte.
Returns:Summary entry template.
Return type:dict
eight_bit_computer.data_structures.get_assembly_line_template()[source]

Get a template for the assembly line information bundle.

Template for a dictionary that contains information about this line of assembly code. The keys have the following meanings:

  • line_no: The line in the assembly file that this line was on.
  • raw: The line as it was in the assembly file.
  • clean: The cleaned up line, ready for parsing.
  • defines_label: Whether or not this line is a label definition.
  • defined_label: The label that this line defined.
  • has_label_assigned: Whether or not this line has a label assigned to it.
  • assigned_label: The label that has been assigned to the first line of the machine code generated for this line.
  • defines_variable: Whether or not this line is a variable definition.
  • defined_variable: The variable that this line defines.
  • defined_variable_value: The value of the variable in data memory.
  • defined_variable_location: The location of the variable in data memory.
  • has_machine_code: Whether or not this line results in machine code. E.g. a comment has no machine code.
  • mc_bytes: List of machine code byte templates (with constant expansion information) for this assembly line.
Returns:Assembly line description template.
Return type:dict
eight_bit_computer.data_structures.get_arg_def_template()[source]

Get a definition template for an assembly operation argument.

This is a set of information that describes an argument used in a line of assembly.

The keys have the following meaning:

  • value_type: What kind of argument this is. constant or module_name.
  • is_memory_location: Whether this argument is referring to a location in memory.
  • value: The permitted value of the argument if it’s a module.

These dictionaries will be grouped in a list of lists that describe the possible arguments for an assembly operation. E.g. if the possible arguments for an assembly operation were:

  • ACC A
  • B C
  • A [#123]

The data structure would be as follows:

[
    [
        {
            "value_type": "module_name",
            "is_memory_location": False,
            "value": "ACC",
        },
        {
            "value_type": "module_name",
            "is_memory_location": False,
            "value": "A",
        },
    ],
    [
        {
            "value_type": "module_name",
            "is_memory_location": False,
            "value": "B",
        },
        {
            "value_type": "module_name",
            "is_memory_location": True,
            "value": "C",
        },
    ],
    [
        {
            "value_type": "module_name",
            "is_memory_location": False,
            "value": "A",
        },
        {
            "value_type": "constant",
            "is_memory_location": True,
            "value": "",
        },
    ],
]
Returns:Machine code byte description template.
Return type:dict
eight_bit_computer.data_structures.get_machine_code_byte_template()[source]

Get the template used to describe a machine code byte.

This is a set of information that describes the byte (of which there could be many) of machine code that an operation (e.g. LOAD [$variable] A) results in.

The keys have the following meaning:

  • bitstring: A byte bitstring of the final byte that will make up the machine code.
  • byte_type: The type of machine code byte. Will be instruction or constant.
  • constant_type: The type of the constant. Could be a label, variable or number.
  • constant: The constant that this byte will need to become. The resolution of the constant to a real machine code byte is done by the assembler.
  • number_value: The value of the constant as an int if it’s a number.
  • index: The index of this byte in program data.
Returns:Machine code byte description template.
Return type:dict
eight_bit_computer.decimal_display module

Generate the data for the decimal display rom.

eight_bit_computer.decimal_display.gen_display_romdatas()[source]

Generate the romdatas that make up the display rom

Returns:List of romdatas (unsorted) that make up the display rom.
Return type:list(RomData)
eight_bit_computer.decimal_display.to_2s_compliment(value)[source]

Convert an unsigned value to it’s 2’s compliment equivalent.

Parameters:value (int) – The unsigned 8 bit value (0-255) to convert
Returns:The 2’s compliment equivalent.
Return type:int
eight_bit_computer.decimal_display.assemble_romdata(raw_value, disp_chars, base_bitdef, binary_mode_bitdef)[source]

Assemble the romdatas for the given display configuration.

Parameters:
  • raw_value (int) – The unsigned 8 bit value to convert to display rom values.
  • disp_chars (string) – The display characters that will make up this value on the seven segment displays
  • base_bitdef (str) – A bitdef signifying which base the display should be in - hex or decimal. Forms part of the address of the rom.
  • binary_mode_bitdef (str) – Whether the raw value should be displayed in unsigned or two’s compliment interpreted value.
Returns:

List of the romdatas that make up this display configuration.

Return type:

list(RomData)

eight_bit_computer.decimal_display.value_to_addr_bitdef(value)[source]

Place the bitdef of the value in the address bitdef.

The address bitdef is 15 bits wide but the value is only 8. Pad this to the correct size by forcing the 3 unused bits in the 3 most significate places to be zero and leaving 4 bits for the base and interpretation (unsigned vs 2’s compliment) in the next most significant bits. The valye goes in the 8 least significant bits.

Parameters:value (int) – Unsigned 8 bit value (0-255) to place in the address bitdef.
Returns:Address bitdef with value in place.
Return type:str
eight_bit_computer.decimal_display.character_to_bitdef(character)[source]

Generate a bitdef for the given character.

Bitdefs are mapped to correspond to a 5641AH 7 segment display:

    A
  - - -
 |     |
F|     |B
 |  G  |
  - - -
 |     |
E|     |C
 |     |
  - - -
    D

A = 0000 0001
B = 0000 0010
C = 0000 0100
D = 0000 1000
E = 0001 0000
F = 0010 0000
G = 0100 0000
Parameters:character (str) – Character to get the bidef for.
Returns:Bitdef that represents the segments to illuminate for that character.
Return type:str
Raises:ValueError – If the character to convert isn’t supported.
eight_bit_computer.exceptions module

Custom exceptions used in this project.

exception eight_bit_computer.exceptions.EightBitComputerError[source]

Bases: exceptions.Exception

Base class for exceptions in the computer

exception eight_bit_computer.exceptions.OperationParsingError[source]

Bases: eight_bit_computer.exceptions.EightBitComputerError

Raised when parsing an operation fails.

E.g. An incorrect argument is used with the LOAD operation.

exception eight_bit_computer.exceptions.LineProcessingError[source]

Bases: eight_bit_computer.exceptions.EightBitComputerError

Raised when processing a line fails.

E.g. The line was not a constant declaration and no operations matched.

exception eight_bit_computer.exceptions.AssemblyError[source]

Bases: eight_bit_computer.exceptions.EightBitComputerError

Raised when the assembly could not be converted to machine code.

eight_bit_computer.export module

Functionality to convert data other package friendly formats.

eight_bit_computer.export.bitstrings_to_arduino_cpp(bitstrings, rom_index, header_filename, rom_var_name)[source]

Convert rom bitstrings to arduino header cpp file.

The format of the file is:

#include "mc_rom_0.h"

extern const byte MC_ROM_0[] __attribute__ (( __section__(".fini1") )) = {
    0x00, 0x01, 0x02, 0x03,  0x04, 0x05, 0x06, 0x07,  0x08, 0x09, 0x0A, 0x0B,  0x0C, 0x0D, 0x0E, 0x0F, // 00000
    0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,  0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E, 0x1F, // 00016
    ...
    ...
    0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,  0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF, // 32736
    0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,  0xF8, 0xF9, 0xFA, 0xFB,  0xFC, 0xFD, 0xFE        // 32752
};
extern const byte MC_ROM_0_LAST_BYTE = 0xFF;

Where the rom index +1 is used for the index of the fini part.

Parameters:
  • bitstrings (list(str)) – This of bitstrings that make up the rom.
  • rom_index (int) – Index of the rom beind written (index in the list of all the roms being written to the arduino).
  • header_filename (str) – Name of the header file, e.g. “mc_rom_0.h”.
  • rom_var_name (str) – The variable name used for the rom data in the arduino code.
Returns:

String ready to be written to cpp file

Return type:

str

eight_bit_computer.export.create_arduino_header(header_file_basename, rom_var_name)[source]

Create arduino header file

The header file looks like this:

#ifndef MC_ROM_0_H
#define MC_ROM_0_H

#include <Arduino.h>

extern const byte MC_ROM_0[];
extern const byte MC_ROM_0_LAST_BYTE;

#endif
Parameters:
  • header_file_basename (str) – The basename of the header file. E.g. if the header file is named mc_rom_0.h, the basename is mc_rom_0.
  • rom_var_name (str) – The variable name used for the rom data in the arduino code.
Returns:

String ready to be written to a file.

Return type:

str

eight_bit_computer.export.chunker(seq, chunk_size)[source]

Take a larger sequence and split it into smaller chunks.

E.g.:

chunker([0,1,2,3,4,5], 4) -> [0,1,2,3], [4,5]
Parameters:
  • seq (list) – List of things to chunk up
  • chunk_size (int) – How big each chunk should be.
Returns:

Generator that yields each chunk.

Return type:

generator

eight_bit_computer.export.write_arduino_pair(bitstrings, output_dir, file_basename, rom_var_name, rom_index)[source]

Write the header and cpp files for the arduino roms.

Parameters:
  • bitstrings (list(str)) – List of bitstrings that will make up the rom.
  • output_dir (str) – Directory (relative or absolute) to output the pair of files into.
  • file_basename (str) – Basename of the h and cpp files. The basename is the part of the file without the extention or the period.
  • rom_var_name (str) – The variable name used for the rom data in the arduino code.
  • rom_index (int) – Index of the rom to be written. This index is the index in the sequence of all roms to be written to the arduino.
eight_bit_computer.export.gen_logisim_program_file(assembly_line_infos)[source]

Generate contents for logisim files holding a program.

Parameters:assembly_line_infos (list(dict)) – List of dictionaries of information about the parsed assembly.
Returns:Content of the logisim file.
Return type:str
eight_bit_computer.export.extract_machine_code(assembly_lines)[source]

Extract machine code from assembly line dictionaries.

Parameters:assembly_lines (list(dict)) – List of assembly line info dictionaries to extract machine code from. See get_assembly_line_template() for details on what those dictionaries contain.
Returns:List of bit strings for the machine code.
Return type:list(str)
eight_bit_computer.export.extract_variables(assembly_lines)[source]

Extract variables from assembly line dictionaries.

Parameters:assembly_lines (list(dict)) – List of assembly line info dictionaries to extract variables from. See get_assembly_line_template() for details on what those dictionaries contain.
Returns:List of bit strings for the machine code. Empty list if there’s no variables
Return type:list(str)
eight_bit_computer.export.combine_mc_and_variable_bitstrings(mc_byte_bitstrings, variable_bitstrings)[source]

Combine machine code and variables into a single appropriately padded list.

Parameters:
  • mc_byte_bitstrings (list(str)) – List of bitstrings that make up the machine code.
  • variable_bitstrings (list(str)) – List of bitstrings that represent the variables.
Returns:

List of the machine code and variable bitstrings, padded to that the variables begin at byte 257.

Return type:

list(str)

eight_bit_computer.export.bitstrings_to_logisim(bitstrings)[source]

Convert bitstrigs to a logisim RAM/ROM file format.

Used to convert ROMs and machine code.

Parameters:bitstrings (list(str)) – List of bitstrings to convert to a logisim friendly format.
Returns:String ready to be written to a file.
Return type:str
eight_bit_computer.export.gen_arduino_program_h_file(h_basename)[source]

Generate header file for program for Arduino.

The header file looks like this:

#ifndef PROG_FIBONACCI_H
#define PROG_FIBONACCI_H

#include <Arduino.h>

extern const byte num_fibonacci_program_bytes;
extern const byte fibonacci_program_bytes[];

extern const byte num_fibonacci_data_bytes;
extern const byte fibonacci_data_bytes[];

extern const char fibonacci_program_name[];

#endif
Parameters:h_basename (str) – The filename (with no extension) for the file.
Returns:String ready to be written to a file.
Return type:str
eight_bit_computer.export.gen_arduino_program_cpp_file(assembly_line_infos, filename_base, h_filename)[source]

Generate cpp file for program for Arduino.

The cpp file looks like this:

#include "prog_fibonacci.h"

extern const byte num_fibonacci_program_bytes = 13;
extern const byte fibonacci_program_bytes[] PROGMEM = {
    0x39, // 000 SET A #1 (@set_initial)
    0x01, // 001 (1)
    0x3A, // 002 SET B #1
    0x01, // 003 (1)
    0x08, // 004 COPY A ACC (@fib_loop)
    0xCE, // 005 ADD B
    0x24, // 006 JUMP_IF_OVERFLOW_FLAG @set_initial
    0x00, // 007 (0)
    0x03, // 008 COPY ACC C (to display)
    0x11, // 009 COPY B A
    0x02, // 010 COPY ACC B
    0x3D, // 011 JUMP @fib_loop
    0x04  // 012 (4)
};

extern const byte num_fibonacci_data_bytes = 0;

// Needs to be at least 1 byte in this array
extern const byte fibonacci_data_bytes[] PROGMEM = {
    0x00 // Placeholder.
};

// Max of seven characters
extern const char fibonacci_program_name[] = "Fbnacci";
Parameters:
  • assembly_line_infos (list(dict)) – List of assembly line info dictionaries to extract variables from. See get_assembly_line_template() for details on what those dictionaries contain.
  • filename_base (str) – The basename (no extension) for the file. Also used as a general identifier.
  • h_filename (str) – The filename of the headerfile (including extension).
Returns:

String ready to be written to a file.

Return type:

str

eight_bit_computer.export.extract_program_file_machinecode_info(assembly_line_infos)[source]

Get necessary machine code info for arduino cpp file.

Parameters:assembly_line_infos (list(dict)) – List of assembly line info dictionaries to extract variables from. See get_assembly_line_template() for details on what those dictionaries contain.
Returns:str)): Bitstring and relevant comment for each machinecode byte.
Return type:list(dict(str
eight_bit_computer.export.extract_program_file_variable_info(assembly_line_infos)[source]

Pull out the info to write variables to program arduino cpp file.

Parameters:assembly_line_infos (list(dict)) – List of assembly line info dictionaries to extract variables from. See get_assembly_line_template() for details on what those dictionaries contain.
Returns:List of variable values and names. Spots with no variables are filled with placeholders.
Return type:list(dict)
eight_bit_computer.language_defs module

Defnitions for the machine code and microcode.

eight_bit_computer.language_defs.instruction_byte_from_bitdefs(bitdefs)[source]

Extract an instruction byte from the bitdefs that make it up.

If more than one bitdef is passed it will be merged with the others prior to extraction.

Parameters:list (bitdefs) – List of bitdefs to potentially merge and extract
Returns:Bitstring of the instruction byte
Return type:str
eight_bit_computer.main module

Top level interface for the module

eight_bit_computer.main.assemble(input_filepath, output_filename_base=None, output_dir=None, output_format='logisim')[source]

Read an assembly file and write out equivalent machine code.

Parameters:
  • input_filepath (str) – The location of the assembly file.
  • output_filename_base (str) (optional) – The location to write out the machine code (without extension). If nothing is passed, the output path will be the input filename with the extension changed to mc.
  • output_dir (str) (optional) – The directory to write the assembled code into.
  • output_format (str) (optional) – How to format the output. logisim or arduino.
eight_bit_computer.main.write_bitstrings_to_logisim(assembly_line_infos, output_dir, output_filename_base)[source]

Write machine code and variable bitstrings to logisim format.

Parameters:
  • assembly_line_infos (list(dict)) – List of dictionaries of information about the parsed assembly.
  • output_dir (str) – The directory to write the assembled code into.
  • output_filename_base (str) – the basename (no extension) for the logisim file.
eight_bit_computer.main.write_bitstrings_to_arduino(assembly_line_infos, output_dir, output_filename_base)[source]

Write machine code and variable bitstrings to arduino format.

Parameters:
  • assembly_line_infos (list(dict)) – List of dictionaries of information about the parsed assembly.
  • output_dir (str) – The directory to write the assembled code into.
  • output_filename_base (str) – The filename (with no extension) for the file.
eight_bit_computer.main.filepath_to_lines(input_filepath)[source]

Take a filepath and get all the lines of the file.

The lines returned have the newline stripped.

Parameters:input_filepath (str) – Path to the file of disk to read.
Returns:Lines of the file.
Return type:list(str)
eight_bit_computer.main.get_mc_filename(asm_path)[source]

Get the filename for the machine code.

This is the assembly filename with .asm replaced with .mc

Parameters:asm_path (str) – Path to the assembly file.
Returns:Path to the machine code file.
Return type:str
eight_bit_computer.main.gen_roms(output_dir='.', file_prefix=None, output_format='logisim')[source]

Write files containing microcode for drive the roms.

Parameters:
  • output_dir (str) (optional) – The directory to write the roms into.
  • file_prefix (str) (optional) – The prefix for the rom files.
  • output_format (str) (optional) – How to format the output. logisim or arduino.
eight_bit_computer.number_utils module

Functions for working with, checking and converting numbers.

All numbers are stored within the computer as the positive equivalent. They may be interpreted as negative.

eight_bit_computer.number_utils.number_to_bitstring(number, bit_width=8)[source]

Convert a number to an equivalent bitstring of the given width.

Raises:ValueError – If number doesn’t fit in the bit width.
eight_bit_computer.number_utils.number_is_within_bit_limit(number, bit_width=8)[source]

Check if a number can be stored in the number of bits given.

Negative numbers are stored in 2’s compliment binary.

Parameters:
  • number (int) – The number to check.
  • bit_width (int, optional) – The number of bits available.
Returns:

True if within limits, False if not.

Return type:

bool

eight_bit_computer.number_utils.get_positive_equivalent(number)[source]

Read the 2’s compliment equivalent of this number as positive.

With a 3 bit number, the positive equivalent of -2 is 5. E.g.:

-4 4 100
-3 5 101
-2 6 110
-1 7 111
 0 0 000
 1 1 001
 2 2 010
 3 3 011
Parameters:number (int) – The number to convert to a positive quivalent
Returns:The positive equivalent of the number.
Return type:int
eight_bit_computer.number_utils.bitstring_to_number(bitstring)[source]

Convert a bitstring to a number.

E.g. 10110101 gives 181.

Parameters:bitstring (str) – String of 1s and 0s.
Returns:The equivalent integer.
Return type:int
eight_bit_computer.number_utils.bitstring_to_hex_string(bitstring, zero_pad_width=2)[source]

Convert a bitstring to a hex number.

Parameters:
  • bitstring (str) – String of 1s and 0s.
  • zero_pad_width (int) (optional) – How many zeroes to pad the returned hex value with.
eight_bit_computer.operation_utils module

Common functions for operations.

eight_bit_computer.operation_utils.assemble_instruction(instruction_bitdefs, flags_bitdefs, control_steps)[source]

Create templates for all steps to form a complete instruction.

Parameters:
  • instruction_bitdefs (list(str)) – List of the bitdefs that make up the instruction byte.
  • flags_bitdefs – list(str): List of the bitdefs that make up the flags for this instruction.
  • control_steps – list(list(str): List of list of bitdefs that make up the control signals for each step.
Returns:

All the steps for this instruction.

Return type:

list(DataTemplate)

Raises:

ValueError – If too many steps were provided.

eight_bit_computer.operation_utils.add_quotes_to_strings(strings)[source]

Add double quotes strings in a list then join with commas.

Parameters:strings (list(str)) – List of strings to add parentheses to.
Returns:The strings with quotes added and joined with commas.
Return type:str
eight_bit_computer.operation_utils.match_and_parse_line(line, opcode, signatures=None)[source]

Examine assembly code to see if it is valid and parse the arguments.

This is a common function used by most of the assembly operations.

Parameters:
  • line (str) – The line of assembly code.
  • opcode (str) – The opcode this line is being tested to match.
  • signatures (list(list(dict)), optional) – Data structure that defines the different combinations of arguments. See get_arg_def_template() for more details.
Returns:

Whether or not the line matched, and if it did, the parsed arguments.

Return type:

(bool, list(dict))

Raises:
  • OperationParsingError – If multiple op_args defs matched. Or
  • if no op_args defs matched if the opcode matched (i.e. the
  • arguments weren’t valid for that assembly operation).
eight_bit_computer.operation_utils.generate_possible_signatures_list(signatures)[source]

Create a readable list of all possible signatures.

Parameters:signatures (list(list(dict))) – Data structure that defines the different combinations of arguments. See get_arg_def_template() for more details.
Returns:All possible argument combinations.
Return type:list(str)
eight_bit_computer.operation_utils.match_and_parse_args(line_args, signature)[source]

Parse assembly operation args if they match the definition.

Take arguments supplied for the assembly operation and see if they match this arguments definition.

Parameters:
  • line_args – (list(str)): The arguments supplied for this assembly operation.
  • signature (list(dict)) – Definition of a set of arguments. See get_arg_def_template() for more details.
Returns:

Whether or not the arguments matched, and if they did, the parsed values.

Return type:

(bool, list(dict))

Raises:

OperationParsingError – If a single argument managed to match different kinds of argument definitions.

eight_bit_computer.rom module

Create and export roms for the computer

eight_bit_computer.rom.get_rom()[source]

Get complete representation of the rom.

Returns:All the defined microcode.
Return type:list(RomData)
Raises:RuntimeError – When the romdata dataset has duplicate addresses.
eight_bit_computer.rom.collect_language_datatemplates()[source]

Get all the datatemplates from all the defined operations.

Returns:
All the data templates from the defined
operations
Return type:list(DataTemplate)
eight_bit_computer.rom.collapse_datatemplates_to_romdatas(datatemplates)[source]

Collapse any addresses in datatemplates to real values.

If an address does need collapsing the original data is copied out to all the collapsed addresses.

Parameters:list (datatemplates) – A list of templates to collapse.
Returns:The expanded datatemplates
Return type:list(RomData)
eight_bit_computer.rom.populate_empty_addresses(romdatas, all_addresses, default_data)[source]

Form a complete set of rom data by filling any undefined addresses.

Parameters:
  • list (romdatas) – The romdatas defined by the instructions.
  • all_addresses (list(str)) – List of bitdefs representing every address in the rom
  • default_data (str) – The value to set for any address that isn’t in romdatas.
Returns:

List of RomDatas representing a completely full

rom

Return type:

list(RomData)

eight_bit_computer.rom.romdatas_have_duplicate_addresses(romdatas)[source]

Check if any of the romdatas have duplicate addresses.

Parameters:list (romdatas) – List of romdatas to check.
Returns:Whether or not there were any duplicated addresses.
Return type:Bool
eight_bit_computer.rom.slice_rom(rom)[source]

Slice a rom into chunks 8 bits wide.

This is to prepare the data to write into the roms. To take a single RomData as an example, if it looked like this (spaces added for clarity):

RomData(
    address="0000000 0000 000",
    data="10101010 11111111 00000000 11001100"
)

We would end up with:

{
    0: RomData(
        address="0000000 0000 000",
        data="11001100"
    ),
    1: RomData(
        address="0000000 0000 000",
        data="00000000"
    ),
    2: RomData(
        address="0000000 0000 000",
        data="11111111"
    ),
    3: RomData(
        address="0000000 0000 000",
        data="10101010"
    )
}
Parameters:rom (list(RomData)) – The complete ROM
Returns:list(RomData)) Dictionary of ROM slices
Return type:dict(int
eight_bit_computer.rom.get_num_bytes(bitstring)[source]

Get the number of bytes needed to store this bitdef.

Parameters:bitstring (str) – Bitstring representing the bits to store.
Returns:The number of bytes needed to store the bitstring.
Return type:int
eight_bit_computer.rom.get_romdata_slice(romdatas, end, start)[source]

Get a slice of the data in the romdatas.

Parameters:
  • romdatas (list(RomData)) – The romdatas to get a slice from
  • end (int) – The index for the end of the slice. Starts at zero at the rightmost (least significant) bit.
  • start (int) – The index for the start of the slice. Starts at zero at the rightmost (least significant) bit.
Returns:

The sliced list of romdatas

Return type:

list(RomData)

eight_bit_computer.rom.get_decimal_rom()[source]

Get complete representation of the decimal rom.

Returns:All the defined data for the decima rom.
Return type:list(RomData)
Raises:RuntimeError – When the decimal romdata dataset has duplicate addresses.
eight_bit_computer.token_utils module

Functionality for working with string tokens on assembly lines

eight_bit_computer.token_utils.is_label(test_string)[source]

Test if a string is a valid label.

Parameters:test_string (str) – The string to test
Returns:True if the string is a valid label, false otherwise.
Return type:bool
eight_bit_computer.token_utils.is_variable(test_string)[source]

Test if a string is a valid variable.

Parameters:test_string (str) – The string to test
Returns:True if the string is a valid variable, false otherwise.
Return type:bool
eight_bit_computer.token_utils.is_constant(test_string)[source]
eight_bit_computer.token_utils.is_number(test_string)[source]

Test if a string is a valid number.

Parameters:test_string (str) – The string to test
Returns:True if the string is a valid number, false otherwise.
Return type:bool
eight_bit_computer.token_utils.number_constant_value(number_constant)[source]

Get the value that a number constant represents.

Parameters:number_constant (str) – The constant to extract the value from.
Returns:The value of the constant.
Return type:int
eight_bit_computer.token_utils.is_memory_index(argument)[source]

Determine whether this argument is a memory index.

Memory indexes can be module names or constants with a [ at the start and a ] at the end. e.g.:

  • [A]
  • [#42]
  • [$variable]
Parameters:argument (str) – The argument being used for the assembly operation.
Returns:True if the argument is a memory index, false if not.
Return type:bool
eight_bit_computer.token_utils.represent_as_memory_index(argument)[source]

Format the argument so it appears as a memory index.

See is_memory_index() for details on what a memory index is.

Parameters:argument (str) – The argument to represent as a memory index.
Returns:The formatted argument.
Return type:str
eight_bit_computer.token_utils.extract_memory_position(argument)[source]

Extract a memory position from a memory index argument.

See is_memory_index() for details of what a memory index is.

Parameters:argument (str) – The argument to extract a memory position from.
Returns:The location in memory being referenced.
Return type:str
eight_bit_computer.token_utils.get_tokens_from_line(line)[source]

Given a line split it into tokens and return them.

Tokens are runs of characters separated by spaces. If there are no tokens return an empty list.

Parameters:line (str) – line to convert to tokens
Returns:The tokens
Return type:list(str)

Module contents

Development Tools

Logisim

Fritzing

Falstad Circuit Simulator

Credits

This project would not have been possible without the generosity of the following people:

Ben Eater

James Bates