Skip to content

Instantly share code, notes, and snippets.

@Robertobean
Last active July 3, 2018 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Robertobean/7ae883efe58f32c138517e3c0df31d85 to your computer and use it in GitHub Desktop.
Save Robertobean/7ae883efe58f32c138517e3c0df31d85 to your computer and use it in GitHub Desktop.

Installation:

pip install PyTech

How to import PyTech:

from PyTech.structure import *

or just

import PyTech.structure

PyTech's name still follows PyTech, to try and make it easier for you folks.

PyTech is a library to emulate the movement of data through a computer. In PyTech.structure (currently the only feature) you will find some usefull classes.

structure.Cpu.init(bit=64, input_registries=10240, output_registries=10240):

set ups the registries and defines the bytesize for the CPU. 
Other possible arguments are: runtag, inttag, floattag, and 		
functag. Those represent the ascii values for escape characters of 
special identities when in use by the CPU's assembler. (see structure.Cpu.run)

structure.Cpu.set_input_registry(num, registry):

takes a bytes object representing a float in the 
specified bytesize and stores it to the identified input registry

structure.Cpu.get_input_registry(registry, unpacked=False):

searches the input registries in the CPU and returns the bytes 
found there or the float interpretation of them based on the unpacked argument

structure.Cpu.set_output_registry(num, registry):

takes a bytes object representing a float in the specified 
bytesize and stores it to the identified output registries

structure.Cpu.get_output_registry(registry, unpacked=False):

searches the output registries in the CPU and returns the bytes found there 
or the float interpretation of them based on the unpacked argument

structure.Cpu.bind(function, bytetag):

takes a bytes object and assigns it to a function. Used like this:
Core.bind(lambda x, b'\x00\x00\x00\x00')

structure.Cpu.run(byte)

this is the assembler for the Cpu. There is special syntax for the bytes. The 	
bytes can be added one at a time or used all at 	
once. Here's a laydown of the syntax:

b't' represents the function escape character. 
After a binded function is called, the arguments should follow right after. 
In code, it looks like this. 

>>> Import PyTech, struct
>>> Core = PyTech.structure.Cpu(bit=32)
>>> def hello_world():
.  .  .  	  print("hello, world")
>>> Core.bind(hello_world, b'\x01\x00\x00\x00')
>>> Core.run(b't\x01\x00\x00\x00')

hello, world

b'b' is the escape character for raw bytes. Use for arithmetic purposes.
b'i' is the escape character for an integer. Currently, it's only for defining pointers
b'f' is the float escape character and has no current implementation.

structure.Cpu.add(input_register_1, input_register_2, output_register):

adds the values found in input_register_1 and input_register_2 and stores them in output_register

structure.Cpu.sub(input_register1, input_register2, output_register):

subtracts the values found in input_register_1
and input_register_2 and stores them in output_register

structure.Cpu.mult(input_register1, input_register2, output_register):

multiplies the values found in input_register_1 and input_register_2 
and stores them in output_register

structure.Cpu.div(input_register1, input_register2, output_register):

divides the values found in input_register_1 and 
input_register_2 and stores them in output_register. Because 8 and 16 bit 		
types do not support floating point, a rounded divison is used.

structure.Cpu.lessthan(input_register1, input_register2, output_register):

if the value found at input_register_1 is lower than input_register_2, 
the bytes equivalent to "1" is stored in output_register. otherwise, 0 is stored there.

structure.Cpu.greaterthan(input_register1, input_register2, output_register):

if the value found at input_register_1 is greater than input_register_2, 
the bytes equivalent to "1" is stored in output_register. otherwise, 0 is stored there.

structure.Cpu.binForm(data):

returns the data in bytes form based on the bytesize specified for the CPU

structure.Cpu.binDeform(bytes):

takes bytes and turns them into a float based on the bytesize specified for the CPU

The Ram class is much simpler. The Ram class stores bytes in objects called "cells", short for memory cells. There are several functions to manipulate the cells.

structure.Ram.init(cells=1048576, bit=64)

creates a list of the cells for use, and specifies 
the bytesize for the Ram's memory cells.

structure.Ram.set_cell(num, cell)

Finds the cell at the position specified and makes it equal to num.
num must be a bytes object.

structure.Ram.get_cell(cell, unpacked=False)

Finds the cell at the position position specified and returns it.
Unpacked specifies wether it is a bytes object or float. 
False returns a byte object, True returns a float.

structure.Ram.swap_cells(cell1, cell2)

finds data at the positions specified and switches the data between the cells,
    so that a now equals b, and b equals former a

structure.Ram.binForm(data)

returns the data in bytes form based on the bytesize specified for the RAM

structure.Ram.binDeform(byte)

takes bytes and turns them into a float based on the bytesize specified for the RAM

the InputOutput class allows a way for userdata to be collected, and is connectable to the RAM and CPU. Uses the python terminal. A Tkinter and PyKeyboard method are planned for a future update

structure.InputOutput.init(bit=64, in_registers=1024, out_registers=1024)

specifies the amount of input and outout registries to be used later, 
and the bytesize for the module.

structure.InputOutput.set_input_registry(num, input_register)

stores num, a bytes object, and the specified input registry.

structure.InputOutput.set_output_registry(num, output_register)

stores num, a bytes object, and the specified output registry.

structure.InputOutput.get_input_registry(num, output_register)

finds the bytes object stored at the specified 
spot in the input registers and returns it

structure.InputOutput.get_output_registry(num, output_register)

finds the bytes object stored at the specified spot in the 
output registers and returns it

structure.InputOutput.input(num, output_register, input_type=1)

Takes user input from the python shell and stores it in the specified 
output register, under the input_type. 

input_type:
0 prompts user to type one character
1 prompts user to type a float
2 prompts user to type in base-2
3 prompts user to type in base-16

Note: doesn't shadow the builtin input() function due to it's being a class method

structure.InputOutput.output(num, input_register, output_type=1)

output_type follows the previous rules set in place by structure.InputOutput.input.
Takes the data stored in the input_register and converts is according to output_type, then displays it.

InputOutput Doesn't include binForm or binDeform

The Motherboard class serves as a way of connecting two parts. It does this by returning a class Connection that contains the two parts together with a method "transfer" and some more soon to come.

structure.Motherboard.init(bit=64)

specifies bytesize for the Motherboard. All connected parts must match this bytesize.

structure.Motherboard.add_connection(part1, part2)

checks to see if the bytesizes match for all parts and then returns a 
Connection class instance containing both parts.

structure.Motherboard.binForm(data)

returns the data in bytes form based on the bytesize specified for the Motherboard

structure.Motherboard.binDeform(byte)

takes bytes and turns them into a float based on the bytesize specified for the Motherboard

The Connection class is returned by Motherboard through the method "add_connection". I do not recommend using the Connection class directly without the Motherboard, due to the possibility of mismatching parts with different bytesizes.

structure.Connection.init(connection_tuple)

connection_tuple should be a tuple or list containing the instances of the two 	connected parts.

structure.Connection.transfer(register_1, register_2)

Takes output from the first part at register_1 and moves it to the input of the second part at register_2. 
For Ram, memory cells can count as input or output.

Here's a nice program that takes User input, adds it, then displays it.

from PyTech.structure import *
BYTESIZE = 32
KILOBYTE = 1024
MEGABYTE = 1048576

Core = Cpu(bit=BYTESIZE, in_registries=KILOBYTE, out_registries=KILOBYTE, inttag=112)
Card = Ram(bit=BYTESIZE, cells=MEGABYTE) 
Board = Motherboard(bit=BYTESIZE)
IO = InputOutput(bit=BYTESIZE, in_registries=KILOBYTE, out_registries=KILOBYTE)

CpuToRam = Board.add_connection(Core, Card)
RamToCpu = Board.add_connection(Card, Core)
RamToIO = Board.add_connection(Card, IO)
IOToRam = Board.add_connection(IO, Card)

Core.bind(Core.add, Board.binForm(0))
Core.bind(Core.set_input_registry, Board.binForm(1))
Core.bind(IO.input, Board.binForm(2))
Core.bind(IO.output, Board.binForm(3))
Core.bind(IOToRam.transfer, Board.binForm(4))
Core.bind(RamToIO.transfer, Board.binForm(5))
Core.bind(RamToCpu.transfer, Board.binForm(6))
Core.bind(CpuToRam.transfer, Board.binForm(7))

TakeInput1 = b't' + Board.binForm(2) + b'p' + Board.binForm(1023) + b'p' + Board.binForm(1)
MoveInput1ToRam1 = b't' + Board.binForm(4) + b'p' + Board.binForm(1023) + b'p' + Board.binForm(1023)
TakeInput2 = b't' + Board.binForm(2) + b'p' + Board.binForm(1022) + b'p' + Board.binForm(1)
MoveInput2ToRam2 = b't' + Board.binForm(4) + b'p' + Board.binForm(1022) + b'p' + Board.binForm(1022)
MoveRam1ToCpu1 = b't' + Board.binForm(6) + b'p' + Board.binForm(1023) + b'p' + Board.binForm(1023)
MoveRam2ToCpu2 = b't' + Board.binForm(6) + b'p' + Board.binForm(1022) + b'p' + Board.binForm(1022)
Add = b't' + Board.binForm(0) + b'p' + Board.binForm(1022) + b'p' + Board.binForm(1023) + b'p' + Board.binForm(1023)
MoveOutputToRam = b't' + Board.binForm(7) + b'p' + Board.binForm(1023) + b'p' + Board.binForm(1021)
MoveRamToIO = b't' + Board.binForm(5) + b'p' + Board.binForm(1021) + b'p' + Board.binForm(1021)
Display = b't' + Board.binForm(3) + b'p' + Board.binForm(1021)

Compiled = TakeInput1 + MoveInput1ToRam1 + TakeInput2 + MoveInput2ToRam2 + MoveRam1ToCpu1 + MoveRam2ToCpu2 + Add + MoveOutputToRam + MoveRamToIO + Display
Core.run(Compiled + b'r')

Features to be added:

Conditionals

Tkinter interface with pixel access

PyKeyboard instead of python shell

Hardrive file in the sitepackages lib for saving info

Bootdrive as well

@Robertobean
Copy link
Author

That code at the end is just a really tiny sliver of what computers actually have to do to complete that task

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment