├── Makefile ├── README.md ├── UNLICENSE ├── aoc ├── aocproxy └── lib │ └── SCAMP │ ├── AdventOfCode.pm │ ├── Files.pm │ └── Serial.pm ├── arduino ├── eeprom-burner-24lc256 │ └── eeprom-burner-24lc256.ino ├── eeprom-burner │ └── eeprom-burner.ino └── ram-test │ └── ram-test.ino ├── asm ├── asm ├── mk-asm-parser └── mk-table-html ├── bad-binaries ├── 20211215.bad ├── 20211215.good ├── 20211215.sl ├── 20211220.1stpass.bad ├── 20211220.1stpass.good ├── 20211220.bad ├── 20211220.good ├── 20211220.sl └── README.md ├── bootrom-debug.s ├── bootrom-fpga.s ├── bootrom.s ├── case ├── card-lever.FCStd ├── card-lever.stl ├── card-rail.FCStd ├── card-rail.stl ├── case.FCStd ├── horizontal-brace.FCStd ├── horizontal-brace.stl └── rod-holder.stl ├── compiler ├── peepopt ├── slangc └── test │ ├── foot.s │ ├── head.s │ ├── list.sl │ ├── malloc.sl │ ├── run │ ├── run-test.sh │ ├── srun │ ├── stdio.sl │ ├── stdlib.sl │ ├── string.sl │ ├── test.out │ └── test.sl ├── doc ├── ALU.md ├── AOC.md ├── ASSEMBLER.md ├── BIGINT.md ├── BOOT.md ├── CARDS.md ├── COMPILER.md ├── COMPILING.md ├── DEVENV ├── FILESYSTEM.md ├── ISA.md ├── LINKING.md ├── LISP.md ├── OS.md ├── PIC.md ├── SELFHOST-TEST.md ├── SUSPEND.md ├── SYSCALLS.md ├── UCODE.md ├── architecture.png ├── asciinema.png ├── card-cage.jpeg ├── case.jpeg ├── computer.jpeg ├── diagram.drawio ├── front-panels.jpeg ├── hamurabi.png ├── lib-file-template.tex ├── lib-function-template.tex ├── lib-ref-template.tex ├── lib │ └── SLANG │ │ └── Tex.pm ├── mk-blobs-tex ├── mk-file-tex ├── mk-lib-ref ├── table.html └── youtube.png ├── emulator ├── Makefile ├── profhtml └── scamp.c ├── front-panels ├── alu-panel.FCStd ├── alu-panel.svg ├── bracket.FCStd ├── bracket.stl ├── cf-spacer.FCStd ├── cf-spacer.stl ├── instruction-panel.FCStd ├── instruction-panel.svg ├── memory-panel.FCStd ├── memory-panel.stl ├── memory-panel.svg ├── serial-connector.FCStd ├── serial-connector.stl ├── serial-panel.FCStd ├── serial-panel.svg ├── storage-panel.FCStd ├── storage-panel.stl ├── storage-panel.svg ├── test-holes.FCStd └── test-holes.stl ├── fs ├── fs ├── lib │ └── SCAMP │ │ └── FS.pm ├── mkfs ├── run-test.sh ├── test.in ├── test.out ├── testfile1 └── testfile2 ├── jesmon.s ├── kernel ├── Makefile ├── blkdev.sl ├── build.sh ├── cf.sl ├── data.sl ├── dir.sl ├── foot.s ├── fs.in ├── fs.sl ├── head.s ├── install ├── kernel-name-selfhost.sl ├── kernel.sl ├── kprintf.sl ├── mk-kernel-name ├── motd ├── run ├── serial.sl ├── sys.sl ├── sys_dir.sl ├── sys_fs.sl ├── sys_io.sl ├── sys_proc.sl ├── sys_random.sl └── util.sl ├── kicad ├── alu │ ├── alu-cache.lib │ ├── alu.kicad_pcb │ ├── alu.net │ ├── alu.pro │ ├── alu.sch │ ├── alu.zip │ ├── alu4.sch │ └── gerber │ │ ├── alu-B_Cu.gbr │ │ ├── alu-B_Mask.gbr │ │ ├── alu-B_SilkS.gbr │ │ ├── alu-Edge_Cuts.gbr │ │ ├── alu-F_Cu.gbr │ │ ├── alu-F_Mask.gbr │ │ ├── alu-F_SilkS.gbr │ │ ├── alu-NPTH.drl │ │ └── alu-PTH.drl ├── backplane │ ├── backplane.kicad_pcb │ ├── backplane.pro │ ├── backplane.sch │ ├── gerber.zip │ └── gerber │ │ ├── backplane-B_Cu.gbr │ │ ├── backplane-B_Mask.gbr │ │ ├── backplane-B_SilkS.gbr │ │ ├── backplane-Edge_Cuts.gbr │ │ ├── backplane-F_Cu.gbr │ │ ├── backplane-F_Mask.gbr │ │ ├── backplane-F_SilkS.gbr │ │ ├── backplane-NPTH.drl │ │ ├── backplane-PTH.drl │ │ └── backplane.drl ├── connector.sch ├── eeprom-burner │ ├── eeprom-burner.kicad_pcb │ ├── eeprom-burner.pro │ ├── eeprom-burner.sch │ └── gerber │ │ ├── eeprom-burner-B_Cu.gbr │ │ ├── eeprom-burner-Edge_Cuts.gbr │ │ ├── eeprom-burner-F_SilkS.gbr │ │ ├── eeprom-burner.drl │ │ └── mk-gcode ├── instruction │ ├── gerber │ │ ├── instruction-B_Cu.gbr │ │ ├── instruction-B_Mask.gbr │ │ ├── instruction-B_SilkS.gbr │ │ ├── instruction-Edge_Cuts.gbr │ │ ├── instruction-F_Cu.gbr │ │ ├── instruction-F_Mask.gbr │ │ ├── instruction-F_SilkS.gbr │ │ ├── instruction-NPTH.drl │ │ └── instruction-PTH.drl │ ├── instruction.kicad_pcb │ ├── instruction.net │ ├── instruction.pro │ ├── instruction.sch │ ├── instruction.zip │ ├── ir.sch │ └── pc.sch ├── memory │ ├── gerber │ │ ├── memory-B_Cu.gbr │ │ ├── memory-B_Mask.gbr │ │ ├── memory-B_SilkS.gbr │ │ ├── memory-Edge_Cuts.gbr │ │ ├── memory-F_Cu.gbr │ │ ├── memory-F_Mask.gbr │ │ ├── memory-F_SilkS.gbr │ │ ├── memory-NPTH.drl │ │ └── memory-PTH.drl │ ├── memory.kicad_pcb │ ├── memory.net │ ├── memory.pro │ ├── memory.sch │ └── memory.zip ├── scamp.dcm ├── scamp.lib ├── serial │ ├── gerber.zip │ ├── gerber │ │ ├── serial-B_Cu.gbr │ │ ├── serial-B_Mask.gbr │ │ ├── serial-B_SilkS.gbr │ │ ├── serial-Edge_Cuts.gbr │ │ ├── serial-F_Cu.gbr │ │ ├── serial-F_Mask.gbr │ │ ├── serial-F_SilkS.gbr │ │ ├── serial-NPTH.drl │ │ └── serial-PTH.drl │ ├── serial.kicad_pcb │ ├── serial.net │ ├── serial.pro │ ├── serial.sch │ └── uart8250.sch └── storage │ ├── cfcard.sch │ ├── storage-cache.lib │ ├── storage.kicad_pcb │ ├── storage.net │ ├── storage.pro │ └── storage.sch ├── pdf ├── 74125.pdf ├── 74138.pdf ├── 74161.pdf ├── 74273.pdf ├── 7474.pdf ├── 74hc245.pdf ├── 8250.jpeg ├── 8250.pdf ├── at28c16.pdf ├── cd4504.pdf ├── ip82c50a-5.pdf ├── lec12_sd_card.pdf ├── led-housing.pdf ├── lisp.pdf ├── sandisk-compactflash.pdf ├── ti-compact-flash-spra803.pdf └── w24512a.pdf ├── sys ├── Makefile ├── aoc.sl ├── asm.sl ├── baud.sl ├── build.sh ├── cat.sl ├── cp.sl ├── dc.sl ├── df.sl ├── diskid.sl ├── du.sl ├── echo.sl ├── fc.sl ├── fsck.sl ├── grep.sl ├── hamurabi.sl ├── hd.sl ├── head.sl ├── init.sl ├── isprime.sl ├── keys.sl ├── kilo.sl ├── kwr.sl ├── lib │ ├── bigint.sl │ ├── bitmap.sl │ ├── bufio.sl │ ├── fixed.sl │ ├── foot.s │ ├── getopt.sl │ ├── glob.sl │ ├── grarr.sl │ ├── hash.sl │ ├── head.s │ ├── heap.sl │ ├── libhead.s │ ├── malloc.sl │ ├── parse.sl │ ├── regex.sl │ ├── serial.sl │ ├── stdio.sl │ ├── stdlib.sl │ ├── strbuf.sl │ ├── string.sl │ ├── sys.sl │ ├── xprintf.sl │ └── xscanf.sl ├── lisp-builtins.sl ├── lisp.sl ├── lisp │ └── lib.l ├── ls.sl ├── make-lib ├── mandel.sl ├── mandelfix.sl ├── mk-rude-globals ├── mkdir.sl ├── more.sl ├── mv.sl ├── opts.sl ├── ps.sl ├── pwd.sl ├── reboot.sl ├── reset.sl ├── rm.sl ├── rsh.sl ├── rude-globals.sl ├── rude.sl ├── rx.sl ├── ser.sl ├── sh.sl ├── slangc.sl ├── slangi.sl ├── slc.sl ├── snake.sl ├── sort.sl ├── stat.sl ├── sx.sl ├── true.sl ├── wc.sl └── while.sl ├── test ├── fs.in ├── lib ├── run-test.sh ├── split-output ├── test.expect ├── test.sl ├── test_basic.sl ├── test_bigint.sl ├── test_bitmap.sl ├── test_grarr.sl ├── test_grep.sl ├── test_hash.sl ├── test_regex.sl └── test_sh.sl ├── test8250.s ├── testrom.s ├── ucode ├── mk-instructions-json ├── uasm └── ucode.s ├── util ├── bin2hex ├── burn-eeprom ├── burn-eeprom-24lc256 ├── dump-eeprom ├── dump-eeprom-24lc256 ├── hex2bin ├── hex2disk ├── pad-lines ├── swap-endian └── unix2scamp ├── verilog ├── alu.v ├── alu_tb.v ├── cards-alu-high.v ├── cards-alu-low.v ├── cards-cpu.v ├── cards-cpuimpl.v ├── cards-instr.v ├── cards-memory.v ├── cards-verbose_tb.v ├── computer.v ├── control.v ├── control_tb.v ├── cpu.v ├── cpu_tb.v ├── cpuimpl.v ├── fpga-alu.v ├── fpga-cpu.v ├── fpga-cpuimpl.v ├── fpga-ir.v ├── fpga-memory.v ├── fpga-pc.v ├── fpga-ram.v ├── fpga-rom.v ├── fpga-tstate.v ├── fpga-ucode.v ├── fpga.v ├── fpga_tb.v ├── fpgacpu.v ├── fr.v ├── fr_tb.v ├── iceFUN.pcf ├── ir.v ├── ir_tb.v ├── ledscan.v ├── memory.v ├── memory_tb.v ├── pc.v ├── pc_tb.v ├── ram.v ├── register.v ├── register_tb.v ├── rom.v ├── run-tests.sh ├── testrom-high.hex ├── testrom-low.hex ├── testrom.hex ├── top.v ├── tstate.v ├── tstate_tb.v ├── ttl-alu.v ├── ttl-alu4.v ├── ttl-control.v ├── ttl-cpu.v ├── ttl-fr.v ├── ttl-ir.v ├── ttl-memory.v ├── ttl-pc.v ├── ttl-register.v ├── ttl-tstate.v ├── ttl-ucode.v ├── ttl │ ├── 7400.v │ ├── 7402.v │ ├── 7404.v │ ├── 7407.v │ ├── 7408.v │ ├── 74125.v │ ├── 74126.v │ ├── 74138.v │ ├── 74153.v │ ├── 74157.v │ ├── 74161.v │ ├── 74244.v │ ├── 74283.v │ ├── 7432.v │ ├── 74377.v │ ├── 7486.v │ ├── README.md │ ├── at28c16.v │ ├── mos_6551.v │ └── w24512a.v ├── ucode-high.hex ├── ucode-low.hex ├── ucode.hex ├── ucode.v └── verbose_tb.v └── web ├── Makefile ├── package-lock.json └── public ├── index.html ├── node_modules └── xterm │ ├── .eslintrc.json │ ├── LICENSE │ ├── README.md │ ├── css │ └── xterm.css │ ├── lib │ ├── xterm.js │ └── xterm.js.map │ ├── package.json │ ├── src │ ├── browser │ │ ├── AccessibilityManager.ts │ │ ├── Clipboard.ts │ │ ├── Color.ts │ │ ├── ColorContrastCache.ts │ │ ├── ColorManager.ts │ │ ├── Dom.ts │ │ ├── Lifecycle.ts │ │ ├── Linkifier.ts │ │ ├── Linkifier2.ts │ │ ├── LocalizableStrings.ts │ │ ├── MouseZoneManager.ts │ │ ├── RenderDebouncer.ts │ │ ├── ScreenDprMonitor.ts │ │ ├── Terminal.ts │ │ ├── Types.d.ts │ │ ├── Viewport.ts │ │ ├── input │ │ │ ├── CompositionHelper.ts │ │ │ ├── Mouse.ts │ │ │ └── MoveToCell.ts │ │ ├── public │ │ │ ├── AddonManager.ts │ │ │ └── Terminal.ts │ │ ├── renderer │ │ │ ├── BaseRenderLayer.ts │ │ │ ├── CursorRenderLayer.ts │ │ │ ├── GridCache.ts │ │ │ ├── LinkRenderLayer.ts │ │ │ ├── Renderer.ts │ │ │ ├── RendererUtils.ts │ │ │ ├── SelectionRenderLayer.ts │ │ │ ├── TextRenderLayer.ts │ │ │ ├── Types.d.ts │ │ │ ├── atlas │ │ │ │ ├── BaseCharAtlas.ts │ │ │ │ ├── CharAtlasCache.ts │ │ │ │ ├── CharAtlasUtils.ts │ │ │ │ ├── Constants.ts │ │ │ │ ├── DynamicCharAtlas.ts │ │ │ │ ├── LRUMap.ts │ │ │ │ └── Types.d.ts │ │ │ └── dom │ │ │ │ ├── DomRenderer.ts │ │ │ │ └── DomRendererRowFactory.ts │ │ ├── selection │ │ │ ├── SelectionModel.ts │ │ │ └── Types.d.ts │ │ ├── services │ │ │ ├── CharSizeService.ts │ │ │ ├── CharacterJoinerService.ts │ │ │ ├── CoreBrowserService.ts │ │ │ ├── MouseService.ts │ │ │ ├── RenderService.ts │ │ │ ├── SelectionService.ts │ │ │ ├── Services.ts │ │ │ └── SoundService.ts │ │ └── tsconfig.json │ ├── common │ │ ├── CircularList.ts │ │ ├── Clone.ts │ │ ├── CoreTerminal.ts │ │ ├── EventEmitter.ts │ │ ├── InputHandler.ts │ │ ├── Lifecycle.ts │ │ ├── Platform.ts │ │ ├── TypedArrayUtils.ts │ │ ├── Types.d.ts │ │ ├── WindowsMode.ts │ │ ├── buffer │ │ │ ├── AttributeData.ts │ │ │ ├── Buffer.ts │ │ │ ├── BufferLine.ts │ │ │ ├── BufferRange.ts │ │ │ ├── BufferReflow.ts │ │ │ ├── BufferSet.ts │ │ │ ├── CellData.ts │ │ │ ├── Constants.ts │ │ │ ├── Marker.ts │ │ │ └── Types.d.ts │ │ ├── data │ │ │ ├── Charsets.ts │ │ │ └── EscapeSequences.ts │ │ ├── input │ │ │ ├── Keyboard.ts │ │ │ ├── TextDecoder.ts │ │ │ ├── UnicodeV6.ts │ │ │ └── WriteBuffer.ts │ │ ├── parser │ │ │ ├── Constants.ts │ │ │ ├── DcsParser.ts │ │ │ ├── EscapeSequenceParser.ts │ │ │ ├── OscParser.ts │ │ │ ├── Params.ts │ │ │ └── Types.d.ts │ │ ├── services │ │ │ ├── BufferService.ts │ │ │ ├── CharsetService.ts │ │ │ ├── CoreMouseService.ts │ │ │ ├── CoreService.ts │ │ │ ├── DirtyRowService.ts │ │ │ ├── InstantiationService.ts │ │ │ ├── LogService.ts │ │ │ ├── OptionsService.ts │ │ │ ├── ServiceRegistry.ts │ │ │ ├── Services.ts │ │ │ └── UnicodeService.ts │ │ └── tsconfig.json │ ├── tsconfig-base.json │ └── tsconfig-library-base.json │ ├── tsconfig.all.json │ └── typings │ └── xterm.d.ts └── scamp-worker.js /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /aoc/aocproxy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use FindBin; 7 | use lib "$FindBin::Bin/lib/"; 8 | 9 | use SCAMP::AdventOfCode; 10 | use SCAMP::Files; 11 | use SCAMP::Serial; 12 | 13 | my $serial = SCAMP::Serial->new(*STDIN, *STDOUT); 14 | 15 | my $aoc = SCAMP::AdventOfCode->new(); 16 | -f "$ENV{HOME}/.aoc-session" or die "Please write your Advent of Code session cookie value to $ENV{HOME}/.aoc-session\n"; 17 | $aoc->read_session("$ENV{HOME}/.aoc-session"); 18 | $aoc->attach($serial); 19 | 20 | my $files = SCAMP::Files->new(); 21 | $files->attach($serial); 22 | 23 | $serial->run; 24 | -------------------------------------------------------------------------------- /aoc/lib/SCAMP/Files.pm: -------------------------------------------------------------------------------- 1 | package SCAMP::Files; 2 | 3 | # TODO: [nice] support changing working directory 4 | # TODO: [bug] don't allow "../../../../../../../etc/passwd" etc. to grab arbitrary files 5 | 6 | use strict; 7 | use warnings; 8 | 9 | sub new { 10 | my ($pkg, %args) = @_; 11 | 12 | my $self = bless \%args, $pkg; 13 | 14 | return $self; 15 | } 16 | 17 | sub attach { 18 | my ($self, $serial) = @_; 19 | 20 | $serial->handle(get => 'file' => sub { 21 | my ($path) = @_; 22 | open (my $fh, '<', $path) 23 | or die "can't read $path: $!"; 24 | my $c = join('', <$fh>); 25 | close $fh; 26 | return $c; 27 | }); 28 | 29 | $serial->handle(put => 'file' => sub { 30 | my ($path, $content) = @_; 31 | open (my $fh, '>', $path) 32 | or die "can't write $path: $!"; 33 | print $fh $content; 34 | close $fh; 35 | return 'ok'; 36 | }); 37 | } 38 | 39 | 1; 40 | -------------------------------------------------------------------------------- /arduino/ram-test/ram-test.ino: -------------------------------------------------------------------------------- 1 | /* Simple Arduino program to test my understanding of how the RAM chip works */ 2 | 3 | int we_pin = 2; 4 | int oe_pin = 3; 5 | int addr_pin[] = {12,13}; 6 | int data_pin[] = {4,5,6,7,8,9,10,11}; 7 | 8 | void setup() { 9 | Serial.begin(9600); 10 | minit(); 11 | } 12 | 13 | void loop() { 14 | Serial.println("Write 42 to 0..."); 15 | mwrite(0, 42); 16 | Serial.println("Write 100 to 1..."); 17 | mwrite(1, 100); 18 | Serial.println("Read from 0..."); 19 | Serial.println(mread(0)); // expect 42 20 | Serial.println("Read from 1..."); 21 | Serial.println(mread(1)); // expect 100 22 | Serial.println(); 23 | delay(1000); 24 | } 25 | 26 | void minit() { 27 | pinMode(we_pin,OUTPUT); 28 | pinMode(oe_pin,OUTPUT); 29 | 30 | digitalWrite(we_pin, 1); 31 | digitalWrite(oe_pin, 1); 32 | 33 | for (int i = 0; i < 2; i++) 34 | pinMode(addr_pin[i], OUTPUT); 35 | } 36 | 37 | void mwrite(int addr, int val) { 38 | for (int i = 0; i < 8; i++) 39 | pinMode(data_pin[i], OUTPUT); 40 | 41 | for (int i = 0; i < 2; i++) 42 | digitalWrite(addr_pin[i], (addr & (1 << i)) ? 1 : 0); 43 | 44 | for (int i = 0; i < 8; i++) 45 | digitalWrite(data_pin[i], (val & (1 << i)) ? 1 : 0); 46 | 47 | delay(1); 48 | digitalWrite(oe_pin, 1); 49 | delay(1); 50 | digitalWrite(we_pin, 0); 51 | delay(1); 52 | digitalWrite(we_pin, 1); 53 | } 54 | 55 | int mread(int addr) { 56 | for (int i = 0; i < 8; i++) 57 | pinMode(data_pin[i], INPUT); 58 | 59 | for (int i = 0; i < 2; i++) 60 | digitalWrite(addr_pin[i], (addr & (1 << i)) ? 1 : 0); 61 | 62 | delay(1); 63 | digitalWrite(we_pin, 1); 64 | delay(1); 65 | digitalWrite(oe_pin, 0); 66 | delay(1); 67 | 68 | int val = 0; 69 | for (int i = 0; i < 8; i++) { 70 | val |= digitalRead(data_pin[i]) << i; 71 | } 72 | 73 | digitalWrite(oe_pin, 1); 74 | 75 | return val; 76 | } 77 | -------------------------------------------------------------------------------- /bad-binaries/20211215.bad: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/bad-binaries/20211215.bad -------------------------------------------------------------------------------- /bad-binaries/20211215.good: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/bad-binaries/20211215.good -------------------------------------------------------------------------------- /bad-binaries/20211215.sl: -------------------------------------------------------------------------------- 1 | include "bufio.sl"; 2 | include "grarr.sl"; 3 | 4 | var in = bfdopen(0, O_READ); 5 | 6 | var grid = vzmalloc([100,128]); 7 | 8 | var w = 0; 9 | var h; 10 | var y = 0; 11 | var x; 12 | while (bgets(in, grid[y], 128)) { 13 | w = strlen(grid[y])-1; 14 | y++; 15 | }; 16 | h = y; 17 | 18 | var bestpath = 0x7fff; 19 | var lastbestpath = 0x7fff; 20 | 21 | var risk = vzmalloc([h,w]); 22 | 23 | printf("%dx%d\n", [w,h]); 24 | 25 | var update = func(x,y) { 26 | var g = grid[y][x] - '0'; 27 | var gx = 0; var gy = 0; 28 | if (x > 0) gx = g + risk[y][x-1]; 29 | if (y > 0) gy = g + risk[y-1][x]; 30 | if ((x < w-1) && risk[y][x+1]) 31 | if ((g + risk[y][x+1]) < gx) 32 | gx = g + risk[y][x+1]; 33 | if ((y < h-1) && risk[y+1][x]) 34 | if ((g + risk[y+1][x]) < gy) 35 | gy = g + risk[y+1][x]; 36 | 37 | if (gx) g = gx; 38 | if (gy && gy < gx) g = gy; 39 | 40 | if ((risk[y][x] == 0) || (g < risk[y][x])) 41 | risk[y][x] = g; 42 | }; 43 | 44 | while (1) { 45 | y = 0; 46 | while (y < h) { 47 | x = 0; 48 | while (x < w) { 49 | update(x,y); 50 | x++; 51 | }; 52 | y++; 53 | }; 54 | bestpath = risk[h-1][w-1]; 55 | printf("%d\n", [bestpath]); 56 | if (bestpath < lastbestpath) { 57 | lastbestpath = bestpath; 58 | } else { 59 | printf("%d\n", [bestpath-(grid[0][0]-'0')]); 60 | break; 61 | }; 62 | }; 63 | -------------------------------------------------------------------------------- /bad-binaries/20211220.1stpass.bad: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/bad-binaries/20211220.1stpass.bad -------------------------------------------------------------------------------- /bad-binaries/20211220.1stpass.good: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/bad-binaries/20211220.1stpass.good -------------------------------------------------------------------------------- /bad-binaries/20211220.bad: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/bad-binaries/20211220.bad -------------------------------------------------------------------------------- /bad-binaries/20211220.good: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/bad-binaries/20211220.good -------------------------------------------------------------------------------- /bad-binaries/20211220.sl: -------------------------------------------------------------------------------- 1 | include "bufio.sl"; 2 | 3 | var in = bfdopen(0, O_READ); 4 | 5 | var enhance = malloc(513); 6 | bgets(in, enhance, 513); 7 | assert(bgetc(in) == '\n', "need newline after enhancement spec\n", 0); 8 | 9 | var grid = vzmalloc([108,108]); 10 | var grid2 = vzmalloc([108,108]); 11 | var y = 4; 12 | var x; 13 | var i = 0; 14 | while (i < 108) { 15 | memset(grid[y], '.', 108); 16 | memset(grid2[y], '#', 108); 17 | i++; 18 | }; 19 | 20 | while (bgets(in, grid[y]+3, 108)) { 21 | y++; 22 | }; 23 | 24 | var h = 108; 25 | var w = 108; 26 | 27 | var getnum = func(g, x, y) { 28 | var n = 0; 29 | var dy = 1; 30 | var dx; 31 | var bit = 1; 32 | while (dy >= -1) { 33 | dx = 1; 34 | while (dx >= -1) { 35 | if (g[y+dy][x+dx] == '#') n = n | bit; 36 | bit = bit + bit; 37 | dx--; 38 | }; 39 | dy--; 40 | }; 41 | return n; 42 | }; 43 | 44 | var step = func(g, g2) { 45 | var y = 1; 46 | var x; 47 | var n; 48 | puts("step"); 49 | while (y < h-1) { 50 | putchar('.'); 51 | x = 1; 52 | while (x < w-1) { 53 | n = getnum(g, x, y); 54 | g2[y][x] = enhance[n]; 55 | x++; 56 | }; 57 | y++; 58 | }; 59 | putchar('\n'); 60 | }; 61 | 62 | var countlit = func(g) { 63 | var y = 1; 64 | var x; 65 | var n = 0; 66 | while (y < h-1) { 67 | x = 1; 68 | while (x < w-1) { 69 | if (g[y][x] == '#') n++; 70 | x++; 71 | }; 72 | y++; 73 | }; 74 | return n; 75 | }; 76 | 77 | step(grid,grid2); 78 | step(grid2,grid); 79 | printf("%d\n", [countlit(grid)]); 80 | -------------------------------------------------------------------------------- /bad-binaries/README.md: -------------------------------------------------------------------------------- 1 | This directory contains samples of bad binaries to try and help me debug 2 | the "bad binary" problem, which is that sometimes the compiler outputs 3 | a binary that behaves incorrectly, and then when recompiled the exact 4 | same source code produces a binary that works fine. 5 | 6 | My best guess is that there is a hardware problem, but currently I'm just 7 | collecting samples in case any patterns become clear. 8 | 9 | I had a first look at it here: https://www.youtube.com/watch?v=BiFeisFLKhY 10 | -------------------------------------------------------------------------------- /bootrom-fpga.s: -------------------------------------------------------------------------------- 1 | ld sp, 0xff80 2 | 3 | loop: 4 | in r4, 0 5 | 6 | ld r100, 0 7 | 8 | push 0x0f # bits to set 9 | push 8 # bit to test 10 | call setbits 11 | 12 | push 0xf0 13 | push 4 14 | call setbits 15 | 16 | out 2, r100 17 | out 3, r100 18 | 19 | ld r100, 0 20 | 21 | push 0x0f 22 | push 2 23 | call setbits 24 | 25 | push 0xf0 26 | push 1 27 | call setbits 28 | 29 | out 0, r100 30 | out 1, r100 31 | 32 | jmp loop 33 | 34 | setbits: 35 | ld x, sp 36 | ld r20, 1(x) # bit to test 37 | ld r19, 2(x) # bits to set 38 | 39 | and r20, r4 40 | jz end 41 | 42 | or r100, r19 43 | 44 | end: 45 | ret 2 46 | -------------------------------------------------------------------------------- /case/card-lever.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/card-lever.FCStd -------------------------------------------------------------------------------- /case/card-lever.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/card-lever.stl -------------------------------------------------------------------------------- /case/card-rail.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/card-rail.FCStd -------------------------------------------------------------------------------- /case/card-rail.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/card-rail.stl -------------------------------------------------------------------------------- /case/case.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/case.FCStd -------------------------------------------------------------------------------- /case/horizontal-brace.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/horizontal-brace.FCStd -------------------------------------------------------------------------------- /case/horizontal-brace.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/horizontal-brace.stl -------------------------------------------------------------------------------- /case/rod-holder.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/case/rod-holder.stl -------------------------------------------------------------------------------- /compiler/test/foot.s: -------------------------------------------------------------------------------- 1 | 2 | # "halt" 3 | ld x, 0 4 | out 3, x 5 | 6 | # top of program address (initialised by head.s) 7 | _TOP: .word 0 8 | TOP: 9 | -------------------------------------------------------------------------------- /compiler/test/head.s: -------------------------------------------------------------------------------- 1 | .at 0x100 2 | 3 | # initialise sp and TOP 4 | .def STACKSZ 2048 5 | ld sp, TOP 6 | add sp, STACKSZ 7 | 8 | # stack grows down, _TOP grows up; 9 | # make _TOP point 1 word past the initial stack pointer 10 | ld (_TOP), sp 11 | inc (_TOP) 12 | 13 | -------------------------------------------------------------------------------- /compiler/test/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Run a source file in the emulator 3 | 4 | set -e 5 | 6 | if [ "$1" = "" ]; then 7 | echo "usage: run foo.sl" 8 | exit 1 9 | fi 10 | 11 | ../slangc < $1 > prog.s 12 | shift 13 | ./srun prog.s $@ 14 | -------------------------------------------------------------------------------- /compiler/test/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo test.sl... 4 | ./run test.sl > test.out.new 5 | diff test.out test.out.new && echo "ok" 6 | -------------------------------------------------------------------------------- /compiler/test/srun: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Run an assembled source file in the emulator 3 | 4 | set -e 5 | 6 | if [ "$1" = "" ]; then 7 | echo "usage: srun foo.s" 8 | exit 1 9 | fi 10 | 11 | asmsrc=$1 12 | 13 | shift 14 | # only peepopt prog.s because it's unsound on hand-written assembly code 15 | ../peepopt $asmsrc | ../peepopt > prog.opt.s 16 | cat head.s prog.opt.s foot.s | ../../asm/asm > prog.hex 17 | cd .. 18 | ../emulator/scamp -r test/prog.hex $@ 19 | -------------------------------------------------------------------------------- /compiler/test/string.sl: -------------------------------------------------------------------------------- 1 | include "malloc.sl"; 2 | 3 | # usage: strcmp(s1,s2) 4 | # return a value: 5 | # <0 if s1 < s2 6 | # 0 if s1 == s2 7 | # >0 if s1 > s2 8 | var strcmp = asm { 9 | pop x 10 | ld r2, x # r2 = s2 11 | pop x 12 | ld r1, x # r1 = s1 13 | 14 | # while (*s1 && *s2) 15 | strcmp_loop: 16 | ld x, (r1) 17 | and x, (r2) 18 | jz strcmp_done 19 | 20 | # if (*s1 != *s2) return *s1-*s2 21 | ld x, (r1) 22 | sub x, (r2) 23 | jz strcmp_cont 24 | ld r0, x 25 | ret 26 | 27 | strcmp_cont: 28 | inc r1 29 | inc r2 30 | jmp strcmp_loop 31 | strcmp_done: 32 | 33 | # return *s1-*s2 34 | ld x, (r1) 35 | sub x, (r2) 36 | ld r0, x 37 | ret 38 | }; 39 | 40 | var strlen = func(s) { 41 | var ss = s; 42 | while (*ss) ss++; 43 | return ss - s; 44 | }; 45 | 46 | var memset = func(s, val, len) { 47 | var ss = s; 48 | while (len--) *(s++) = val; 49 | return ss; 50 | }; 51 | 52 | var memcpy = func(dest, src, len) { 53 | var dd = dest; 54 | while (len--) *(dest++) = *(src++); 55 | return dd; 56 | }; 57 | 58 | var strcpy = func(dest, src) { 59 | var dd = dest; 60 | while (*src) *(dest++) = *(src++); 61 | *dest = 0; 62 | return dd; 63 | }; 64 | 65 | var strdup = func(s) { 66 | var ss = malloc(strlen(s)+1); 67 | strcpy(ss, s); 68 | return ss; 69 | }; 70 | -------------------------------------------------------------------------------- /doc/ASSEMBLER.md: -------------------------------------------------------------------------------- 1 | # Assembler 2 | 3 | (This is about the assembler written in SLANG, not the one written in Perl). 4 | 5 | The assembler writes code into a file, and writes unresolved symbol addresses to 6 | a different file. Once the first pass is finished, the generated code is re-processed, 7 | with unresolved symbols now resolved on the second pass. 8 | 9 | The parser uses the recursive descent parsing framework. The code to turn 10 | instructions into code is generated from `instructions.json` on a "modern" 11 | computer using `mk-asm-parser`. 12 | -------------------------------------------------------------------------------- /doc/BIGINT.md: -------------------------------------------------------------------------------- 1 | # Integer operations per second, by type 2 | 3 | | | int | big32 | big32/int | big64 | big64/int | 4 | | :-- | :---- | :---- | :-------- | :---- | :-------- | 5 | | add | 10000 | 2900 | 1300 | 2100 | 1000 | 6 | | mul | 1500 | 37 | 36 | 17 | 17 | 7 | | div | 680 | 22 | 20 | 11 | 10 | 8 | | cmp | 5700 | 2900 | 1700 | 2200 | 1300 | 9 | 10 | * `mod` throughput is the same as `div` in all cases 11 | * `cmp` means magnitude comparison (e.g. `<`, or `bigcmp()`) 12 | * `bigX` means both operands bigint (e.g. `bigadd()`) 13 | * `bigX/int` means the second operand is native int (e.g. `bigaddw()`) 14 | -------------------------------------------------------------------------------- /doc/BOOT.md: -------------------------------------------------------------------------------- 1 | # SCAMP Boot Process 2 | 3 | When the machine is reset, the program counter becomes 0. The first 256 words are ROM, and contain the bootloader. 4 | 5 | The bootloader loads the kernel from disk, see `bootrom.s`. 6 | 7 | The first 3 words of the disk should be: 8 | 9 | 1. magic number (0x5343) 10 | 2. start address 11 | 3. length 12 | 13 | The bootloader adds together all the 16-bit values that it reads (that is magic number, start address, length, 14 | and then `length` words). So the kernel data should be followed by a 16-bit checksum value that will make 15 | this all sum to 0. The checksum value can actually be anywhere in the kernel, as long as all the data sums to 0. 16 | 17 | So the disk will look like: 18 | 19 | [magic][start addr][length][kernel code][checksum][ ... gap ... ][filesystem data] 20 | 21 | The "... gap ..." is there to allow the kernel code to be replaced with a longer one without 22 | having to relocate the filesystem. 23 | 24 | Once the kernel is loaded, its job is: 25 | 26 | 1. initialise system call jump vectors or whatever 27 | 2. initialise peripherals 28 | 3. load init and execute it 29 | 30 | Init's job is currently just to display `/etc/motd/` and execute the shell, at which point the system is booted and ready 31 | to use. 32 | 33 | The program in `util/hex2disk` can take in a machine code program and turn it into a disk image 34 | that will load it into address 0x100. 35 | 36 | Example usage: 37 | 38 | $ asm/asm < prog.s > prog.hex 39 | $ util/hex2disk < prog.hex > prog.disk 40 | $ cd emulator/; ./scamp -i ../prog.disk 41 | -------------------------------------------------------------------------------- /doc/SELFHOST-TEST.md: -------------------------------------------------------------------------------- 1 | # Self-hosting test 2 | 3 | With the compiler-specific test no longer working properly, I think a good 4 | end-to-end self-hosting test is in order. 5 | 6 | It should load up the OS in the kernel, and run something like: 7 | 8 | cd /src 9 | ./build.sh 10 | cd /src/kernel 11 | ./build.sh 12 | kwr kernel.bin c400 13 | reboot 14 | echo "Great success" 15 | 16 | The test harness should make some effort to ensure: 17 | 18 | * a new line of the input is given every time the shell prompts for one 19 | * the VM actually reboots when instructed 20 | * the new kernel is running instead of the old one (maybe check the `kernel-name.sl` 21 | output?) 22 | * any text output containing "error:" counts as an output 23 | * (bonus) we should have `install.sh` under `/src` to install the system utilities, 24 | and check that they still work when self-hosted 25 | * (bonus) rebuild the system again, using the toolchain that was built from under 26 | SCAMP/os 27 | 28 | Probably just want a Perl script to fire up the emulator and manage input/output. 29 | Input maybe needs to be "drip-fed" because of the slowness of the serial port? 30 | -------------------------------------------------------------------------------- /doc/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/architecture.png -------------------------------------------------------------------------------- /doc/asciinema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/asciinema.png -------------------------------------------------------------------------------- /doc/card-cage.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/card-cage.jpeg -------------------------------------------------------------------------------- /doc/case.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/case.jpeg -------------------------------------------------------------------------------- /doc/computer.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/computer.jpeg -------------------------------------------------------------------------------- /doc/front-panels.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/front-panels.jpeg -------------------------------------------------------------------------------- /doc/hamurabi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/hamurabi.png -------------------------------------------------------------------------------- /doc/lib-file-template.tex: -------------------------------------------------------------------------------- 1 | \subsection{\tt{__FILENAME__}} 2 | 3 | __LIB_DESCR__ 4 | -------------------------------------------------------------------------------- /doc/lib-function-template.tex: -------------------------------------------------------------------------------- 1 | \subsubsection{\tt{__FUNCTION__}} 2 | \index{__FUNCTION__} 3 | 4 | \texttt{__FUNCTION_DEF__} 5 | 6 | __FUNCTION_DESCR__ 7 | -------------------------------------------------------------------------------- /doc/lib-ref-template.tex: -------------------------------------------------------------------------------- 1 | \documentclass[twocolumn]{article} 2 | \usepackage{imakeidx} 3 | \makeindex[intoc] 4 | \usepackage[hidelinks]{hyperref} 5 | \setcounter{tocdepth}{2} 6 | 7 | \title{SLANG Library Reference} 8 | \date{__DATE__} 9 | 10 | \begin{document} 11 | \maketitle 12 | \tableofcontents 13 | \newpage 14 | 15 | \section{Overview} 16 | 17 | This document is a reference of the functions available in the SLANG library modules. 18 | 19 | \section{Libraries} 20 | 21 | \input{library-functions.tex} 22 | 23 | \section{Blobs} 24 | 25 | \subsection{Overview} 26 | 27 | Most of the source code in a typical small program is library functions. To save 28 | wasting time recompiling the library functions every time the program is 29 | compiled, the library 30 | functions are built in ``blobs'' which can be directly included in the output binaries. 31 | 32 | Note that blobs are only used when compiling on SCAMP itself. When cross-compiling, all 33 | included library code is re-compiled for every program that uses it. 34 | 35 | \subsection{List of blobs} 36 | 37 | \subsubsection{Default} 38 | 39 | The default blob includes the following libraries: 40 | 41 | \input{blobs.tex} 42 | 43 | Other libraries will be re-compiled every time they are used. 44 | 45 | \subsubsection{\texttt{bigint}} 46 | 47 | Compiling with \texttt{-lbigint} will use the \texttt{bigint} blob, which 48 | contains the default libraries, plus \texttt{bigint.sl}. 49 | 50 | \subsubsection{\texttt{fixed}} 51 | 52 | Compiling with \texttt{-lfixed} will use the \texttt{fixed} blob, which 53 | contains the default libraries, plus \texttt{fixed.sl}. 54 | 55 | \subsubsection{\texttt{bigfix}} 56 | 57 | Compiling with \texttt{-lbigfix} will use the \texttt{bigfix} blob, which 58 | contains the default libraries, plus both \texttt{bigint.sl} and \texttt{fixed.sl}. 59 | 60 | \printindex 61 | 62 | \end{document} 63 | -------------------------------------------------------------------------------- /doc/lib/SLANG/Tex.pm: -------------------------------------------------------------------------------- 1 | package SLANG::Tex; 2 | 3 | our @ISA = qw(Exporter); 4 | our @EXPORT_OK = qw(texescape template slurp); 5 | 6 | sub texescape { 7 | my ($str) = @_; 8 | $str =~ s/([_&#^{}])/\\$1/g; 9 | return $str; 10 | } 11 | 12 | sub template { 13 | my ($tmpl, $fields) = @_; 14 | for my $f (keys %$fields) { 15 | $tmpl =~ s/$f/$fields->{$f}/g; 16 | } 17 | return $tmpl; 18 | } 19 | 20 | sub slurp { 21 | my ($name) = @_; 22 | open(my $fh, '<', $name) 23 | or die "can't read $name: $!\n"; 24 | my $c = join('', <$fh>); 25 | close $fh; 26 | return $c; 27 | } 28 | 29 | 1; 30 | -------------------------------------------------------------------------------- /doc/mk-blobs-tex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use FindBin; 7 | use lib "$FindBin::Bin/lib/"; 8 | 9 | use SLANG::Tex qw(texescape template slurp); 10 | 11 | my $src = slurp("../sys/make-lib"); 12 | 13 | die "can't understand ../sys/make-lib" 14 | unless $src =~ /LIBS="(.*)"/; 15 | 16 | my @libs = split / /, $1; 17 | print "\\texttt{$_}\n\n" for sort @libs; 18 | -------------------------------------------------------------------------------- /doc/mk-file-tex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use FindBin; 7 | use lib "$FindBin::Bin/lib/"; 8 | 9 | use SLANG::Tex qw(texescape slurp template); 10 | 11 | my $filename = shift or die "usage: mk-file-tex SRCFILE\n"; 12 | 13 | my $srcfile = slurp($filename); 14 | my $file_template = slurp('lib-file-template.tex'); 15 | my $func_template = slurp('lib-function-template.tex'); 16 | 17 | $filename =~ s!^.*/!!g; 18 | 19 | my $fields = { 20 | __FILENAME__ => $filename, 21 | __LIB_DESCR__ => texescape(libdescr($srcfile)), 22 | }; 23 | 24 | print template($file_template, $fields); 25 | 26 | for my $func (sort { $a->{name} cmp $b->{name} } funcs($srcfile)) { 27 | $fields->{__FUNCTION__} = texescape($func->{name}); 28 | $fields->{__FUNCTION_DEF__} = texescape($func->{def}); 29 | $fields->{__FUNCTION_DESCR__} = texescape($func->{descr}); 30 | print template($func_template, $fields); 31 | } 32 | 33 | sub libdescr { 34 | my ($src) = @_; 35 | my @lines = split /\n/, $src; 36 | my $descr = ''; 37 | while (my $l = shift @lines){ 38 | last unless $l =~ s/^\s*#\s*//; 39 | $descr .= $l . "\n\n"; 40 | } 41 | return $descr; 42 | } 43 | 44 | sub funcs { 45 | my ($src) = @_; 46 | my @lines = split /\n/, $src; 47 | my @funcs; 48 | my $comment = ''; 49 | for my $l (@lines) { 50 | if ($l =~ /^\s*(?:var)?\s*([a-zA-Z0-9_]+)\s*=\s*func/) { 51 | my $name = $1; 52 | $l =~ s/\).*/)/; 53 | $comment =~ s/^\s*//; 54 | push @funcs, { 55 | name => $name, 56 | def => $l, 57 | descr => $comment, 58 | } unless $name =~ /^_/; 59 | } elsif ($l =~ s/^#//) { 60 | $comment .= "\n\n" . $l; 61 | } else { 62 | $comment = ''; 63 | } 64 | } 65 | return @funcs; 66 | } 67 | -------------------------------------------------------------------------------- /doc/mk-lib-ref: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | date=`date +%Y-%m-%d` 7 | 8 | for f in ../sys/lib/*.sl 9 | do 10 | echo $f >&2 11 | ./mk-file-tex $f 12 | done > library-functions.tex 13 | 14 | ./mk-blobs-tex > blobs.tex 15 | 16 | cp lib-ref-template.tex slang-lib.tex 17 | sed -i "s/__DATE__/$date/g" slang-lib.tex 18 | pdflatex slang-lib.tex 19 | makeindex slang-lib 20 | pdflatex slang-lib.tex 21 | -------------------------------------------------------------------------------- /doc/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/doc/youtube.png -------------------------------------------------------------------------------- /emulator/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all test clean 2 | 3 | all: scamp 4 | 5 | scamp: scamp.c 6 | cc -o scamp $< -Wall -Wextra -DPROFILING 7 | 8 | test: scamp 9 | ./scamp -t 10 | 11 | clean: 12 | rm -f scamp 13 | -------------------------------------------------------------------------------- /front-panels/alu-panel.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/alu-panel.FCStd -------------------------------------------------------------------------------- /front-panels/bracket.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/bracket.FCStd -------------------------------------------------------------------------------- /front-panels/bracket.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/bracket.stl -------------------------------------------------------------------------------- /front-panels/cf-spacer.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/cf-spacer.FCStd -------------------------------------------------------------------------------- /front-panels/cf-spacer.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/cf-spacer.stl -------------------------------------------------------------------------------- /front-panels/instruction-panel.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/instruction-panel.FCStd -------------------------------------------------------------------------------- /front-panels/memory-panel.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/memory-panel.FCStd -------------------------------------------------------------------------------- /front-panels/memory-panel.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/memory-panel.stl -------------------------------------------------------------------------------- /front-panels/serial-connector.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/serial-connector.FCStd -------------------------------------------------------------------------------- /front-panels/serial-connector.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/serial-connector.stl -------------------------------------------------------------------------------- /front-panels/serial-panel.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/serial-panel.FCStd -------------------------------------------------------------------------------- /front-panels/storage-panel.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/storage-panel.FCStd -------------------------------------------------------------------------------- /front-panels/storage-panel.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/storage-panel.stl -------------------------------------------------------------------------------- /front-panels/test-holes.FCStd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/test-holes.FCStd -------------------------------------------------------------------------------- /front-panels/test-holes.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/front-panels/test-holes.stl -------------------------------------------------------------------------------- /fs/mkfs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # make a blank filesystem 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use FindBin; 9 | use lib "$FindBin::Bin/lib/"; 10 | 11 | use SCAMP::FS; 12 | 13 | my $fs = SCAMP::FS->new("/dev/zero"); 14 | 15 | # TODO: [nice] get these constants from SCAMP::FS instead of hardcoding 16 | my $BLKSZ = 512; 17 | my $SKIP_BLOCKS = 64; 18 | my $BITMAP_BLOCKS = 16; 19 | my $FS_SIZE = $BLKSZ * 65536; 20 | 21 | # skipped blocks (to store the kernel), bitmap blocks, and root block are all used 22 | $fs->setblkused($_, 1) for (0..80); 23 | 24 | # sanity check 25 | my $ok = 1; 26 | for my $i (0..80) { 27 | if ($fs->blkisfree($i)) { 28 | $ok = 0; 29 | print STDERR "block $i shouldn't be free\n"; 30 | } 31 | } 32 | for my $i (81 .. 65535) { 33 | if (!$fs->blkisfree($i)) { 34 | $ok = 0; 35 | print STDERR "block $i should be free\n"; 36 | } 37 | } 38 | exit(1) if !$ok; 39 | 40 | # root directory gets "." and ".." entries 41 | $fs->add_dirent(80, ".", 80); 42 | $fs->add_dirent(80, "..", 80); 43 | 44 | $fs->{file} = '/dev/stdout'; 45 | $fs->save(); 46 | -------------------------------------------------------------------------------- /fs/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./mkfs > test-disk < /dev/null 4 | ./fs test-disk < test.in > test.out.new 5 | cmp test.out test.out.new 6 | -------------------------------------------------------------------------------- /fs/test.in: -------------------------------------------------------------------------------- 1 | free 2 | ll 3 | mkdir foo 4 | ls 5 | cd foo 6 | put testfile1 7 | ll 8 | cat testfile1 9 | rm testfile1 10 | ll 11 | free 12 | cd / 13 | mkdir a 14 | mkdir b 15 | mkdir c 16 | mkdir d 17 | mkdir e 18 | mkdir f 19 | mkdir g 20 | mkdir h 21 | mkdir i 22 | mkdir j 23 | mkdir k 24 | mkdir l 25 | mkdir m 26 | mkdir n 27 | mkdir o 28 | mkdir p 29 | mkdir q 30 | mkdir r 31 | mkdir s 32 | mkdir t 33 | mkdir u 34 | mkdir v 35 | mkdir w 36 | mkdir x 37 | mkdir y 38 | mkdir z 39 | free 40 | ls 41 | ll foo 42 | rm foo/testfile1 43 | ll foo 44 | put testfile2 a/b/illegal-file 45 | free 46 | put testfile2 a/testfile2 47 | put testfile2 b/testfile2 48 | put testfile2 c/testfile2 49 | put testfile2 d/testfile2 50 | put testfile2 e/testfile2 51 | put testfile2 f/testfile2 52 | cat f/testfile2 53 | free 54 | -------------------------------------------------------------------------------- /fs/testfile1: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | SOURCES = *.sl 2 | 3 | .PHONY: all prof test clean 4 | 5 | all: os.disk 6 | 7 | prof: kernel.prof kernel.anhex 8 | ../emulator/profhtml -x kernel.anhex < kernel.prof > kernel.prof.html 9 | xdg-open kernel.prof.html 10 | 11 | kernel.prof: os.disk 12 | ../emulator/scamp -i os.disk -c -p kernel.prof 13 | 14 | os.disk: kernel.hex fs.in ../sys/*.bin motd os.disk.blank ../sys/lib.o 15 | cp os.disk.blank os.disk.tmp 16 | ../fs/fs os.disk.tmp < fs.in 17 | mv os.disk.tmp os.disk 18 | 19 | os.disk.blank: 20 | ../fs/mkfs > os.disk.blank 21 | 22 | kernel.hex: head.s kernel.opt.s foot.s 23 | cat head.s kernel.opt.s foot.s | ../asm/asm --verbose-file kernel.anhex.tmp > kernel.hex.tmp 24 | mv kernel.hex.tmp kernel.hex 25 | mv kernel.anhex.tmp kernel.anhex 26 | 27 | kernel.opt.s: kernel.s 28 | ../compiler/peepopt kernel.s | ../compiler/peepopt > kernel.opt.s.tmp 29 | mv kernel.opt.s.tmp kernel.opt.s 30 | 31 | kernel.s: $(SOURCES) 32 | ./mk-kernel-name > kernel-name.sl 33 | ../compiler/slangc kernel.sl > kernel.s.tmp 34 | mv kernel.s.tmp kernel.s 35 | 36 | clean: 37 | rm -f os.disk os.disk.blank kernel.prof kernel.hex kernel.anhex kernel.opt.s kernel.s *.tmp kernel.prof.html 38 | -------------------------------------------------------------------------------- /kernel/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # XXX: This is a script to build the kernel inside SCAMP/os, *not* for cross-compiling 4 | 5 | echo slangc... 6 | slangc < kernel.sl > /tmp/1.s 7 | echo cat... 8 | cat head.s /tmp/1.s foot.s > /tmp/2.s 9 | echo asm... 10 | asm < /tmp/2.s > kernel.bin 11 | rm /tmp/1.s /tmp/2.s 12 | -------------------------------------------------------------------------------- /kernel/foot.s: -------------------------------------------------------------------------------- 1 | 2 | _OSBASE: .word OSBASE 3 | 4 | # kernel stack 5 | #sym:kernel_stack 6 | .gap STACKSZ 7 | #nosym 8 | INITIAL_SP: .word 0 9 | 10 | .at 0xfee5 11 | # system call vectors 12 | _sys_getpid: .word 0 13 | _sys_savetpa: .word 0 14 | _sys_trap: .word 0 15 | _sys_blkwrite: .word 0 16 | _sys_blkread: .word 0 17 | _sys_random: .word 0 18 | _sys_serflags: .word 0 19 | _sys_cmdargs: .word 0 20 | _sys_osbase: .word 0 21 | _sys_copyfd: .word 0 22 | _sys_unlink: .word 0 23 | _sys_stat: .word 0 24 | _sys_readdir: .word 0 25 | _sys_opendir: .word 0 26 | _sys_mkdir: .word 0 27 | _sys_chdir: .word 0 28 | _sys_rename: .word 0 29 | _sys_sync: .word 0 30 | _sys_close: .word 0 31 | _sys_open: .word 0 32 | _sys_read: .word 0 33 | _sys_setbuf: .word 0 34 | _sys_write: .word 0 35 | _sys_getcwd: .word 0 36 | _sys_system: .word 0 37 | _sys_exec: .word 0 38 | _sys_exit: .word 0 39 | 40 | # sanity check 41 | .at 0xff00 42 | -------------------------------------------------------------------------------- /kernel/head.s: -------------------------------------------------------------------------------- 1 | .def OSBASE 0xd500 2 | .at OSBASE 3 | 4 | .def STACKSZ 64 5 | ld sp, INITIAL_SP 6 | -------------------------------------------------------------------------------- /kernel/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # install the latest disk image to the given device, preserving the contents of /home 4 | 5 | set -e 6 | set -o pipefail 7 | 8 | dev=$1 9 | 10 | if [ $# -eq 0 ]; then 11 | echo "usage: install DEVICE" 12 | exit 1 13 | fi 14 | 15 | echo "Copy image from $dev..." 16 | sudo dd if=$dev of=dev.disk bs=1k count=34k 17 | echo "Fix endianness..." 18 | ../util/swap-endian < dev.disk > dev2.disk 19 | echo "Make fresh disk image..." 20 | rm -f os.disk 21 | make os.disk 22 | echo "Copy contents of /home..." 23 | echo "grab dev2.disk /home" | ../fs/fs os.disk 24 | echo "Fix endianness..." 25 | ../util/swap-endian < os.disk > os2.disk 26 | echo "Write image to $dev..." 27 | sudo dd if=os2.disk of=$dev bs=1k 28 | -------------------------------------------------------------------------------- /kernel/kernel-name-selfhost.sl: -------------------------------------------------------------------------------- 1 | var KERNEL_NAME="self-hosted"; 2 | -------------------------------------------------------------------------------- /kernel/kernel.sl: -------------------------------------------------------------------------------- 1 | # Kernel for SCAMP by jes 2 | 3 | include "util.sl"; 4 | 5 | include "kernel-name.sl"; 6 | kputs("kernel "); 7 | kputs(KERNEL_NAME); 8 | kputs("\r\n"); 9 | 10 | kputs("data "); 11 | include "data.sl"; 12 | kputs("serial "); 13 | include "serial.sl"; 14 | kputs("blkdev "); 15 | include "blkdev.sl"; 16 | kputs("dir "); 17 | include "dir.sl"; 18 | kputs("fs "); 19 | include "fs.sl"; 20 | 21 | # Each of the included sys_*.sl modules initialises itself and writes the correct addresses 22 | # to the system call vectors that it is responsible for. 23 | kputs("sys_fs "); 24 | include "sys_fs.sl"; 25 | kputs("sys_dir "); 26 | include "sys_dir.sl"; 27 | kputs("sys_io "); 28 | include "sys_io.sl"; 29 | kputs("sys_proc "); 30 | include "sys_proc.sl"; 31 | kputs("sys_random "); 32 | include "sys_random.sl"; 33 | 34 | # initialise fdtable 35 | kputs("fd_init() "); 36 | fd_init(); 37 | 38 | # setup serial port fds 39 | kputs("ser_init()\r\n"); 40 | ser_init(); 41 | 42 | # We just need to start init to boot the system. 43 | kputs("init...\r\n"); 44 | sys_exec(["/bin/init"]); 45 | 46 | kpanic("return from init"); # is /bin/init missing? 47 | -------------------------------------------------------------------------------- /kernel/mk-kernel-name: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo -n "var KERNEL_NAME=\"" 4 | 5 | sha=`git rev-parse --short HEAD` 6 | if [ $sha ]; then 7 | # write the commit hash 8 | echo -n "$sha" 9 | 10 | # append a "+" if there are uncommitted changes 11 | if git status --porcelain=v1 | egrep -q '^ M'; then 12 | echo -n "+" 13 | fi 14 | echo -n " " 15 | else 16 | # write question marks in lieu of commit hash 17 | echo -n "??????? " 18 | fi 19 | 20 | # write the current date 21 | echo -n `date +"%Y-%m-%d %H:%M:%S"` 22 | 23 | echo "\";" 24 | -------------------------------------------------------------------------------- /kernel/motd: -------------------------------------------------------------------------------- 1 | ____ ____ _ __ __ ____ __ 2 | / ___| / ___| / \ | \/ | _ \ / /__ ___ 3 | \___ \| | / _ \ | |\/| | |_) / / _ \/ __| 4 | ___) | |___ / ___ \| | | | __/ / (_) \__ \ 5 | |____/ \____/_/ \_\_| |_|_| /_/ \___/|___/ 6 | 7 | -------------------------------------------------------------------------------- /kernel/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | make os.disk 4 | ../emulator/scamp -i os.disk $@ 5 | -------------------------------------------------------------------------------- /kernel/sys.sl: -------------------------------------------------------------------------------- 1 | # system call declarations 2 | 3 | extern sys_getpid; 4 | extern sys_savetpa; 5 | extern sys_trap; 6 | extern sys_blkwrite; 7 | extern sys_blkread; 8 | extern sys_random; 9 | extern sys_serflags; 10 | extern sys_cmdargs; 11 | extern sys_osbase; 12 | extern sys_copyfd; 13 | extern sys_unlink; 14 | extern sys_stat; 15 | extern sys_readdir; 16 | extern sys_opendir; 17 | extern sys_mkdir; 18 | extern sys_chdir; 19 | extern sys_rename; 20 | extern sys_sync; 21 | extern sys_close; 22 | extern sys_open; 23 | extern sys_read; 24 | extern sys_setbuf; 25 | extern sys_write; 26 | extern sys_getcwd; 27 | extern sys_system; 28 | extern sys_exec; 29 | extern sys_exit; 30 | -------------------------------------------------------------------------------- /kernel/sys_random.sl: -------------------------------------------------------------------------------- 1 | # RNG 2 | 3 | var shr9 = asm { 4 | pop x 5 | ld r0, x 6 | ld r1, r254 # stash return address 7 | zero r254 8 | tbsz r0, 0x8000 9 | sb r254, 0x40 10 | tbsz r0, 0x4000 11 | sb r254, 0x20 12 | tbsz r0, 0x2000 13 | sb r254, 0x10 14 | tbsz r0, 0x1000 15 | sb r254, 0x08 16 | tbsz r0, 0x0800 17 | sb r254, 0x04 18 | tbsz r0, 0x0400 19 | sb r254, 0x02 20 | tbsz r0, 0x0200 21 | sb r254, 0x01 22 | ld r0, r254 23 | jmp r1 # return 24 | }; 25 | 26 | sys_random = func() { 27 | # XXX: output 0 after 0x1234 to get up to full 2^16 period 28 | if (rngstate == 0x1234) return 0; 29 | if (rngstate == 0) rngstate = 0x1234; 30 | 31 | rngstate = rngstate ^ shl(rngstate, 13); 32 | rngstate = rngstate ^ shr9(rngstate); 33 | rngstate = rngstate ^ shl(rngstate, 7); 34 | 35 | return rngstate & 0x7fff; 36 | }; 37 | -------------------------------------------------------------------------------- /kicad/alu/alu.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/kicad/alu/alu.zip -------------------------------------------------------------------------------- /kicad/alu/gerber/alu-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-02-11T10:51:17+00:00* 3 | G04 #@! TF.ProjectId,alu,616c752e-6b69-4636-9164-5f7063625858,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Profile,NP* 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-02-11 10:51:17* 9 | %MOMM*% 10 | %LPD*% 11 | G04 APERTURE LIST* 12 | %ADD10C,0.100000*% 13 | G04 APERTURE END LIST* 14 | D10* 15 | X266700000Y-41910000D02* 16 | X266700000Y-144780000D01* 17 | X29210000Y-41910000D02* 18 | X266700000Y-41910000D01* 19 | X29210000Y-144780000D02* 20 | X29210000Y-41910000D01* 21 | X266700000Y-144780000D02* 22 | X29210000Y-144780000D01* 23 | M02* 24 | -------------------------------------------------------------------------------- /kicad/alu/gerber/alu-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 5.1.5+dfsg1-2build2} date Thu 11 Feb 2021 10:51:25 GMT 3 | ; FORMAT={3:3/ absolute / metric / suppress leading zeros} 4 | ; #@! TF.CreationDate,2021-02-11T10:51:25+00:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,5.1.5+dfsg1-2build2 6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH 7 | FMAT,2 8 | METRIC,TZ 9 | T1C3.200 10 | % 11 | G90 12 | G05 13 | T1 14 | X34290Y-137160 15 | X34290Y-49530 16 | X261620Y-137160 17 | X261620Y-49530 18 | T0 19 | M30 20 | -------------------------------------------------------------------------------- /kicad/backplane/gerber.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/kicad/backplane/gerber.zip -------------------------------------------------------------------------------- /kicad/backplane/gerber/backplane-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-02-22T20:55:43+00:00* 3 | G04 #@! TF.ProjectId,backplane,6261636b-706c-4616-9e65-2e6b69636164,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Profile,NP* 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-02-22 20:55:43* 9 | %MOMM*% 10 | %LPD*% 11 | G04 APERTURE LIST* 12 | %ADD10C,0.100000*% 13 | G04 APERTURE END LIST* 14 | D10* 15 | X356000000Y-69600000D02* 16 | X356000000Y-172400000D01* 17 | X61000000Y-69600000D02* 18 | X356000000Y-69600000D01* 19 | X61000000Y-172400000D02* 20 | X61000000Y-69600000D01* 21 | X356000000Y-172400000D02* 22 | X61000000Y-172400000D01* 23 | M02* 24 | -------------------------------------------------------------------------------- /kicad/backplane/gerber/backplane-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 5.1.5+dfsg1-2build2} date Mon 22 Feb 2021 20:55:48 GMT 3 | ; FORMAT={-:-/ absolute / metric / decimal} 4 | ; #@! TF.CreationDate,2021-02-22T20:55:48+00:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,5.1.5+dfsg1-2build2 6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH 7 | FMAT,2 8 | METRIC 9 | T1C3.200 10 | % 11 | G90 12 | G05 13 | T1 14 | X72.25Y-75.0 15 | X112.0Y-167.0 16 | X112.0Y-75.0 17 | X192.0Y-167.0 18 | X312.0Y-75.0 19 | X232.0Y-167.0 20 | X232.0Y-75.0 21 | X312.0Y-167.0 22 | X352.0Y-167.0 23 | X352.0Y-75.0 24 | X272.0Y-167.0 25 | X72.0Y-167.0 26 | X272.0Y-75.0 27 | X152.0Y-75.0 28 | X192.0Y-75.0 29 | X152.0Y-167.0 30 | T0 31 | M30 32 | -------------------------------------------------------------------------------- /kicad/eeprom-burner/eeprom-burner.sch: -------------------------------------------------------------------------------- 1 | EESchema Schematic File Version 2 2 | EELAYER 25 0 3 | EELAYER END 4 | $EndSCHEMATC 5 | -------------------------------------------------------------------------------- /kicad/eeprom-burner/gerber/eeprom-burner-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-02-11T13:07:57+00:00* 3 | G04 #@! TF.ProjectId,eeprom-burner,65657072-6f6d-42d6-9275-726e65722e6b,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Profile,NP* 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-02-11 13:07:57* 9 | %MOMM*% 10 | %LPD*% 11 | G04 APERTURE LIST* 12 | %ADD10C,0.050000*% 13 | G04 APERTURE END LIST* 14 | D10* 15 | X117856000Y-142748000D02* 16 | X127000000Y-133604000D01* 17 | X84328000Y-142748000D02* 18 | X117856000Y-142748000D01* 19 | X76200000Y-134620000D02* 20 | X84328000Y-142748000D01* 21 | X76200000Y-78740000D02* 22 | X76200000Y-134620000D01* 23 | X129540000Y-94234000D02* 24 | X127000000Y-91694000D01* 25 | X125476000Y-78740000D02* 26 | X127000000Y-80264000D01* 27 | X127000000Y-80264000D02* 28 | X127000000Y-91694000D01* 29 | X127000000Y-129540000D02* 30 | X127000000Y-133604000D01* 31 | X129540000Y-127000000D02* 32 | X127000000Y-129540000D01* 33 | X129540000Y-94234000D02* 34 | X129540000Y-127000000D01* 35 | X76200000Y-78740000D02* 36 | X125476000Y-78740000D01* 37 | M02* 38 | -------------------------------------------------------------------------------- /kicad/eeprom-burner/gerber/eeprom-burner.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 5.1.5+dfsg1-2build2} date Thu 11 Feb 2021 13:09:32 GMT 3 | ; FORMAT={-:-/ absolute / metric / decimal} 4 | ; #@! TF.CreationDate,2021-02-11T13:09:32+00:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,5.1.5+dfsg1-2build2 6 | FMAT,2 7 | METRIC 8 | T1C0.800 9 | T2C1.000 10 | % 11 | G90 12 | G05 13 | T1 14 | X88.9Y-93.98 15 | X88.9Y-109.22 16 | X91.44Y-93.98 17 | X91.44Y-109.22 18 | X93.98Y-93.98 19 | X93.98Y-109.22 20 | X96.52Y-93.98 21 | X96.52Y-109.22 22 | X99.06Y-93.98 23 | X99.06Y-109.22 24 | X101.6Y-93.98 25 | X101.6Y-109.22 26 | X104.14Y-93.98 27 | X104.14Y-109.22 28 | X106.68Y-93.98 29 | X106.68Y-109.22 30 | X109.22Y-93.98 31 | X109.22Y-109.22 32 | X111.76Y-93.98 33 | X111.76Y-109.22 34 | X114.3Y-93.98 35 | X114.3Y-109.22 36 | X116.84Y-93.98 37 | X116.84Y-109.22 38 | X96.52Y-119.38 39 | X104.14Y-119.38 40 | T2 41 | X111.76Y-129.54 42 | X114.3Y-129.54 43 | X116.84Y-129.54 44 | X119.38Y-129.54 45 | X121.92Y-129.54 46 | X124.46Y-129.54 47 | X106.68Y-81.28 48 | X109.22Y-81.28 49 | X111.76Y-81.28 50 | X114.3Y-81.28 51 | X116.84Y-81.28 52 | X119.38Y-81.28 53 | X121.92Y-81.28 54 | X124.46Y-81.28 55 | X79.756Y-81.28 56 | X82.296Y-81.28 57 | X84.836Y-81.28 58 | X87.376Y-81.28 59 | X89.916Y-81.28 60 | X92.456Y-81.28 61 | X94.996Y-81.28 62 | X97.536Y-81.28 63 | X100.076Y-81.28 64 | X102.616Y-81.28 65 | X88.9Y-129.54 66 | X91.44Y-129.54 67 | X93.98Y-129.54 68 | X96.52Y-129.54 69 | X99.06Y-129.54 70 | X101.6Y-129.54 71 | X104.14Y-129.54 72 | X106.68Y-129.54 73 | X101.6Y-124.46 74 | X104.14Y-124.46 75 | X96.52Y-124.46 76 | X116.84Y-119.38 77 | T0 78 | M30 79 | -------------------------------------------------------------------------------- /kicad/eeprom-burner/gerber/mk-gcode: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "B_Cu:" 4 | gbr2ngc --metric --radius 0.1 --zsafe 5 --feed 50 --seek 400 eeprom-burner-B_Cu.gbr > B_Cu.gcode.tmp 5 | echo "-75 -75" | gcodetile --show-bounds --invert-y B_Cu.gcode.tmp > B_Cu.gcode 6 | rm B_Cu.gcode.tmp 7 | 8 | echo "Edge_Cuts:" 9 | gbr2ngc --metric --radius 2 --zsafe 5 --zcut -2 --feed 50 --seek 400 eeprom-burner-Edge_Cuts.gbr > Edge_Cuts.gcode.tmp 10 | # The sed command strips the second path so that we don't cut out the *inside* of the edge cuts 11 | echo "-75 75" | gcodetile --show-bounds Edge_Cuts.gcode.tmp | sed '/^( path 1/,$ d' > Edge_Cuts.gcode 12 | rm Edge_Cuts.gcode.tmp 13 | 14 | echo "F_SilkS:" 15 | gbr2ngc --metric --zsafe 5 --feed 50 --seek 400 eeprom-burner-F_SilkS.gbr > F_SilkS.gcode.tmp 16 | echo "-75 75" | gcodetile --show-bounds F_SilkS.gcode.tmp > F_SilkS.gcode 17 | rm F_SilkS.gcode.tmp 18 | 19 | echo "Drill:" 20 | drl2gcode --safe-height 5 eeprom-burner.drl 21 | echo "-75 -75" | gcodetile --show-bounds --invert-y <(cat eeprom-burner_T*.gcode) > Drill.gcode 22 | rm eeprom-burner_T*.gcode 23 | -------------------------------------------------------------------------------- /kicad/instruction/gerber/instruction-B_SilkS.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-02-11T11:00:20+00:00* 3 | G04 #@! TF.ProjectId,instruction,696e7374-7275-4637-9469-6f6e2e6b6963,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Legend,Bot* 6 | G04 #@! TF.FilePolarity,Positive* 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-02-11 11:00:20* 10 | %MOMM*% 11 | %LPD*% 12 | G04 APERTURE LIST* 13 | G04 APERTURE END LIST* 14 | M02* 15 | -------------------------------------------------------------------------------- /kicad/instruction/gerber/instruction-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-02-11T11:00:20+00:00* 3 | G04 #@! TF.ProjectId,instruction,696e7374-7275-4637-9469-6f6e2e6b6963,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Profile,NP* 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-02-11 11:00:20* 9 | %MOMM*% 10 | %LPD*% 11 | G04 APERTURE LIST* 12 | %ADD10C,0.100000*% 13 | G04 APERTURE END LIST* 14 | D10* 15 | X262890000Y-38100000D02* 16 | X262890000Y-140970000D01* 17 | X25400000Y-38100000D02* 18 | X262890000Y-38100000D01* 19 | X25400000Y-140970000D02* 20 | X25400000Y-38100000D01* 21 | X262890000Y-140970000D02* 22 | X25400000Y-140970000D01* 23 | M02* 24 | -------------------------------------------------------------------------------- /kicad/instruction/gerber/instruction-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 5.1.5+dfsg1-2build2} date Thu 11 Feb 2021 11:00:22 GMT 3 | ; FORMAT={3:3/ absolute / metric / suppress leading zeros} 4 | ; #@! TF.CreationDate,2021-02-11T11:00:22+00:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,5.1.5+dfsg1-2build2 6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH 7 | FMAT,2 8 | METRIC,TZ 9 | T1C3.200 10 | % 11 | G90 12 | G05 13 | T1 14 | X257810Y-133350 15 | X257810Y-45720 16 | T0 17 | M30 18 | -------------------------------------------------------------------------------- /kicad/instruction/instruction.pro: -------------------------------------------------------------------------------- 1 | update=Mon 08 Feb 2021 16:46:43 GMT 2 | version=1 3 | last_client=kicad 4 | [general] 5 | version=1 6 | RootSch= 7 | BoardNm= 8 | [pcbnew] 9 | version=1 10 | LastNetListRead= 11 | UseCmpFile=1 12 | PadDrill=0.600000000000 13 | PadDrillOvalY=0.600000000000 14 | PadSizeH=1.500000000000 15 | PadSizeV=1.500000000000 16 | PcbTextSizeV=1.500000000000 17 | PcbTextSizeH=1.500000000000 18 | PcbTextThickness=0.300000000000 19 | ModuleTextSizeV=1.000000000000 20 | ModuleTextSizeH=1.000000000000 21 | ModuleTextSizeThickness=0.150000000000 22 | SolderMaskClearance=0.000000000000 23 | SolderMaskMinWidth=0.000000000000 24 | DrawSegmentWidth=0.200000000000 25 | BoardOutlineThickness=0.100000000000 26 | ModuleOutlineThickness=0.150000000000 27 | [cvpcb] 28 | version=1 29 | NetIExt=net 30 | [eeschema] 31 | version=1 32 | LibDir= 33 | [eeschema/libraries] 34 | [schematic_editor] 35 | version=1 36 | PageLayoutDescrFile= 37 | PlotDirectoryName= 38 | SubpartIdSeparator=0 39 | SubpartFirstId=65 40 | NetFmtName=Pcbnew 41 | SpiceAjustPassiveValues=0 42 | LabSize=50 43 | ERC_TestSimilarLabels=1 44 | -------------------------------------------------------------------------------- /kicad/instruction/instruction.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/kicad/instruction/instruction.zip -------------------------------------------------------------------------------- /kicad/memory/gerber/memory-B_SilkS.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-02-11T10:57:50+00:00* 3 | G04 #@! TF.ProjectId,memory,6d656d6f-7279-42e6-9b69-6361645f7063,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Legend,Bot* 6 | G04 #@! TF.FilePolarity,Positive* 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-02-11 10:57:50* 10 | %MOMM*% 11 | %LPD*% 12 | G04 APERTURE LIST* 13 | G04 APERTURE END LIST* 14 | M02* 15 | -------------------------------------------------------------------------------- /kicad/memory/gerber/memory-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-02-11T10:57:50+00:00* 3 | G04 #@! TF.ProjectId,memory,6d656d6f-7279-42e6-9b69-6361645f7063,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Profile,NP* 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-02-11 10:57:50* 9 | %MOMM*% 10 | %LPD*% 11 | G04 APERTURE LIST* 12 | %ADD10C,0.100000*% 13 | G04 APERTURE END LIST* 14 | D10* 15 | X261620000Y-40640000D02* 16 | X261620000Y-143510000D01* 17 | X24130000Y-40640000D02* 18 | X261620000Y-40640000D01* 19 | X24130000Y-143510000D02* 20 | X24130000Y-40640000D01* 21 | X261620000Y-143510000D02* 22 | X24130000Y-143510000D01* 23 | M02* 24 | -------------------------------------------------------------------------------- /kicad/memory/gerber/memory-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 5.1.5+dfsg1-2build2} date Thu 11 Feb 2021 10:57:56 GMT 3 | ; FORMAT={3:3/ absolute / metric / suppress leading zeros} 4 | ; #@! TF.CreationDate,2021-02-11T10:57:56+00:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,5.1.5+dfsg1-2build2 6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH 7 | FMAT,2 8 | METRIC,TZ 9 | T1C3.200 10 | % 11 | G90 12 | G05 13 | T1 14 | X256540Y-135890 15 | X256540Y-48260 16 | T0 17 | M30 18 | -------------------------------------------------------------------------------- /kicad/memory/memory.pro: -------------------------------------------------------------------------------- 1 | update=Sun 07 Feb 2021 17:31:36 GMT 2 | version=1 3 | last_client=kicad 4 | [general] 5 | version=1 6 | RootSch= 7 | BoardNm= 8 | [pcbnew] 9 | version=1 10 | LastNetListRead= 11 | UseCmpFile=1 12 | PadDrill=0.600000000000 13 | PadDrillOvalY=0.600000000000 14 | PadSizeH=1.500000000000 15 | PadSizeV=1.500000000000 16 | PcbTextSizeV=1.500000000000 17 | PcbTextSizeH=1.500000000000 18 | PcbTextThickness=0.300000000000 19 | ModuleTextSizeV=1.000000000000 20 | ModuleTextSizeH=1.000000000000 21 | ModuleTextSizeThickness=0.150000000000 22 | SolderMaskClearance=0.000000000000 23 | SolderMaskMinWidth=0.000000000000 24 | DrawSegmentWidth=0.200000000000 25 | BoardOutlineThickness=0.100000000000 26 | ModuleOutlineThickness=0.150000000000 27 | [cvpcb] 28 | version=1 29 | NetIExt=net 30 | [eeschema] 31 | version=1 32 | LibDir= 33 | [eeschema/libraries] 34 | [schematic_editor] 35 | version=1 36 | PageLayoutDescrFile= 37 | PlotDirectoryName= 38 | SubpartIdSeparator=0 39 | SubpartFirstId=65 40 | NetFmtName=Pcbnew 41 | SpiceAjustPassiveValues=0 42 | LabSize=50 43 | ERC_TestSimilarLabels=1 44 | -------------------------------------------------------------------------------- /kicad/memory/memory.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/kicad/memory/memory.zip -------------------------------------------------------------------------------- /kicad/scamp.dcm: -------------------------------------------------------------------------------- 1 | EESchema-DOCLIB Version 2.0 2 | # 3 | $CMP 28C16 4 | D Paged Parallel EEPROM 16Kb (2K x 8), DIP-24/SOIC-24 5 | K Parallel EEPROM 16Kb 6 | F http://ww1.microchip.com/downloads/en/DeviceDoc/doc0006.pdf 7 | $ENDCMP 8 | # 9 | $CMP W24512A 10 | D 64K x 8 High Speed CMOS Static RAM 11 | K Static RAM SRAM 64KB 12 | F http://ww1.microchip.com/downloads/en/DeviceDoc/doc0006.pdf 13 | $ENDCMP 14 | # 15 | #End Doc Library 16 | -------------------------------------------------------------------------------- /kicad/serial/gerber.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/kicad/serial/gerber.zip -------------------------------------------------------------------------------- /kicad/serial/gerber/serial-B_SilkS.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-04-04T16:47:07+01:00* 3 | G04 #@! TF.ProjectId,serial,73657269-616c-42e6-9b69-6361645f7063,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Legend,Bot* 6 | G04 #@! TF.FilePolarity,Positive* 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-04-04 16:47:07* 10 | %MOMM*% 11 | %LPD*% 12 | G04 APERTURE LIST* 13 | G04 APERTURE END LIST* 14 | M02* 15 | -------------------------------------------------------------------------------- /kicad/serial/gerber/serial-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.5+dfsg1-2build2* 2 | G04 #@! TF.CreationDate,2021-04-04T16:47:07+01:00* 3 | G04 #@! TF.ProjectId,serial,73657269-616c-42e6-9b69-6361645f7063,rev?* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Profile,NP* 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW 5.1.5+dfsg1-2build2) date 2021-04-04 16:47:07* 9 | %MOMM*% 10 | %LPD*% 11 | G04 APERTURE LIST* 12 | %ADD10C,0.100000*% 13 | G04 APERTURE END LIST* 14 | D10* 15 | X267462000Y-43942000D02* 16 | X267462000Y-146812000D01* 17 | X29972000Y-43942000D02* 18 | X267462000Y-43942000D01* 19 | X29972000Y-146812000D02* 20 | X29972000Y-43942000D01* 21 | X267462000Y-146812000D02* 22 | X29972000Y-146812000D01* 23 | M02* 24 | -------------------------------------------------------------------------------- /kicad/serial/gerber/serial-NPTH.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad 5.1.5+dfsg1-2build2} date Sun 04 Apr 2021 16:47:09 BST 3 | ; FORMAT={-:-/ absolute / metric / decimal} 4 | ; #@! TF.CreationDate,2021-04-04T16:47:09+01:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,5.1.5+dfsg1-2build2 6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH 7 | FMAT,2 8 | METRIC 9 | T1C3.200 10 | % 11 | G90 12 | G05 13 | T1 14 | X262.382Y-139.192 15 | X262.382Y-51.562 16 | T0 17 | M30 18 | -------------------------------------------------------------------------------- /pdf/74125.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/74125.pdf -------------------------------------------------------------------------------- /pdf/74138.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/74138.pdf -------------------------------------------------------------------------------- /pdf/74161.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/74161.pdf -------------------------------------------------------------------------------- /pdf/74273.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/74273.pdf -------------------------------------------------------------------------------- /pdf/7474.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/7474.pdf -------------------------------------------------------------------------------- /pdf/74hc245.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/74hc245.pdf -------------------------------------------------------------------------------- /pdf/8250.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/8250.jpeg -------------------------------------------------------------------------------- /pdf/8250.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/8250.pdf -------------------------------------------------------------------------------- /pdf/at28c16.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/at28c16.pdf -------------------------------------------------------------------------------- /pdf/cd4504.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/cd4504.pdf -------------------------------------------------------------------------------- /pdf/ip82c50a-5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/ip82c50a-5.pdf -------------------------------------------------------------------------------- /pdf/lec12_sd_card.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/lec12_sd_card.pdf -------------------------------------------------------------------------------- /pdf/led-housing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/led-housing.pdf -------------------------------------------------------------------------------- /pdf/lisp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/lisp.pdf -------------------------------------------------------------------------------- /pdf/sandisk-compactflash.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/sandisk-compactflash.pdf -------------------------------------------------------------------------------- /pdf/ti-compact-flash-spra803.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/ti-compact-flash-spra803.pdf -------------------------------------------------------------------------------- /pdf/w24512a.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jes/scamp-cpu/11710ad5fe76fee11a6d3748f511093d5cf4f551/pdf/w24512a.pdf -------------------------------------------------------------------------------- /sys/Makefile: -------------------------------------------------------------------------------- 1 | LIBS = lib/*.sl 2 | BINS = cat.bin init.bin ls.bin mkdir.bin sh.bin pwd.bin echo.bin stat.bin rm.bin slangc.bin asm.bin hd.bin grep.bin more.bin wc.bin head.bin mv.bin slc.bin kilo.bin reboot.bin diskid.bin baud.bin cp.bin dc.bin keys.bin isprime.bin hamurabi.bin opts.bin mandel.bin sort.bin mandelfix.bin fc.bin snake.bin reset.bin true.bin while.bin rx.bin sx.bin du.bin aoc.bin df.bin kwr.bin ser.bin rsh.bin ps.bin rude.bin fsck.bin lisp.bin slangi.bin 3 | 4 | .PHONY: all test clean 5 | 6 | all: $(BINS) lib.o rude-globals.sl 7 | 8 | .PRECIOUS: %.bin 9 | %.bin: %.hex lib.o 10 | ../util/hex2bin $*.hex > $*.bin.tmp 11 | mv $*.bin.tmp $*.bin 12 | 13 | %.hex: lib/head.s %.opt.s lib/foot.s 14 | cat lib/head.s $*.opt.s lib/foot.s | ../asm/asm --verbose-file $*.anhex.tmp > $*.hex.tmp 15 | mv $*.hex.tmp $*.hex 16 | mv $*.anhex.tmp $*.anhex 17 | 18 | %.opt.s: %.s 19 | ../compiler/peepopt $*.s | ../compiler/peepopt > $*.opt.s.tmp 20 | mv $*.opt.s.tmp $*.opt.s 21 | 22 | %.s: %.sl $(LIBS) 23 | ../compiler/slangc $*.sl > $*.s.tmp 24 | mv $*.s.tmp $*.s 25 | 26 | lib.list: make-lib 27 | ./make-lib 28 | 29 | lib.o: $(LIBS) make-lib 30 | ./make-lib 31 | 32 | rude-globals.sl: lib.list mk-rude-globals 33 | ./mk-rude-globals > rude-globals.sl 34 | 35 | clean: 36 | rm -f *.bin *.hex *.anhex *.s *.tmp lib*.o lib*.s.build lib*.h rude-globals.sl lib*.list lib*.const 37 | -------------------------------------------------------------------------------- /sys/baud.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | include "stdlib.sl"; 3 | 4 | var setclkdiv = asm { 5 | .def SERIALREG0 136 6 | .def SERIALREG1 137 7 | .def SERIALREG3 139 8 | 9 | pop x 10 | ld r0, x # r0 = clkdiv 11 | 12 | # select divisor latches: 13 | # write 0x80 to line control register 14 | ld x, 0x80 15 | out SERIALREG3, x 16 | 17 | # set high byte of divisor latch = 0 18 | ld x, 0 19 | out SERIALREG1, x 20 | # set low byte of divisor latch = SERIALCLKDIV 21 | ld x, r0 22 | out SERIALREG0, x 23 | 24 | # select data register instead of divisor latches, and set 8-bit words, no parity, 1 stop: 25 | # write 0x03 to line control register (addr 3) 26 | ld x, 0x03 27 | out SERIALREG3, x 28 | 29 | ret 30 | }; 31 | 32 | var args = cmdargs()+1; 33 | 34 | if (!*args) { 35 | fprintf(2, "usage: baud N\nexample: baud 9600\n", 0); 36 | exit(1); 37 | }; 38 | 39 | var baud_rate = atoi(*args); 40 | 41 | # XXX: should be 115200/baud_rate but 115200 is too large for 16-bit 42 | var clkdiv = div(57600, baud_rate); 43 | clkdiv = clkdiv + clkdiv; 44 | 45 | setclkdiv(clkdiv); 46 | -------------------------------------------------------------------------------- /sys/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # XXX: This is a script to build inside SCAMP/os, *not* for cross-compiling 4 | 5 | slc < aoc.sl > aoc 6 | slc < asm.sl > asm 7 | slc < baud.sl > baud 8 | slc < cat.sl > cat 9 | slc < cp.sl > cp 10 | slc -lbigint < dc.sl > dc 11 | slc -lfixed < df.sl > df 12 | slc < slc.sl < diskid.sl > diskid 13 | slc -lbigint < du.sl > du 14 | slc < echo.sl > echo 15 | slc -lfixed < fc.sl > fc 16 | slc < grep.sl > grep 17 | slc < hamurabi.sl > hamurabi 18 | slc < hd.sl > hd 19 | slc < head.sl > head 20 | slc < init.sl > init 21 | slc -lbigint < isprime.sl > isprime 22 | slc < keys.sl > keys 23 | slc < kilo.sl > kilo 24 | slc < kwr.sl > kwr 25 | slc < ls.sl > ls 26 | slc -lbigint < mandel.sl > mandel 27 | slc -lfixed < mandelfix.sl > mandelfix 28 | slc < mkdir.sl > mkdir 29 | slc < more.sl > more 30 | slc < mv.sl > mv 31 | slc < opts.sl > opts 32 | slc < pwd.sl > pwd 33 | slc < reboot.sl > reboot 34 | slc < reset.sl > reset 35 | slc < rm.sl > rm 36 | slc < rx.sl > rx 37 | slc < sh.sl > sh 38 | slc < slangc.sl > slangc 39 | slc < slc.sl > slc 40 | slc < snake.sl > snake 41 | slc -lbigint < sort.sl > sort 42 | slc < stat.sl > stat 43 | slc < sx.sl > sx 44 | slc < true.sl > true 45 | slc -lbigint < wc.sl > wc 46 | slc < while.sl > while 47 | -------------------------------------------------------------------------------- /sys/cat.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | include "sys.sl"; 3 | include "malloc.sl"; 4 | include "string.sl"; 5 | 6 | var bufsz = 256; 7 | var buf = malloc(bufsz); 8 | 9 | # TODO: ability to cat a file named "-" 10 | 11 | var cat = func(name) { 12 | var fd; 13 | if (strcmp(name, "-") == 0) { 14 | fd = 0; 15 | } else { 16 | fd = open(name, O_READ); 17 | if (fd < 0) { 18 | fprintf(2, "cat: open %s: %s\n", [name, strerror(fd)]); 19 | return 0; 20 | }; 21 | }; 22 | 23 | var n; 24 | while (1) { 25 | n = read(fd, buf, bufsz); 26 | if (n == 0) break; 27 | if (n < 0) { 28 | fprintf(2, "cat: read %d: %s\n", [fd, strerror(n)]); 29 | break; 30 | }; 31 | write(1, buf, n); 32 | }; 33 | close(fd); 34 | }; 35 | 36 | var args = cmdargs()+1; 37 | 38 | if (!*args) { 39 | cat("-"); 40 | exit(0); 41 | }; 42 | 43 | while (*args) { 44 | cat(*args); 45 | args++; 46 | }; 47 | -------------------------------------------------------------------------------- /sys/df.sl: -------------------------------------------------------------------------------- 1 | # df - show overall disk usage 2 | 3 | include "stdio.sl"; 4 | include "sys.sl"; 5 | include "fixed.sl"; 6 | 7 | var countbits = func(p, len) { 8 | var n = 0; 9 | var i = 0; 10 | while (i < len) { 11 | n = n + popcnt(p[i]); 12 | i++; 13 | }; 14 | return n; 15 | }; 16 | 17 | # work out how many blocks are used by counting bits set to 1 in the free-space bitmap 18 | var b = 64; 19 | var p; 20 | var usedblocks = 0; 21 | while (b < 80) { 22 | p = blkread(b); 23 | usedblocks = usedblocks + countbits(p, 256); 24 | b++; 25 | }; 26 | 27 | printf("%u blocks used of 65536\n", [usedblocks]); 28 | 29 | var usedb = mul(usedblocks, 512); 30 | var usedkb = div(usedblocks, 2); 31 | var usedmb = div(usedblocks, 2048); 32 | if (usedkb < 2) printf("%u bytes used of 32 Mbytes\n", [usedb]) 33 | else if (usedmb < 2) printf("%u Kbytes used of 32 Mbytes\n", [usedkb]) 34 | else printf("%u Mbytes used of 32 MB\n", [usedmb]); 35 | 36 | fixinit(8); 37 | var usedpct = shr(usedblocks,8); 38 | printf("%f%% used\n", [mul(usedpct,100)]); 39 | -------------------------------------------------------------------------------- /sys/echo.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | include "sys.sl"; 3 | 4 | var args = cmdargs()+1; 5 | 6 | while (*args) { 7 | puts(*args); 8 | args++; 9 | if (*args) putchar(' '); 10 | }; 11 | putchar('\n'); 12 | -------------------------------------------------------------------------------- /sys/grep.sl: -------------------------------------------------------------------------------- 1 | include "bufio.sl"; 2 | include "stdio.sl"; 3 | include "string.sl"; 4 | include "sys.sl"; 5 | 6 | var bufsz = 16384; 7 | var buf = malloc(bufsz); 8 | 9 | setbuf(1, malloc(257)); 10 | 11 | var showfilename = 0; 12 | var filename = ""; 13 | 14 | # return 1 if haystack contains needle, 0 otherwise 15 | # TODO: [perf] we can do better than strncmp() here, e.g. Aho-Corasick? 16 | var match = func(haystack, needle) { 17 | var i = 0; 18 | var len = strlen(needle); 19 | 20 | while (haystack[i]) { 21 | if (strncmp(haystack+i,needle,len) == 0) return 1; 22 | i++; 23 | }; 24 | 25 | return 0; 26 | }; 27 | 28 | var bgrep = func(term, in) { 29 | while (bgets(in,buf,bufsz)) 30 | if (match(buf, term)) { 31 | if (showfilename) { 32 | puts(filename); 33 | putchar(':'); 34 | }; 35 | puts(buf); 36 | }; 37 | }; 38 | 39 | var grep = func(term, name) { 40 | var in = bopen(name, O_READ); 41 | var fd; 42 | if (!in) { 43 | fd = open(name, O_READ); 44 | fprintf(2, "grep: %s: %s\n", [name, strerror(fd)]); 45 | return 0; 46 | }; 47 | filename = name; 48 | bgrep(term, in); 49 | bclose(in); 50 | }; 51 | 52 | var args = cmdargs()+1; 53 | 54 | if (!*args) { 55 | fputs(2,"usage: grep SEARCHTERM FILE...\n"); 56 | exit(1); 57 | }; 58 | 59 | var searchterm = *(args++); 60 | 61 | if (*args) { 62 | # show filename in output if more than 1 filename is given 63 | if (*(args+1)) showfilename = 1; 64 | 65 | while (*args) 66 | grep(searchterm, *(args++)); 67 | } else { 68 | bgrep(searchterm, bfdopen(0, O_READ)); 69 | }; 70 | -------------------------------------------------------------------------------- /sys/hd.sl: -------------------------------------------------------------------------------- 1 | # hex dump 2 | 3 | include "bufio.sl"; 4 | include "stdio.sl"; 5 | include "sys.sl"; 6 | include "malloc.sl"; 7 | 8 | var bufsz = 256; 9 | var buf = malloc(bufsz); 10 | 11 | var linebuf = malloc(8); 12 | var linepos = 0; 13 | var first = 1; 14 | 15 | var out = bfdopen(1, O_WRITE); 16 | 17 | var show_text_line = func() { 18 | var end = 8; 19 | 20 | var n; 21 | if ((linepos & 7) != 0) { 22 | n = 8 - (linepos&7); 23 | while (n--) bputs(out, " "); 24 | end = linepos & 7; 25 | }; 26 | 27 | bputs(out, " |"); 28 | var i = 0; 29 | var ch; 30 | while (i < end) { 31 | ch = linebuf[i++] & 0xff; 32 | if (ch >= ' ' && ch <= '~') bputc(out, ch) 33 | else bputc(out, '.'); 34 | }; 35 | bputs(out, "|\n"); 36 | }; 37 | 38 | var output = func(ch) { 39 | if ((linepos & 7) == 0) { 40 | if (!first) show_text_line() 41 | else first = 0; 42 | 43 | bprintf(out, "%04x: ", [linepos]); 44 | }; 45 | 46 | *(linebuf+(linepos&7)) = ch; 47 | 48 | bprintf(out, " %04x", [ch]); 49 | }; 50 | 51 | var hd = func(name) { 52 | var fd = 0; 53 | if (name) { 54 | fd = open(name, O_READ); 55 | if (fd < 0) { 56 | fprintf(2, "hd: open %s: %s\n", [name, strerror(fd)]); 57 | return 0; 58 | }; 59 | }; 60 | var in = bfdopen(fd, O_READ); 61 | 62 | var n; 63 | var i; 64 | while (1) { 65 | n = bread(in, buf, bufsz); 66 | if (n == 0) break; 67 | if (n < 0) { 68 | fprintf(2, "hd: read %d: %s\n", [fd, strerror(n)]); 69 | break; 70 | }; 71 | 72 | i = 0; 73 | while (i < n) { 74 | output(buf[i++]); 75 | linepos++; 76 | }; 77 | }; 78 | bclose(in); 79 | 80 | if ((linepos & 7) != 0) show_text_line(); 81 | }; 82 | 83 | var args = cmdargs()+1; 84 | 85 | if (args[1]) { 86 | fputs(2, "usage: hd [FILE]\n"); 87 | exit(1); 88 | }; 89 | 90 | if (*args) hd(*args) 91 | else hd(0); 92 | 93 | bclose(out); 94 | 95 | exit(0); 96 | -------------------------------------------------------------------------------- /sys/head.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | include "malloc.sl"; 3 | 4 | var bufsz = 16384; 5 | var buf = malloc(bufsz); 6 | 7 | var args = cmdargs()+1; 8 | if (!*args || *(args+1)) { 9 | fputs(2, "usage: head N\n"); 10 | exit(1); 11 | }; 12 | 13 | var N = atoi(*args); 14 | 15 | setbuf(0, malloc(257)); 16 | setbuf(1, malloc(257)); 17 | 18 | while (gets(buf,bufsz) && N--) 19 | puts(buf); 20 | -------------------------------------------------------------------------------- /sys/init.sl: -------------------------------------------------------------------------------- 1 | include "sys.sl"; 2 | 3 | # TODO: [nice] init should become a shell script if they get fast enough 4 | 5 | var bufsz = 128; 6 | var buf = asm { .gap 128 }; 7 | 8 | var clearout = func(dir) { 9 | var fd = opendir(dir); 10 | if (fd < 0) return 0; 11 | 12 | chdir(dir); 13 | 14 | var n; 15 | var p; 16 | while (1) { 17 | n = readdir(fd, buf, bufsz); 18 | if (n <= 0) break; 19 | p = buf; 20 | while (n--) { 21 | unlink(p); 22 | while (*p) p++; 23 | p++; 24 | }; 25 | }; 26 | close(fd); 27 | }; 28 | 29 | var cat = func(name) { 30 | var fd = open(name, O_READ); 31 | if (fd < 0) return 0; 32 | 33 | var n; 34 | while (1) { 35 | n = read(fd, buf, bufsz); 36 | if (n <= 0) break; 37 | write(1, buf, n); 38 | }; 39 | close(fd); 40 | }; 41 | 42 | #clearout("/tmp"); 43 | #clearout("/proc"); 44 | cat("/etc/motd"); 45 | chdir("/home"); 46 | while (1) 47 | system(["/bin/sh"]); 48 | -------------------------------------------------------------------------------- /sys/isprime.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | include "bigint.sl"; 3 | 4 | var args = cmdargs()+1; 5 | if (!*args) { 6 | fprintf(2, "usage: isprime N\n", 0); 7 | exit(1); 8 | }; 9 | 10 | biginit(2); 11 | 12 | var N = bigatoi(*args); 13 | var m = bigclone(N); 14 | 15 | # special case: divisible by 2? 16 | bigmodw(m, 2); 17 | if (bigcmpw(m, 0) == 0) { 18 | printf("%b is divisible by 2\n", [N]); 19 | exit(0); 20 | }; 21 | 22 | var i = bignew(3); 23 | var isquared = bignew(9); 24 | while (bigcmp(isquared, N) <= 0) { 25 | bigset(m, N); 26 | bigmod(m, i); 27 | if (bigcmpw(m, 0) == 0) { 28 | printf("%b is divisible by %b\n", [N, i]); 29 | exit(0); 30 | }; 31 | 32 | # (i+2)*(i+2) = i^2 + 4i + 2 33 | bigadd(isquared, i); 34 | bigadd(isquared, i); 35 | bigadd(isquared, i); 36 | bigadd(isquared, i); 37 | bigaddw(isquared, 4); 38 | 39 | bigaddw(i, 2); 40 | }; 41 | 42 | printf("%b is prime\n", [N]); 43 | -------------------------------------------------------------------------------- /sys/keys.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | 3 | serflags(0, 0); 4 | 5 | var ch; 6 | while (1) { 7 | ch = getchar(); 8 | printf("%d ", [ch]); 9 | if (ch == 3) break; # ctrl-c 10 | }; 11 | -------------------------------------------------------------------------------- /sys/kwr.sl: -------------------------------------------------------------------------------- 1 | # write kernel to disk 2 | # 3 | # usage: kwr kernel.bin c000 4 | 5 | include "getopt.sl"; 6 | include "sys.sl"; 7 | 8 | var args = cmdargs()+1; 9 | 10 | if (!*args || !*(args+1) || *(args+2)) { 11 | fprintf(2, "usage: kwr FILE START\nWhere START is the start address in hex.\n", 0); 12 | exit(1); 13 | }; 14 | 15 | var file = args[0]; 16 | var start = atoibase(args[1], 16); 17 | 18 | var statbuf = malloc(4); 19 | var n = stat(file, statbuf); 20 | if (n == -1) { 21 | fprintf(2, "stat %s: %s\n", [file, strerror(n)]); 22 | exit(1); 23 | }; 24 | var length = statbuf[1]; 25 | 26 | var sum = 0; 27 | var blksz = 256; 28 | var blk = malloc(blksz); 29 | blk[0] = 0x5343; 30 | blk[1] = start; 31 | blk[2] = length+1; 32 | 33 | var fd = open(file, O_READ); 34 | if (fd == -1) { 35 | fprintf(2, "open %s: %s\n", [file, strerror(n)]); 36 | exit(1); 37 | }; 38 | 39 | # read first block 40 | n = read(fd, blk+3, blksz-3); 41 | var i = 0; 42 | while (i < n+3) { 43 | sum = sum + blk[i]; 44 | i++; 45 | }; 46 | 47 | # TODO: [bug] if kernel is smaller than 1 block, put checksum in first block 48 | 49 | # write first block 50 | var blknum = 0; 51 | blkwrite(blknum++, blk); 52 | 53 | # write more blocks 54 | while (1) { 55 | n = read(fd, blk, blksz); 56 | if (n < 0) { 57 | fprintf(2, "read %s: %s\n", [file, strerror(n)]); 58 | exit(1); 59 | }; 60 | i = 0; 61 | while (i < n) { 62 | sum = sum + blk[i]; 63 | i++; 64 | }; 65 | if (n < blksz) blk[n] = -sum; 66 | blkwrite(blknum++, blk); 67 | if (n < blksz) break; 68 | }; 69 | -------------------------------------------------------------------------------- /sys/lib/foot.s: -------------------------------------------------------------------------------- 1 | 2 | # exit(0) 3 | push 0 4 | call (_sys_exit) 5 | 6 | # top of program address 7 | TOP: 8 | -------------------------------------------------------------------------------- /sys/lib/head.s: -------------------------------------------------------------------------------- 1 | .at 0x100 2 | 3 | # initialise sp and TOP 4 | .def STACKSZ 2048 5 | ld sp, TOP 6 | add sp, STACKSZ 7 | 8 | # stack grows down, _TOP grows up; 9 | # make _TOP point 1 word past the initial stack pointer 10 | ld (_TOP), sp 11 | inc (_TOP) 12 | 13 | # storage for _TOP address 14 | jr+ 1 15 | _TOP: .word 0 16 | 17 | # system call vectors 18 | .def _sys_getpid 0xfee5 19 | .def _sys_savetpa 0xfee6 20 | .def _sys_trap 0xfee7 21 | .def _sys_blkwrite 0xfee8 22 | .def _sys_blkread 0xfee9 23 | .def _sys_random 0xfeea 24 | .def _sys_serflags 0xfeeb 25 | .def _sys_cmdargs 0xfeec 26 | .def _sys_osbase 0xfeed 27 | .def _sys_copyfd 0xfeee 28 | .def _sys_unlink 0xfeef 29 | .def _sys_stat 0xfef0 30 | .def _sys_readdir 0xfef1 31 | .def _sys_opendir 0xfef2 32 | .def _sys_mkdir 0xfef3 33 | .def _sys_chdir 0xfef4 34 | .def _sys_rename 0xfef5 35 | .def _sys_sync 0xfef6 36 | .def _sys_close 0xfef7 37 | .def _sys_open 0xfef8 38 | .def _sys_read 0xfef9 39 | .def _sys_setbuf 0xfefa 40 | .def _sys_write 0xfefb 41 | .def _sys_getcwd 0xfefc 42 | .def _sys_system 0xfefd 43 | .def _sys_exec 0xfefe 44 | .def _sys_exit 0xfeff 45 | 46 | -------------------------------------------------------------------------------- /sys/lib/heap.sl: -------------------------------------------------------------------------------- 1 | # min-heap 2 | # based on the broken example at https://www.educative.io/blog/data-structure-heaps-guide 3 | # 4 | # h[0] = comparator 5 | # h[1] = grarr 6 | 7 | include "grarr.sl"; 8 | 9 | var heapnew = func(cmp) { 10 | var h = malloc(2); 11 | h[0] = cmp; 12 | h[1] = grnew(); 13 | return h; 14 | }; 15 | 16 | var heapfree = func(h) { 17 | grfree(h[1]); 18 | free(h); 19 | }; 20 | 21 | var heaplen = func(h) { 22 | return grlen(h[1]); 23 | }; 24 | 25 | var _heappercolateup = func(h, index) { 26 | var parent; 27 | var cmp = h[0]; 28 | var gr = h[1]; 29 | var t; 30 | while (index) { 31 | parent = div(index-1,2); 32 | 33 | # if "index" and "parent" are already in the right order, do nothing 34 | if (cmp(grget(gr,parent), grget(gr,index)) < 0) return 0; 35 | 36 | # otherwise, swap index and parent, and step up a level 37 | t = grget(gr,parent); 38 | grset(gr,parent, grget(gr,index)); 39 | grset(gr,index, t); 40 | 41 | index = parent; 42 | }; 43 | }; 44 | 45 | var _heapify = func(h, index) { 46 | var cmp = h[0]; 47 | var gr = h[1]; 48 | var left; 49 | var right; 50 | var min; 51 | var t; 52 | while (1) { 53 | left = index+index+1; 54 | right = left+1; 55 | min = index; 56 | if (grlen(gr) > left) 57 | if (cmp(grget(gr,min), grget(gr,left)) > 0) 58 | min = left; 59 | if (grlen(gr) > right) 60 | if (cmp(grget(gr,min), grget(gr,right)) > 0) 61 | min = right; 62 | if (min == index) return 0; 63 | 64 | t = grget(gr, min); 65 | grset(gr, min, grget(gr, index)); 66 | grset(gr, index, t); 67 | index = min; 68 | }; 69 | }; 70 | 71 | # insert element v into heap h 72 | var heappush = func(h, v) { 73 | grpush(h[1], v); 74 | _heappercolateup(h, grlen(h[1])-1); 75 | }; 76 | 77 | # remove the minimum element from the heap and return it, or 0 if none 78 | var heappop = func(h) { 79 | var gr = h[1]; 80 | var min; 81 | if (grlen(gr) > 1) { 82 | min = grget(gr, 0); 83 | grset(gr, 0, grpop(gr)); 84 | _heapify(h, 0); 85 | return min; 86 | } else if (grlen(gr) == 1) { 87 | return grpop(gr); 88 | } else { 89 | return 0; 90 | }; 91 | }; 92 | -------------------------------------------------------------------------------- /sys/lib/libhead.s: -------------------------------------------------------------------------------- 1 | # we need ".at" to start us at the point where "head.s" will end 2 | .at 0x10a 3 | 4 | # point to the _TOP storage allocated in head.s 5 | .def _TOP 0x109 6 | 7 | # system call vectors 8 | .def _sys_getpid 0xfee5 9 | .def _sys_savetpa 0xfee6 10 | .def _sys_trap 0xfee7 11 | .def _sys_blkwrite 0xfee8 12 | .def _sys_blkread 0xfee9 13 | .def _sys_random 0xfeea 14 | .def _sys_serflags 0xfeeb 15 | .def _sys_cmdargs 0xfeec 16 | .def _sys_osbase 0xfeed 17 | .def _sys_copyfd 0xfeee 18 | .def _sys_unlink 0xfeef 19 | .def _sys_stat 0xfef0 20 | .def _sys_readdir 0xfef1 21 | .def _sys_opendir 0xfef2 22 | .def _sys_mkdir 0xfef3 23 | .def _sys_chdir 0xfef4 24 | .def _sys_rename 0xfef5 25 | .def _sys_sync 0xfef6 26 | .def _sys_close 0xfef7 27 | .def _sys_open 0xfef8 28 | .def _sys_read 0xfef9 29 | .def _sys_setbuf 0xfefa 30 | .def _sys_write 0xfefb 31 | .def _sys_getcwd 0xfefc 32 | .def _sys_system 0xfefd 33 | .def _sys_exec 0xfefe 34 | .def _sys_exit 0xfeff 35 | -------------------------------------------------------------------------------- /sys/lib/strbuf.sl: -------------------------------------------------------------------------------- 1 | # string buffer 2 | 3 | include "grarr.sl"; 4 | 5 | var sbnew = grnew; 6 | var sbfree = grfree; 7 | var sbbase = func(sb) { 8 | grpush(sb,0); grpop(sb); # make sure string is nul-terminated 9 | return grbase(sb); 10 | }; 11 | var sblen = grlen; 12 | var sbputc = grpush; 13 | var sbpop = grpop; 14 | var sbclear = func(sb) { 15 | grtrunc(sb, 0); 16 | }; 17 | 18 | var sbputs = func(sb, s) { 19 | while (*s) { 20 | sbputc(sb, *s); 21 | s++; 22 | }; 23 | }; 24 | 25 | var sbwrite = func(sb, s, len) { 26 | while (len--) { 27 | sbputc(sb, *s); 28 | s++; 29 | }; 30 | }; 31 | 32 | var sbprintf_sb; 33 | var sbprintf = func(sb, fmt, args) { 34 | sbprintf_sb = sb; 35 | return xprintf(fmt, args, func(ch) { 36 | sbputc(sbprintf_sb, ch); 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /sys/lisp/lib.l: -------------------------------------------------------------------------------- 1 | (defmacro (if pred thenexpr elseexpr) 2 | `(cond (,pred ,thenexpr) 3 | (else ,elseexpr))) 4 | 5 | -------------------------------------------------------------------------------- /sys/make-lib: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # if you add something here you also need to add a line to ../kernel/fs.in to put 4 | # an empty file in /lib/foo.h 5 | LIBS="grarr.sl malloc.sl parse.sl stdio.sl stdlib.sl string.sl sys.sl xprintf.sl strbuf.sl bufio.sl hash.sl xscanf.sl bitmap.sl" 6 | 7 | makelib() { 8 | name=$1 9 | shift 10 | 11 | echo " ... makelib $name" 12 | 13 | for f in $LIBS $*; 14 | do 15 | echo "include \"$f\";" 16 | done > lib$name.sl 17 | 18 | ../compiler/slangc --consts-list lib$name.const lib$name.sl | ../compiler/peepopt | ../compiler/peepopt > lib$name.s.build 19 | 20 | cat lib/libhead.s lib$name.s.build | ../asm/asm --externs-list lib$name.list > lib$name.hex.tmp 21 | ../util/hex2bin lib$name.hex.tmp > lib$name.o.tmp 22 | mv lib$name.o.tmp lib$name.o 23 | cat lib/libhead.s lib$name.s.build | ../asm/asm -v > lib$name.anhex 24 | } 25 | 26 | makelib "" & 27 | makelib fixed fixed.sl & 28 | makelib bigint bigint.sl & 29 | makelib bigfix bigint.sl fixed.sl & 30 | 31 | wait 32 | -------------------------------------------------------------------------------- /sys/mk-rude-globals: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | for my $extern (read_list('libbigint.list')) { 7 | my ($name, $addr) = @$extern; 8 | print "addglobal(\"$name\", &$name);\n"; 9 | } 10 | 11 | for my $const (read_list('libbigint.const')) { 12 | my ($name, $val) = @$const; 13 | print "var const_$name = $val;\n"; 14 | print "addglobal(\"$name\", &const_$name);\n"; 15 | } 16 | 17 | sub read_list { 18 | my ($name) = @_; 19 | my @results; 20 | open (my $fh, '<', $name) 21 | or die "can't read $name: $!\n"; 22 | my $val = ord(getc($fh))*256+ord(getc($fh)); 23 | while (<$fh>) { 24 | chomp; 25 | my ($name) = unpack("a*", $_); 26 | $name =~ s/\0//g; 27 | push @results, [$name,$val]; 28 | my $c1 = getc($fh) // last; 29 | my $c2 = getc($fh) // last; 30 | $val = ord($c1)*256+ord($c2); 31 | }; 32 | return @results; 33 | } 34 | -------------------------------------------------------------------------------- /sys/mkdir.sl: -------------------------------------------------------------------------------- 1 | include "sys.sl"; 2 | include "stdio.sl"; 3 | 4 | # TODO: [nice] implement "-p" 5 | 6 | var args = cmdargs()+1; 7 | 8 | if (!*args) { 9 | fputs(2, "usage: mkdir NAME...\n"); 10 | exit(1); 11 | }; 12 | 13 | var n; 14 | while (*args) { 15 | n = mkdir(*args); 16 | if (n < 0) fprintf(2, "mkdir: %s: %s\n", [*args, strerror(n)]); 17 | args++; 18 | }; 19 | -------------------------------------------------------------------------------- /sys/more.sl: -------------------------------------------------------------------------------- 1 | include "bufio.sl"; 2 | include "malloc.sl"; 3 | include "sys.sl"; 4 | 5 | var LINES = 25; 6 | var COLS = 80; 7 | 8 | var bufsz = COLS; 9 | var buf = malloc(bufsz); 10 | 11 | var out = bfdopen(1, O_WRITE); 12 | 13 | # put console in raw mode 14 | serflags(3, 0); 15 | 16 | var prompt = func(text) { 17 | bputs(out, text); 18 | bflush(out); 19 | var ch = fgetc(3); # read 1 char from the console 20 | 21 | # now rub out the prompt 22 | bputc(out, '\r'); 23 | while (*(text++)) bputc(out, ' '); 24 | bputc(out, '\r'); 25 | 26 | if (ch == 'q') exit(0); 27 | 28 | # TODO: [nice] if (ch == '/'), read a search phrase up to '\n' and then search forwards 29 | # TODO: [nice] if (ch == 'n'), repeat search 30 | }; 31 | 32 | var more = func(in) { 33 | var l = 0; 34 | 35 | while (bgets(in, buf, bufsz)) { 36 | bputs(out, buf); 37 | l++; 38 | 39 | if (l == LINES-1) { 40 | prompt("--MORE--"); 41 | l = 0; 42 | }; 43 | }; 44 | }; 45 | 46 | var in; 47 | 48 | var args = cmdargs()+1; 49 | if (!*args) { 50 | in = bfdopen(0, O_READ); 51 | more(in); 52 | } else { 53 | while (*args) { 54 | in = bopen(*args, O_READ); 55 | if (in) { 56 | more(in); 57 | } else { 58 | bflush(out); 59 | fprintf(2, "more: %s: can't read\n", [*args]); 60 | bflush(out); 61 | }; 62 | args++; 63 | if (*args) prompt("--MORE (next file)--"); 64 | }; 65 | }; 66 | 67 | bflush(out); 68 | -------------------------------------------------------------------------------- /sys/mv.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | include "sys.sl"; 3 | include "malloc.sl"; 4 | 5 | var args = cmdargs()+1; 6 | 7 | if (!*args || !*(args+1) || *(args+2)) { 8 | fputs(2,"usage: mv OLDNAME NEWNAME\n"); 9 | exit(1); 10 | }; 11 | 12 | # TODO: [nice] if *(args+1) is a directory, create the name inside the directory 13 | 14 | var n; 15 | 16 | var statbuf = malloc(4); 17 | n = stat(*(args+1), statbuf); 18 | if (n == 0 && statbuf[0] == 0) { 19 | fprintf(2, "mv: %s: is directory\n", [*(args+1)]); 20 | exit(1); 21 | }; 22 | 23 | n = rename(*args, *(args+1)); 24 | if (n == EXISTS) { 25 | unlink(*(args+1)); 26 | n = rename(*args, *(args+1)); 27 | }; 28 | if (n != 0) fprintf(2, "mv: %s\n", [strerror(n)]); 29 | -------------------------------------------------------------------------------- /sys/opts.sl: -------------------------------------------------------------------------------- 1 | include "getopt.sl"; 2 | include "stdio.sl"; 3 | include "sys.sl"; 4 | 5 | var message = "message"; 6 | var file = "file"; 7 | 8 | var help = func(rc) { 9 | printf( 10 | "options: 11 | 12 | -f file Set the filename. 13 | -h Show this help text. 14 | -m msg Set the message to display. 15 | ", 0); 16 | exit(rc); 17 | }; 18 | 19 | var more_args = getopt(cmdargs()+1, "mf", func(ch, arg) { 20 | printf(" ... option %c takes argument %s\n", [ch,arg]); 21 | if (ch == 'm') message = arg 22 | else if (ch == 'f') file = arg 23 | else if (ch == 'h') help(0) 24 | else { 25 | fprintf(2, "error: unrecognised option -%c\n", [ch]); 26 | help(1); 27 | }; 28 | }); 29 | 30 | printf("%s\n", [message]); 31 | printf("The file is: %s\n", [file]); 32 | 33 | if (*more_args) { 34 | printf("More arguments:\n", 0); 35 | while (*more_args) { 36 | printf(" %s\n", [*more_args]); 37 | more_args++; 38 | }; 39 | }; 40 | -------------------------------------------------------------------------------- /sys/ps.sl: -------------------------------------------------------------------------------- 1 | # read /proc/*.kernel and report the state of the process stack 2 | # 3 | # TODO: [nice] what other stuff should we display? size of *.user? number of open 4 | # files? return address? whether a trap function is in use? 5 | 6 | include "stdio.sl"; 7 | 8 | var showproc = func(pid) { 9 | var name = sprintf("/proc/%d.kernel", [pid]); 10 | var fd = open(name, O_READ); 11 | free(name); 12 | if (fd < 0) return 0; 13 | 14 | var sp; 15 | var ret; 16 | var cwdblk; 17 | var args_sz; 18 | var args_ptr; 19 | var args; 20 | var trapfunc; 21 | var fdtable = malloc(128); 22 | 23 | # this should match sys_exit_impl() from kernel/sys_proc.sl 24 | read(fd, &sp, 1); 25 | read(fd, &ret, 1); 26 | read(fd, &cwdblk, 1); 27 | read(fd, &args_sz, 1); 28 | args = malloc(args_sz); 29 | read(fd, &args_ptr, 1); 30 | read(fd, args, args_sz); 31 | read(fd, &trapfunc, 1); 32 | read(fd, fdtable, 128); 33 | close(fd); 34 | 35 | printf("%d ", [pid]); 36 | 37 | var args_off = args - args_ptr; 38 | var p = args; 39 | while (*p) { 40 | puts(*p + args_off); 41 | p++; 42 | if (*p) putchar(' '); 43 | }; 44 | putchar('\n'); 45 | 46 | free(args); 47 | free(fdtable); 48 | return 1; 49 | }; 50 | 51 | var pid = 0; 52 | while (pid < getpid()) { 53 | if (!showproc(pid)) break; 54 | pid++; 55 | }; 56 | -------------------------------------------------------------------------------- /sys/pwd.sl: -------------------------------------------------------------------------------- 1 | include "sys.sl"; 2 | include "stdio.sl"; 3 | include "malloc.sl"; 4 | 5 | var bufsz = 256; 6 | var buf = malloc(bufsz); 7 | var n = getcwd(buf, bufsz); 8 | if (n < 0) fprintf(2, "pwd: %s\n", [strerror(n)]) 9 | else printf("%s\n", [buf]); 10 | -------------------------------------------------------------------------------- /sys/reboot.sl: -------------------------------------------------------------------------------- 1 | var reboot = 0; 2 | reboot(); 3 | -------------------------------------------------------------------------------- /sys/reset.sl: -------------------------------------------------------------------------------- 1 | # reset the terminal 2 | 3 | include "stdio.sl"; 4 | 5 | var esc = func() { putchar(0x1b); }; 6 | 7 | esc(); puts("[2J"); # clear screen 8 | esc(); puts("[H"); # home cursor 9 | esc(); puts("[?25h"); # show cursor 10 | esc(); puts("[?12h"); # enable blinking 11 | -------------------------------------------------------------------------------- /sys/rsh.sl: -------------------------------------------------------------------------------- 1 | # open a shell on the 2nd serial port 2 | 3 | include "sys.sl"; 4 | 5 | serflags(4, SER_COOKED); 6 | 7 | copyfd(0, 4); 8 | copyfd(1, 4); 9 | copyfd(2, 4); 10 | exec(["/bin/sh"]); 11 | -------------------------------------------------------------------------------- /sys/rx.sl: -------------------------------------------------------------------------------- 1 | # rx - receive a file with xmodem from secondary serial port 2 | # TODO: [nice] show debug info if "-v" or similar 3 | 4 | include "stdio.sl"; 5 | include "sys.sl"; 6 | 7 | var CH_SOH = 0x01; 8 | var CH_EOT = 0x04; 9 | var CH_ACK = 0x06; 10 | var CH_NAK = 0x15; 11 | 12 | var packet = 1; 13 | var buf = malloc(132); 14 | 15 | serflags(4, 0); # raw mode 16 | 17 | var readpacket = func() { 18 | var need = 132; 19 | var bufp = buf; 20 | var n; 21 | while (need) { 22 | n = read(4, bufp, need); 23 | if (n < 0) { 24 | fprintf(2, "error: read: %s\n", [strerror(n)]); 25 | exit(1); 26 | }; 27 | need = need - n; 28 | bufp = bufp + n; 29 | 30 | if (*buf == CH_EOT) break; 31 | }; 32 | }; 33 | 34 | var ack = func() write(4, &CH_ACK, 1); 35 | var nak = func() write(4, &CH_NAK, 1); 36 | 37 | var chk = func() { 38 | var sum = 0; 39 | var n = 131; 40 | while (n--) { 41 | sum = sum + buf[n]; 42 | }; 43 | return (sum&0xff) == buf[131]; 44 | }; 45 | 46 | nak(); 47 | 48 | while (1) { 49 | readpacket(); 50 | if (*buf == CH_EOT) { 51 | nak(); 52 | readpacket(); 53 | if (*buf != CH_EOT) { 54 | nak(); 55 | continue; 56 | }; 57 | break; 58 | }; 59 | 60 | if (*buf != CH_SOH) { 61 | nak(); 62 | continue; 63 | }; 64 | 65 | if ((buf[1] != packet) || (buf[2] != (0xff - packet))) { 66 | nak(); 67 | continue; 68 | }; 69 | 70 | if (!chk()) { 71 | nak(); 72 | continue; 73 | }; 74 | 75 | write(1, buf+3, 128); 76 | fputc(2, '.'); 77 | packet++; 78 | ack(); 79 | }; 80 | 81 | fputc(2, '\n'); 82 | -------------------------------------------------------------------------------- /sys/ser.sl: -------------------------------------------------------------------------------- 1 | include "bufio.sl"; 2 | include "serial.sl"; 3 | include "strbuf.sl"; 4 | 5 | var usage = func() { 6 | fputs(2, "usage: ser get REMOTEPATH LOCALPATH\n"); 7 | fputs(2, " ser put LOCALPATH REMOTEPATH\n"); 8 | exit(1); 9 | }; 10 | 11 | var slurp = func(name) { 12 | var b = bopen(name, O_READ); 13 | var sb = sbnew(); 14 | var ch; 15 | while (1) { 16 | ch = bgetc(b); 17 | if (ch == EOF) break; 18 | sbputc(sb, ch); 19 | }; 20 | bclose(b); 21 | return sbbase(sb); 22 | }; 23 | 24 | var args = cmdargs()+1; 25 | if (!args[0] || !args[1] || !args[2]) usage(); 26 | 27 | var rc = 0; 28 | 29 | var localfile; 30 | var filebuf = malloc(16384); 31 | *filebuf = 0; 32 | var filep = filebuf; 33 | var filelen = 0; 34 | var cb = func(ok, buf, len) { 35 | if (ok) { 36 | if (localfile) bwrite(localfile, buf, len); 37 | } else { 38 | rc = 1; 39 | write(2, buf, len); 40 | }; 41 | }; 42 | 43 | var r; 44 | 45 | ser_sync(); 46 | 47 | if (strcmp(args[0], "get") == 0) { 48 | localfile = bopen(args[2], O_WRITE|O_CREAT); 49 | if (!localfile) { 50 | fprintf(2, "error: can't open %s\n", [args[2]]); 51 | exit(1); 52 | }; 53 | ser_get_p("file", args[1], 0, cb); 54 | } else if (strcmp(args[0], "put") == 0) { 55 | r = ser_put("file", args[2], slurp(args[1])); 56 | if (!r[0]) { 57 | fputs(2, r[1]); 58 | rc = 1; 59 | }; 60 | free(r[1]); 61 | } else { 62 | usage(); 63 | }; 64 | 65 | if (rc != 0) fputc(2, '\n'); 66 | 67 | if (localfile) bclose(localfile); 68 | 69 | exit(rc); 70 | -------------------------------------------------------------------------------- /sys/sort.sl: -------------------------------------------------------------------------------- 1 | # sorting test: read lines into memory, sort, print out 2 | # 3 | # TODO: [perf] long-term, this should swap to disk so that it can sort longer inputs 4 | 5 | include "bigint.sl"; 6 | include "bufio.sl"; 7 | include "grarr.sl"; 8 | include "malloc.sl"; 9 | include "stdlib.sl"; 10 | include "string.sl"; 11 | include "getopt.sl"; 12 | 13 | biginit(4); 14 | 15 | var help = func(rc) { 16 | puts("usage: sort [options] < INPUT 17 | 18 | options: 19 | -h show this text 20 | -n numeric sort 21 | -r reverse sort 22 | "); 23 | exit(rc); 24 | }; 25 | 26 | var rev = 0; 27 | var num = 0; 28 | 29 | var cmp = func(a, b) { 30 | var n; 31 | var biga; 32 | var bigb; 33 | 34 | if (num) { 35 | # TODO: [perf] compare characters instead of using bigint 36 | biga = bigatoi(a); 37 | bigb = bigatoi(b); 38 | n = bigcmp(biga, bigb); 39 | bigfree(biga); bigfree(bigb); 40 | } else { 41 | n = strcmp(a, b); 42 | }; 43 | 44 | if (rev) return -n; 45 | return n; 46 | }; 47 | 48 | var args = getopt(cmdargs()+1, "", func(ch,arg) { 49 | if (ch == 'r') rev = 1 50 | else if (ch == 'n') num = 1 51 | else if (ch == 'h') help(0) 52 | else help(1); 53 | }); 54 | if (*args) help(1); 55 | 56 | var in = bfdopen(0, O_READ); 57 | var out = bfdopen(1, O_WRITE); 58 | 59 | var bufsz = 1024; 60 | var buf = malloc(bufsz); 61 | 62 | var strings = grnew(); 63 | 64 | while (bgets(in, buf, bufsz)) 65 | grpush(strings, strdup(buf)); 66 | 67 | grsort(strings, cmp); 68 | 69 | grwalk(strings, func(s) { 70 | bputs(out, s); 71 | }); 72 | bflush(out); 73 | -------------------------------------------------------------------------------- /sys/stat.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | include "sys.sl"; 3 | 4 | # TODO: [bug] suport numbers > 16-bit 5 | 6 | var showstat = func(name) { 7 | var statbuf = [0,0,0,0]; 8 | var n = stat(name, statbuf); 9 | if (n < 0) { 10 | fprintf(2, "stat: %s: %s\n", [name, strerror(n)]); 11 | return 0; 12 | }; 13 | 14 | var typch = 'f'; 15 | if (*statbuf == 0) typch = 'd'; 16 | printf("%c %u\t%u\t%u\t%s\n", [typch, statbuf[1], statbuf[2], statbuf[3], name]); 17 | }; 18 | 19 | var args = cmdargs()+1; 20 | 21 | if (!*args) { 22 | fputs(2, "usage: stat NAME...\n"); 23 | exit(1); 24 | }; 25 | 26 | while (*args) { 27 | showstat(*args); 28 | args++; 29 | }; 30 | -------------------------------------------------------------------------------- /sys/sx.sl: -------------------------------------------------------------------------------- 1 | # sx - send a file with xmodem to secondary serial port 2 | # TODO: [nice] show debug info if "-v" or similar 3 | 4 | include "stdio.sl"; 5 | include "sys.sl"; 6 | 7 | var CH_SOH = 0x01; 8 | var CH_EOT = 0x04; 9 | var CH_ACK = 0x06; 10 | var CH_NAK = 0x15; 11 | var CH_SUB = 0x1a; 12 | 13 | var packet = 1; 14 | var buf = malloc(132); 15 | var seeneof = 0; 16 | 17 | var readblock = func() { 18 | var need = 128; 19 | var bufp = buf+3; 20 | var n; 21 | while (need) { 22 | n = read(0, bufp, need); 23 | if (n < 0) { 24 | fprintf(2, "error: read stdin: %s\n", [strerror(n)]); 25 | exit(1); 26 | }; 27 | if (n == 0) { 28 | seeneof = 1; 29 | while (need--) *(bufp++) = CH_SUB; 30 | break; 31 | }; 32 | need = need - n; 33 | bufp = bufp + n; 34 | }; 35 | }; 36 | 37 | var chk = func() { 38 | var sum = 0; 39 | var n = 131; 40 | while (n--) { 41 | sum = sum + buf[n]; 42 | }; 43 | buf[131] = sum&0xff; 44 | }; 45 | 46 | serflags(4, 0); # raw mode 47 | 48 | # wait for initial NAK from remote side 49 | while (fgetc(4) != CH_NAK); 50 | 51 | var ch; 52 | var finished = 0; 53 | while (!finished) { 54 | buf[0] = CH_SOH; 55 | buf[1] = packet; 56 | buf[2] = 0xff-packet; 57 | readblock(); 58 | chk(); 59 | write(4, buf, 132); 60 | while (1) { 61 | read(4, &ch, 1); 62 | if (ch == CH_ACK) { 63 | fputc(2, '.'); 64 | if (seeneof) finished = 1; 65 | packet++; 66 | break; 67 | } else if (ch == CH_NAK) { 68 | fputc(2, '!'); 69 | break; 70 | }; 71 | }; 72 | }; 73 | 74 | fputc(2, '\n'); 75 | -------------------------------------------------------------------------------- /sys/true.sl: -------------------------------------------------------------------------------- 1 | include "sys.sl"; 2 | exit(0); 3 | -------------------------------------------------------------------------------- /sys/while.sl: -------------------------------------------------------------------------------- 1 | # while CONDITION BODY 2 | 3 | include "sys.sl"; 4 | include "stdio.sl"; 5 | include "malloc.sl"; 6 | 7 | var usage = func() { 8 | fputs(2, "usage: while CONDITION BODY\n"); 9 | exit(1); 10 | }; 11 | 12 | var args = cmdargs()+1; 13 | if (!args[0] || !args[1] || args[2]) usage(); 14 | var condition = strdup(args[0]); 15 | var body = strdup(args[1]); 16 | 17 | while (system(["/bin/sh", "-c", condition]) == 0) 18 | system(["/bin/sh", "-c", body]); 19 | -------------------------------------------------------------------------------- /test/fs.in: -------------------------------------------------------------------------------- 1 | cd bin 2 | rm init 3 | cd .. 4 | put test.bin /bin/init 5 | 6 | put -t test.sl /home/test.sl 7 | put -t test_basic.sl /home/test_basic.sl 8 | put -t test_bigint.sl /home/test_bigint.sl 9 | put -t test_bitmap.sl /home/test_bitmap.sl 10 | put -t test_grarr.sl /home/test_grarr.sl 11 | put -t test_grep.sl /home/test_grep.sl 12 | put -t test_hash.sl /home/test_hash.sl 13 | put -t test_regex.sl /home/test_regex.sl 14 | put -t test_sh.sl /home/test_sh.sl 15 | -------------------------------------------------------------------------------- /test/lib: -------------------------------------------------------------------------------- 1 | ../sys/lib -------------------------------------------------------------------------------- /test/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | # build the test binary 7 | ../compiler/slangc test.sl | ../compiler/peepopt | ../compiler/peepopt > test.s 8 | cat ../sys/lib/head.s test.s ../sys/lib/foot.s | ../asm/asm > test.hex 9 | ../util/hex2bin test.hex > test.bin 10 | 11 | # get a filesystem image 12 | rm ../kernel/os.disk 13 | make -C ../kernel/ os.disk 14 | cp ../kernel/os.disk . 15 | 16 | # add the test binary to the filesystem 17 | ../fs/fs os.disk < fs.in 18 | 19 | # run the test 20 | ../emulator/scamp -i os.disk > test.out 21 | 22 | # check the results 23 | ./split-output < test.out 24 | cmp test.expect test-top.out || (diff -u test.expect test-top.out | less) 25 | cmp test.expect test-slc.out || (diff -u test.expect test-slc.out | less) 26 | cmp test.expect test-slangi.out || (diff -u test.expect test-slangi.out | less) 27 | cmp test.expect test-top.out && cmp test.expect test-slc.out && cmp test.expect test-slangi.out && echo "All tests PASSED." 28 | -------------------------------------------------------------------------------- /test/split-output: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my $fh; 7 | my $run; 8 | 9 | while (<>) { 10 | s/\r?\n?$//; 11 | if (/END TEST OUTPUT/) { 12 | die "'END TEST OUTPUT' but not begun" if !$fh; 13 | close $fh; 14 | undef $fh; 15 | } 16 | print $fh "$_\n" if $fh; 17 | if (/BEGIN TEST OUTPUT \(([^)]+)\)/) { 18 | die "'BEGIN TEST OUTPUT' but already begun ($run)" if $fh; 19 | my $run = $1; 20 | my $filename = "test-$run.out"; 21 | open($fh, '>', $filename) 22 | or die "write $filename: $!\n"; 23 | } 24 | } 25 | 26 | die "ran out of text before 'END TEST OUTPUT' ($run)" if $fh; 27 | -------------------------------------------------------------------------------- /test/test.sl: -------------------------------------------------------------------------------- 1 | include "stdio.sl"; 2 | 3 | include "test_basic.sl"; 4 | include "test_bigint.sl"; 5 | include "test_bitmap.sl"; 6 | include "test_grarr.sl"; 7 | include "test_grep.sl"; 8 | include "test_hash.sl"; 9 | include "test_regex.sl"; 10 | include "test_sh.sl"; 11 | 12 | chdir("/home"); 13 | 14 | var recurse = 1; 15 | var running_under = "(top)"; 16 | 17 | var args = cmdargs()+1; 18 | if (*args) { 19 | recurse = 0; 20 | running_under = sprintf("(%s)", [*args]); 21 | }; 22 | 23 | printf("BEGIN TEST OUTPUT %s\n", [running_under]); 24 | 25 | puts("test_basic:\n"); test_basic(); 26 | puts("test_bigint:\n"); test_bigint(); 27 | puts("test_bitmap:\n"); test_bitmap(); 28 | puts("test_grarr:\n"); test_grarr(); 29 | puts("test_grep:\n"); test_grep(); 30 | puts("test_hash:\n"); test_hash(); 31 | puts("test_regex:\n"); test_regex(); 32 | puts("test_sh:\n"); test_sh(); 33 | 34 | puts("END TEST OUTPUT\n"); 35 | 36 | if (recurse) { 37 | puts("----\nrun test again under slc:\n"); 38 | system(["/bin/slc", "-lbigint", "test.sl"]); 39 | system(["./test", "slc"]); 40 | 41 | puts("----\nrun test again under slangi:\n"); 42 | system(["/bin/slangi", "test.sl", "slangi"]); 43 | 44 | outp(3, 1); # halt 45 | }; 46 | -------------------------------------------------------------------------------- /test/test_basic.sl: -------------------------------------------------------------------------------- 1 | var _test_basic_foo = func(x) { 2 | printf("foo(%d)\n", [x]); 3 | }; 4 | 5 | var test_basic = func() { 6 | _test_basic_foo(0); 7 | _test_basic_foo(-1); 8 | _test_basic_foo(-2); 9 | _test_basic_foo(-5); 10 | _test_basic_foo(1); 11 | _test_basic_foo(2); 12 | _test_basic_foo(5); 13 | _test_basic_foo(-200); 14 | _test_basic_foo(-300); 15 | _test_basic_foo(-1); 16 | _test_basic_foo(1); 17 | _test_basic_foo(200); 18 | _test_basic_foo(300); 19 | }; 20 | -------------------------------------------------------------------------------- /test/test_bigint.sl: -------------------------------------------------------------------------------- 1 | include "bigint.sl"; 2 | 3 | var test_bigint = func() { 4 | biginit(4); 5 | 6 | var a = bignew(1234); 7 | var b = bignew(5678); 8 | var c = bignew(0); 9 | bigset(c, b); 10 | bigmul(c, a); 11 | printf("a=%b, b=%b, c=%b\n", [a, b, c]); 12 | 13 | bigdiv(c, b); 14 | printf("div b: c=%b\n", [c]); 15 | bigdiv(c, a); 16 | printf("div a: c=%b\n", [c]); 17 | 18 | var d = bigatoi("1234567890"); 19 | printf("d=%b\n", [d]); 20 | bigaddw(d, 1); 21 | printf("add 1: d=%b\n", [d]); 22 | bigsubw(d, 1000); 23 | printf("sub 1000: d=%b\n", [d]); 24 | 25 | bigadd(d, a); 26 | printf("add a: d=%b\n", [d]); 27 | }; 28 | -------------------------------------------------------------------------------- /test/test_bitmap.sl: -------------------------------------------------------------------------------- 1 | include "bitmap.sl"; 2 | 3 | var test_bitmap = func() { 4 | var bm = bmnew(120, 120); 5 | bmset(bm, 42, 42, 1); 6 | printf("count=%d\n", [bmcount(bm)]); 7 | bmset(bm, 42, 50, 1); 8 | printf("count=%d\n", [bmcount(bm)]); 9 | bmset(bm, 42, 50, 0); 10 | printf("count=%d\n", [bmcount(bm)]); 11 | 12 | bmset(bm, 100,100, 1); 13 | 14 | printf("bmwalk:",0); 15 | bmwalk(bm, func(x,y) { 16 | printf("%d,%d ", [x,y]); 17 | }); 18 | putchar('\n'); 19 | 20 | bmfree(bm); 21 | }; 22 | -------------------------------------------------------------------------------- /test/test_grarr.sl: -------------------------------------------------------------------------------- 1 | include "grarr.sl"; 2 | 3 | var test_grarr = func() { 4 | var gr = grnew(); 5 | 6 | var i = 0; 7 | while (i < 100) { 8 | grpush(gr, i); 9 | i++; 10 | }; 11 | 12 | i = 0; 13 | var n; 14 | while (i < 40) { 15 | printf("%d: grshift=%d, grpop=%d\n", [i, grshift(gr), grpop(gr)]); 16 | i++; 17 | }; 18 | 19 | printf("grlen=%d\n", [grlen(gr)]); 20 | 21 | i = 0; 22 | while (i < 10) { 23 | grunshift(gr, 500+i); 24 | grpush(gr, 1000+i); 25 | i++; 26 | }; 27 | puts("grwalk: "); 28 | grwalk(gr, func(v) { printf("%d ", [v]); }); 29 | putchar('\n'); 30 | 31 | grsort(gr, func(a, b) { return a - b }); 32 | 33 | puts("sorted grwalk: "); 34 | grwalk(gr, func(v) { printf("%d ", [v]); }); 35 | putchar('\n'); 36 | 37 | grfree(gr); 38 | }; 39 | -------------------------------------------------------------------------------- /test/test_grep.sl: -------------------------------------------------------------------------------- 1 | var test_grep = func() { 2 | system(["/bin/grep", "GREPGREPGREP", "test_grep.sl"]); 3 | }; 4 | -------------------------------------------------------------------------------- /test/test_hash.sl: -------------------------------------------------------------------------------- 1 | include "hash.sl"; 2 | 3 | var test_hash = func() { 4 | var ht = htnew(); 5 | htput(ht, "onetwothree", 123); 6 | htput(ht, "fourfivesix", 456); 7 | printf("get onetwothree=%d\n", [htget(ht, "onetwothree")]); 8 | printf("get fourfivesix=%d\n", [htget(ht, "fourfivesix")]); 9 | printf("get seveneightnine=%d\n", [htget(ht, "seveneightnine")]); 10 | var i = 0; 11 | while (i < 50) { 12 | htput(ht, sprintf("key%d", [i]), i); 13 | i++; 14 | }; 15 | 16 | printf("get key42=%d\n", [htget(ht, "key42")]); 17 | htfree(ht); 18 | }; 19 | -------------------------------------------------------------------------------- /test/test_regex.sl: -------------------------------------------------------------------------------- 1 | include "regex.sl"; 2 | 3 | var re; 4 | 5 | var test1 = func(str) { 6 | printf("%s: ", [str]); 7 | var cap = 0; 8 | if (rematch(re, str)) { 9 | if (recap(1)) cap = 1; 10 | *(recapend(cap)) = 0; 11 | printf("matched (captured %s)\n", [recap(cap)]) 12 | } 13 | else puts("didn't match\n"); 14 | }; 15 | 16 | var checkre = func(restr, matchstr, nomatchstr) { 17 | re = renew(restr); 18 | printf("%s should match:\n", [restr]); 19 | test1(matchstr); 20 | printf("%s shouldn't match:\n", [restr]); 21 | test1(nomatchstr); 22 | refree(re); 23 | }; 24 | 25 | var test_regex = func() { 26 | var restr = "a((?:b|c)*)d"; 27 | re = renew(restr); 28 | 29 | printf("%s should match:\n", [restr]); 30 | test1("abcd"); 31 | test1("abbbbbbbd"); 32 | test1("acccccccd"); 33 | test1("ad"); 34 | test1("abcbcbbbbbcccbcbcbcccbcbcbcbcd"); 35 | test1("abd"); 36 | test1("acd"); 37 | 38 | printf("%s should not match:\n", [restr]); 39 | test1("aadd"); 40 | test1(""); 41 | test1("abbbcc"); 42 | test1("bbccd"); 43 | test1("aad"); 44 | test1("ddddd"); 45 | 46 | refree(re); 47 | 48 | checkre("...\\w+...foo", "..._1234f348_43...foo", "...1234-1234...foo"); 49 | checkre("\\d+foo", "12345foo", "abcdefoo"); 50 | checkre("\\s*foo", " foo", "123foo"); 51 | checkre("[abc]*-end", "abcbcbabcbabcbbabc-end", "abd-end"); 52 | checkre("...\\W+...", "...-;[]'...", "...12345..."); 53 | checkre("\\D+foo", "abcdefoo", "12345foo"); 54 | checkre("\\S*foo", "1234fsdfsdfsd---foo", " foo"); 55 | checkre("[^abc]*-end", "def-end", "abc-end"); 56 | }; 57 | -------------------------------------------------------------------------------- /test/test_sh.sl: -------------------------------------------------------------------------------- 1 | var test_sh = func() { 2 | system(["/bin/sh", "-c", "ls", "-1", "test*.sl", "| sort > ls.out"]); 3 | system(["/bin/sh", "-c", "cat ls.*"]); 4 | system(["/bin/sh", "-c", "echo foo 'single quotes' \"double quotes\""]); 5 | }; 6 | -------------------------------------------------------------------------------- /ucode/mk-instructions-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Make instructions.json for the assembler 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use JSON qw(encode_json); 9 | 10 | my $opcode = -1; 11 | my $curinstr = ''; 12 | my %instructions; 13 | 14 | while (<>) { 15 | my $orig = $_; 16 | chomp; 17 | s/#.*//; # strip comments 18 | s/^\s+//; # strip leading spaces 19 | s/\s$//; # strip trailing spaces 20 | s/\s+/ /; # collapse spaces 21 | 22 | if ($orig =~ /# clobbers: (\w+)/) { 23 | push @{ $instructions{$curinstr}{clobbers} }, $1; 24 | } 25 | 26 | next if $_ eq ''; 27 | 28 | if (/^([a-z_0-9, \(\)\+-]+): ?([0-9a-f]*)$/i) { # new instruction starts 29 | $opcode++; 30 | $curinstr = $1; 31 | 32 | my $remark = ''; 33 | if ($orig =~ /#/) { 34 | $remark = $orig; 35 | $remark =~ s/^.*#\s*//; 36 | } 37 | 38 | $instructions{$curinstr} = { 39 | opcode => $opcode, 40 | cycles => 2, # every instruction takes at least 2 cycles 41 | ucode => [], 42 | words => ($curinstr =~ /i16/ ? 2 : 1), # XXX: ? 43 | clobbers => [], 44 | remark => $remark, 45 | }; 46 | } else { 47 | $instructions{$curinstr}{cycles}++; 48 | push @{ $instructions{$curinstr}{ucode} }, $_; 49 | push @{ $instructions{$curinstr}{clobbers} }, 'x' if /XI/ && !grep { /x/ } @{ $instructions{$curinstr}{clobbers} }; 50 | push @{ $instructions{$curinstr}{clobbers} }, 'y' if /YI/ && !grep { /y/ } @{ $instructions{$curinstr}{clobbers} }; 51 | } 52 | } 53 | 54 | print encode_json(\%instructions); 55 | -------------------------------------------------------------------------------- /util/bin2hex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # convert raw binary to 16-bit hex 4 | 5 | use strict; 6 | use warnings; 7 | 8 | die "give input on stdin" if @ARGV; 9 | 10 | while (read(STDIN, my $word, 2)) { 11 | my ($a,$b) = split //, $word; 12 | print sprintf("%02x%02x\n", ord($a), ord($b)); 13 | } 14 | -------------------------------------------------------------------------------- /util/burn-eeprom: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Time::HiRes qw(usleep); 7 | 8 | my $usage = "burn-eeprom DEVICE HEXFILE\ne.g. \$ burn-eeprom /dev/ttyACM0 ucode-low.hex\n"; 9 | my $dev = shift or die "usage: $usage"; 10 | my $hexfile = shift or die "usage: $usage"; 11 | 12 | # configure serial port 13 | # no idea what the hex numbers mean, I got them from "stty -g" after getting the port into a workable state using Arduino serial monitor 14 | system("stty -F \Q$dev\E 0:0:18b2:0:3:1c:7f:15:4:0:0:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"); 15 | open(my $fh, '+<', $dev) 16 | or die "can't open $dev: $!\n"; 17 | 18 | # load hex file 19 | my @data; 20 | open(my $hexfh, '<', $hexfile) 21 | or die "can't read $hexfile: $!\n"; 22 | while (<$hexfh>) { 23 | chomp; 24 | die "line $.: value out of range: $_\n" if hex($_) > 255; 25 | push @data, hex($_); 26 | } 27 | close $hexfh; 28 | 29 | print STDERR "Please close the jumper and hit ENTER...\n"; 30 | <>; 31 | burn_eeprom(0); 32 | 33 | if (@data > 1024) { 34 | print STDERR "Please open the jumper and hit ENTER...\n"; 35 | <>; 36 | burn_eeprom(1024); 37 | } 38 | 39 | sub burn_eeprom { 40 | my ($base) = @_; 41 | for my $addr (0 .. 1023) { 42 | my $val = $data[$addr+$base]; 43 | last if !defined $val; 44 | print $fh "write $addr $val\n"; 45 | usleep(12000); 46 | my $l = <$fh>; 47 | $l =~ s/[\0\r\n]//g; 48 | die "write $addr: ($l)\n" if $l ne 'ok'; 49 | my $pct = $addr / 1023; 50 | print STDERR sprintf(" \r%d%%", 100*$pct); 51 | } 52 | print STDERR "\n"; 53 | } 54 | -------------------------------------------------------------------------------- /util/burn-eeprom-24lc256: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Time::HiRes qw(usleep); 7 | 8 | my $usage = "burn-eeprom-24lc256 DEVICE BINARYFILE\ne.g. \$ burn-eeprom-24lc256 /dev/ttyUSB0 vt100.bin\n"; 9 | my $dev = shift or die "usage: $usage"; 10 | my $binfile = shift or die "usage: $usage"; 11 | 12 | # configure serial port 13 | # no idea what the hex numbers mean, I got them from "stty -g" after getting the port into a workable state using Arduino serial monitor 14 | system("stty -F \Q$dev\E 0:0:18b2:0:3:1c:7f:15:4:0:0:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"); 15 | open(my $fh, '+<', $dev) 16 | or die "can't open $dev: $!\n"; 17 | 18 | # load bin file 19 | open(my $binfh, '<', $binfile) 20 | or die "can't read $binfile: $!\n"; 21 | my @data = map { ord($_) } split //, join('', <$binfh>); 22 | close $binfh; 23 | 24 | burn_eeprom(); 25 | 26 | sub burn_eeprom { 27 | my $addr = 0; 28 | while (1) { 29 | my $val = $data[$addr]; 30 | last if !defined $val; 31 | print $fh "write $addr $val\n"; 32 | usleep(12000); 33 | my $l = <$fh>; 34 | $l =~ s/[\0\r\n]//g; 35 | die "write $addr: ($l)\n" if $l ne 'ok'; 36 | my $pct = $addr / @data; 37 | print STDERR sprintf(" \r%d%%", 100*$pct); 38 | $addr++; 39 | } 40 | print STDERR "\n"; 41 | } 42 | -------------------------------------------------------------------------------- /util/dump-eeprom: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Time::HiRes qw(usleep); 7 | 8 | $| = 1; 9 | 10 | my $dev = shift or die "usage: dump-eeprom DEVICE\ne.g. \$ dump-eeprom /dev/ttyACM0\n"; 11 | 12 | # configure serial port 13 | # no idea what the hex numbers mean, I got them from "stty -g" after getting the port into a workable state using Arduino serial monitor 14 | system("stty -F \Q$dev\E 0:0:18b2:0:3:1c:7f:15:4:0:0:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"); 15 | open(my $fh, '+<', $dev) 16 | or die "can't open $dev: $!\n"; 17 | 18 | print STDERR "Please close the jumper and hit ENTER...\n"; 19 | <>; 20 | dump_eeprom(); 21 | 22 | print STDERR "Please open the jumper and hit ENTER...\n"; 23 | <>; 24 | dump_eeprom(); 25 | 26 | sub dump_eeprom { 27 | for my $addr (0 .. 1023) { 28 | print $fh "read $addr\n"; 29 | usleep(12000); 30 | my $l = <$fh>; 31 | $l =~ s/[\0\r\n]//g; 32 | die "read $addr: ($l)\n" if $l !~ /^\d+$/; 33 | print sprintf("%02x\n", $l); 34 | my $pct = $addr / 1023; 35 | print STDERR sprintf(" \r%d%%", 100*$pct); 36 | } 37 | print STDERR "\n"; 38 | } 39 | -------------------------------------------------------------------------------- /util/dump-eeprom-24lc256: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Time::HiRes qw(usleep); 7 | 8 | $| = 1; 9 | 10 | my $dev = shift or die "usage: dump-eeprom-24lc256 DEVICE\ne.g. \$ dump-eeprom-24lc256 /dev/ttyUSB0\n"; 11 | 12 | # configure serial port 13 | # no idea what the hex numbers mean, I got them from "stty -g" after getting the port into a workable state using Arduino serial monitor 14 | system("stty -F \Q$dev\E 0:0:18b2:0:3:1c:7f:15:4:0:0:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"); 15 | open(my $fh, '+<', $dev) 16 | or die "can't open $dev: $!\n"; 17 | 18 | dump_eeprom(); 19 | 20 | sub dump_eeprom { 21 | my $SIZE = 24000; 22 | for my $addr (0 .. $SIZE) { 23 | print $fh "read $addr\n"; 24 | usleep(12000); 25 | my $l = <$fh>; 26 | $l =~ s/[\0\r\n]//g; 27 | die "read $addr: ($l)\n" if $l !~ /^\d+$/; 28 | print chr($l); 29 | my $pct = $addr / $SIZE; 30 | print STDERR sprintf(" \r%d%%", 100*$pct); 31 | } 32 | print STDERR "\n"; 33 | } 34 | -------------------------------------------------------------------------------- /util/hex2bin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # convert hex to raw binary 4 | # auto-detect whether the input is in bytes or words based on whether the 5 | # line is 2 or 4 chars 6 | 7 | use strict; 8 | use warnings; 9 | 10 | while (<>) { 11 | chomp; 12 | if (length($_) == 2) { 13 | print chr(hex($_)); 14 | } elsif (length($_) == 4) { 15 | print chr(hex($_)>>8); 16 | print chr(hex($_)&0xff); 17 | } else { 18 | die "line $.: unexpected line length: " . length($_) . "; expected 2 or 4 chars\n"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /util/hex2disk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # read in a 16-bit hex file and output a corresponding 8-bit 4 | # disk image that the bootrom can load into 0x100 5 | 6 | use strict; 7 | use warnings; 8 | 9 | sub usage { 10 | my ($rc) = @_; 11 | print qq{usage: $0 [options] < HEXFILE > DISKFILE 12 | 13 | options: 14 | --start ADDR Start the OS at the given address (in hex). 15 | }; 16 | exit($rc); 17 | } 18 | 19 | my $addr; 20 | 21 | use Getopt::Long; 22 | GetOptions( 23 | 'start=s' => \$addr, 24 | 'h|help' => sub { usage(0) }, 25 | ) or usage(1); 26 | 27 | if ($addr) { 28 | $addr = hex($addr); 29 | } else { 30 | $addr = 0x100; 31 | } 32 | 33 | # initialise magic number (0x5343), start address (0x0100), and placeholder length (0x0000) 34 | my @d = (0x53,0x43, $addr>>8,$addr&0xff, 0x00,0x00); 35 | 36 | while (<>) { 37 | chomp; 38 | my $v = hex($_); 39 | push @d, ($v>>8)&0xff; 40 | push @d, $v&0xff; 41 | } 42 | 43 | my $nwords = (@d-6)/2; 44 | $d[4] = ($nwords>>8)&0xff; 45 | $d[5] = $nwords&0xff; 46 | 47 | print sprintf("%02x\n", $_) for @d; 48 | -------------------------------------------------------------------------------- /util/pad-lines: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my $n = shift @ARGV or die "usage: pad-lines N LINE\n"; 7 | my $line = shift @ARGV or die "usage: pad-lines N LINE\n"; 8 | 9 | while (<>) { 10 | print; 11 | } 12 | 13 | print "$line\n" for ($.+1 .. $n); 14 | 15 | -------------------------------------------------------------------------------- /util/swap-endian: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | while (1) { 7 | last unless read(STDIN, my $ch1, 1); 8 | read(STDIN, my $ch2, 1); 9 | 10 | print "$ch2$ch1"; 11 | } 12 | -------------------------------------------------------------------------------- /util/unix2scamp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # in other words: ascii2utf16 4 | 5 | use strict; 6 | use warnings; 7 | 8 | my $s = join('',<>); 9 | 10 | for my $c (split //, $s) { 11 | print chr(0); 12 | print $c; 13 | }; 14 | -------------------------------------------------------------------------------- /verilog/alu.v: -------------------------------------------------------------------------------- 1 | /* Nand2Tetris ALU, but with zx/zy inverted 2 | 3 | This ALU is purely combinational. 4 | 5 | X,Y are 16-bit inputs 6 | 7 | C is 6 control bits: 8 | 5 4 3 2 1 0 9 | ex nx ey ny f no 10 | 11 | ex,ey: enable the respective operand (instead of using 0) 12 | nx,ny: invert the bits of the operand (applied after ex,ey) 13 | f: function select: 0 for '&', 1 for '+' 14 | no: invert the bits of the output 15 | 16 | Output to bus is enabled when en_bar is low. Output to val always. 17 | */ 18 | module ALU(X, Y, C, en_bar, bus, val, Z_flag, LT_flag); 19 | input [15:0] X; 20 | input [15:0] Y; 21 | input [5:0] C; 22 | input en_bar; 23 | output [15:0] bus; 24 | output [15:0] val; 25 | output Z_flag, LT_flag; 26 | 27 | assign {ex,nx,ey,ny,f,no} = C; 28 | 29 | wire [15:0] inx; 30 | wire [15:0] iny; 31 | wire [15:0] argx; 32 | wire [15:0] argy; 33 | wire [15:0] fxy; 34 | 35 | assign inx = ex ? X : 0; 36 | assign argx = nx ? ~inx : inx; 37 | assign iny = ey ? Y : 0; 38 | assign argy = ny ? ~iny : iny; 39 | 40 | assign fxy = f ? (argx+argy) : (argx&argy); 41 | 42 | assign val = no ? ~fxy : fxy; 43 | assign bus = !en_bar ? val : 16'hZZZZ; 44 | 45 | assign Z_flag = (val == 0); 46 | assign LT_flag = val[15]; 47 | endmodule 48 | -------------------------------------------------------------------------------- /verilog/cards-alu-high.v: -------------------------------------------------------------------------------- 1 | /* SCAMP ALU Card (MSB) 2 | 3 | Contains high byte of each of the ALU, X register, and Y register. 4 | Also contains flags register. 5 | */ 6 | 7 | `include "ttl/7402.v" 8 | `include "ttl/7432.v" 9 | `include "ttl/74244.v" 10 | `include "ttl/74377.v" 11 | 12 | module ALUHigh(clk, bus, XI_bar, YI_bar, EO_bar, ALU_op, carry_in, lsb_nz1, lsb_nz2, Z, LT, 13 | E_val, X_val, Y_val); 14 | input clk; 15 | inout [15:0] bus; 16 | input XI_bar, YI_bar, EO_bar; 17 | input [5:0] ALU_op; 18 | input carry_in, lsb_nz1, lsb_nz2; 19 | output Z, LT; 20 | output [7:0] E_val; 21 | output [7:0] X_val; 22 | output [7:0] Y_val; 23 | 24 | assign E_val = val; 25 | assign X_val = X; 26 | assign Y_val = Y; 27 | 28 | wire [7:0] X; 29 | wire [7:0] Y; 30 | wire [7:0] val; 31 | 32 | ALU4 alu1 (X[3:0], Y[3:0], ALU_op, carry_in, carry1, val[3:0], nonzero1); 33 | ALU4 alu2 (X[7:4], Y[7:4], ALU_op, carry1, nc, val[7:4], nonzero2); 34 | 35 | ttl_74244 buflow ({EO_bar,EO_bar}, val[7:0], bus[15:8]); 36 | 37 | ttl_74377 Xreg (XI_bar, bus[15:8], clk, X[7:0]); 38 | ttl_74377 Yreg (YI_bar, bus[15:8], clk, Y[7:0]); 39 | 40 | assign LT_flag = val[7]; 41 | 42 | ttl_7432 orer ({1'bZ, nonzero1, nonzero2, or1}, {1'bZ, lsb_nz1, lsb_nz2, or2}, {nc, or1, or2, nonzero}); 43 | ttl_7402 norer ({3'bZ, nonzero}, {3'bZ, nonzero}, {nc,nc,nc, Z_flag}); 44 | 45 | ttl_74377 flags (EO_bar, {6'bZ, Z_flag, LT_flag}, clk, {nc,nc,nc,nc,nc,nc, Z, LT}); 46 | endmodule 47 | -------------------------------------------------------------------------------- /verilog/cards-alu-low.v: -------------------------------------------------------------------------------- 1 | /* SCAMP ALU Card (LSB) 2 | 3 | Contains low byte of each of the ALU, X register, and Y register 4 | */ 5 | 6 | `include "ttl/74377.v" 7 | 8 | module ALULow(clk, bus, XI_bar, YI_bar, EO_bar, ALU_op, carry_out, lsb_nz1, lsb_nz2, 9 | E_val, X_val, Y_val); 10 | input clk; 11 | inout [15:0] bus; 12 | input XI_bar, YI_bar, EO_bar; 13 | input [5:0] ALU_op; 14 | output carry_out, lsb_nz1, lsb_nz2; 15 | output [7:0] E_val; 16 | output [7:0] X_val; 17 | output [7:0] Y_val; 18 | 19 | assign E_val = val; 20 | assign X_val = X; 21 | assign Y_val = Y; 22 | 23 | wire [7:0] X; 24 | wire [7:0] Y; 25 | wire [7:0] val; 26 | 27 | ALU4 alu1 (X[3:0], Y[3:0], ALU_op, 1'b0, carry1, val[3:0], lsb_nz1); 28 | ALU4 alu2 (X[7:4], Y[7:4], ALU_op, carry1, carry_out, val[7:4], lsb_nz2); 29 | 30 | ttl_74244 buflow ({EO_bar,EO_bar}, val[7:0], bus[7:0]); 31 | 32 | ttl_74377 Xreg (XI_bar, bus[7:0], clk, X[7:0]); 33 | ttl_74377 Yreg (YI_bar, bus[7:0], clk, Y[7:0]); 34 | endmodule 35 | -------------------------------------------------------------------------------- /verilog/cards-cpu.v: -------------------------------------------------------------------------------- 1 | /* CPU */ 2 | 3 | `include "cards-alu-low.v" 4 | `include "cards-alu-high.v" 5 | `include "cards-memory.v" 6 | `include "cards-instr.v" 7 | `include "ttl-alu4.v" 8 | 9 | `include "cards-cpuimpl.v" 10 | -------------------------------------------------------------------------------- /verilog/cards-memory.v: -------------------------------------------------------------------------------- 1 | /* SCAMP Memory Card 2 | 3 | Contains ROM, RAM, and address register. 4 | */ 5 | 6 | `include "ttl/7400.v" 7 | `include "ttl/7432.v" 8 | `include "ttl/74377.v" 9 | `include "ttl/at28c16.v" 10 | `include "ttl/w24512a.v" 11 | 12 | module Memory(clk, bus, MI, MO, AI_bar, AR_val); 13 | input clk; 14 | inout [15:0] bus; 15 | input MI, MO, AI_bar; 16 | output [15:0] AR_val; 17 | 18 | wire [15:0] rom_value; 19 | wire [15:0] ram_value; 20 | 21 | at28c16 #(.ROM_FILE("testrom-low.hex"), .ROM_BYTES(256)) rom1 ({3'b0, AR_val[7:0]}, bus[7:0], romen_bar, 1'b0); 22 | at28c16 #(.ROM_FILE("testrom-high.hex"), .ROM_BYTES(256)) rom2 ({3'b0, AR_val[7:0]}, bus[15:8], romen_bar, 1'b0); 23 | 24 | w24512a ram1 (AR_val, bus[7:0], 1'b0, 1'b1, load_clk_bar, ramen_bar); 25 | w24512a ram2 (AR_val, bus[15:8], 1'b0, 1'b1, load_clk_bar, ramen_bar); 26 | 27 | // we want the RAM chip if any of the first 8 bits are 1, and the ROM 28 | // chip otherwise (i.e. ROM if AR_val < 256, else RAM) 29 | ttl_7432 orer1 ({AR_val[15], AR_val[14], AR_val[13], AR_val[12]}, {AR_val[11], AR_val[10], AR_val[9], AR_val[8]}, {or1, or2, or3, or4}); 30 | ttl_7432 orer2 ({1'bZ, or5, or1, or2}, {1'bZ, or6, or3, or4}, {nc, want_ram, or5, or6}); 31 | 32 | // ramen_bar = want_ram NAND MO 33 | // want_rom = want_ram NAND want_ram = !want_ram 34 | // romen_bar = want_rom NAND MO 35 | ttl_7400 nander ({MI, MO, MO, want_ram}, {clk, want_ram, want_rom, want_ram}, {load_clk_bar, ramen_bar, romen_bar, want_rom}); 36 | 37 | ttl_74377 arlow (AI_bar, bus[7:0], clk, AR_val[7:0]); 38 | ttl_74377 arhigh (AI_bar, bus[15:8], clk, AR_val[15:8]); 39 | endmodule 40 | -------------------------------------------------------------------------------- /verilog/cards-verbose_tb.v: -------------------------------------------------------------------------------- 1 | /* CPU testbench */ 2 | `include "cards-cpu.v" 3 | 4 | module test; 5 | reg clk; 6 | reg reset_bar = 1; 7 | wire [15:0] addr; 8 | wire [15:0] bus; 9 | 10 | CPU #(.DEBUG(1)) cpu (clk, reset_bar, addr, bus, DI, DO); 11 | 12 | reg [15:0] cycle = 0; 13 | 14 | reg [15:0] outputs = 0; 15 | 16 | initial begin 17 | reset_bar = 0; clk = 0; 18 | #1 clk = 1; 19 | #1 clk = 0; #1 reset_bar = 1; 20 | 21 | /* run the CPU for 2000 cycles */ 22 | while (cycle < 2000) begin 23 | cycle = cycle + 1; 24 | 25 | #1 clk = 1; 26 | 27 | #1 if (addr == 0 && DI) begin 28 | if (bus !== outputs) $display("Bad: output ",outputs, " != ", outputs, ": ", bus); 29 | outputs = outputs + 1; 30 | end 31 | 32 | clk = 0; 33 | end 34 | 35 | $display("Got ", outputs, " outputs"); 36 | end 37 | endmodule 38 | -------------------------------------------------------------------------------- /verilog/computer.v: -------------------------------------------------------------------------------- 1 | /* CPU testbench */ 2 | `include "cpu.v" 3 | 4 | `include "ttl/mos_6551.v" 5 | 6 | module test; 7 | reg clk; 8 | reg reset_bar = 1; 9 | wire [15:0] addr; 10 | wire [15:0] bus; 11 | 12 | CPU cpu (clk, reset_bar, addr, bus, DI, DO); 13 | 14 | mos_6551 acia (clk, addr[1], !(DI | DO), reset_bar, {addr[3],addr[2]}, DO, bus[7:0]); 15 | 16 | reg [15:0] cycle = 0; 17 | 18 | initial begin 19 | reset_bar = 0; clk = 0; 20 | #1 clk = 1; 21 | #1 clk = 0; reset_bar = 1; 22 | 23 | /* run the CPU for 3000 cycles */ 24 | while (cycle < 3000) begin 25 | cycle = cycle + 1; 26 | 27 | #1 clk = 1; 28 | 29 | #1 clk = 0; 30 | end 31 | end 32 | endmodule 33 | -------------------------------------------------------------------------------- /verilog/cpu.v: -------------------------------------------------------------------------------- 1 | /* CPU */ 2 | 3 | `include "alu.v" 4 | `include "control.v" 5 | `include "ucode.v" 6 | `include "fr.v" 7 | `include "ir.v" 8 | `include "memory.v" 9 | `include "pc.v" 10 | `include "tstate.v" 11 | `include "register.v" 12 | 13 | `include "cpuimpl.v" 14 | -------------------------------------------------------------------------------- /verilog/cpu_tb.v: -------------------------------------------------------------------------------- 1 | /* CPU testbench */ 2 | `include "cpu.v" 3 | 4 | module test; 5 | reg clk; 6 | reg reset_bar = 1; 7 | wire [15:0] addr; 8 | wire [15:0] bus; 9 | 10 | CPU cpu (clk, reset_bar, addr, bus, DI, DO); 11 | 12 | reg [15:0] cycle = 0; 13 | 14 | parameter EXPECT_OUTPUTS = 25; 15 | reg [15:0] outputs = 0; 16 | 17 | initial begin 18 | reset_bar = 0; clk = 0; 19 | #1 clk = 1; 20 | #1 clk = 0; reset_bar = 1; 21 | 22 | #100 23 | 24 | /* run the CPU for 3000 cycles */ 25 | while (cycle < 3000) begin 26 | cycle = cycle + 1; 27 | 28 | #1 clk = 1; 29 | 30 | #1 if (addr == 0 && DI) begin 31 | if (bus !== outputs) $display("Bad: output ",outputs, " != ", outputs, ": ", bus); 32 | outputs = outputs + 1; 33 | end 34 | 35 | clk = 0; 36 | end 37 | 38 | if (outputs !== EXPECT_OUTPUTS) $display("Bad: got ", outputs, " outputs, expected ", EXPECT_OUTPUTS); 39 | end 40 | endmodule 41 | -------------------------------------------------------------------------------- /verilog/fpga-alu.v: -------------------------------------------------------------------------------- 1 | /* Nand2Tetris ALU, but with zx/zy inverted 2 | 3 | This ALU is purely combinational. 4 | 5 | X,Y are 16-bit inputs 6 | 7 | C is 6 control bits: 8 | 5 4 3 2 1 0 9 | ex nx ey ny f no 10 | 11 | ex,ey: enable the respective operand (instead of using 0) 12 | nx,ny: invert the bits of the operand (applied after ex,ey) 13 | f: function select: 0 for '&', 1 for '+' 14 | no: invert the bits of the output 15 | 16 | Output to bus is enabled when en_bar is low. Output to val always. 17 | */ 18 | module ALU(X, Y, C, en_bar, bus, val, Z_flag, LT_flag); 19 | input [15:0] X; 20 | input [15:0] Y; 21 | input [5:0] C; 22 | input en_bar; 23 | output [15:0] bus; 24 | output [15:0] val; 25 | output Z_flag, LT_flag; 26 | 27 | assign {ex,nx,ey,ny,f,no} = C; 28 | 29 | wire [15:0] inx; 30 | wire [15:0] iny; 31 | wire [15:0] argx; 32 | wire [15:0] argy; 33 | wire [15:0] fxy; 34 | 35 | assign inx = ex ? X : 0; 36 | assign argx = nx ? ~inx : inx; 37 | assign iny = ey ? Y : 0; 38 | assign argy = ny ? ~iny : iny; 39 | 40 | assign fxy = f ? (argx+argy) : (argx&argy); 41 | 42 | assign val = no ? ~fxy : fxy; 43 | 44 | assign Z_flag = (val == 0); 45 | assign LT_flag = val[15]; 46 | endmodule 47 | -------------------------------------------------------------------------------- /verilog/fpga-cpu.v: -------------------------------------------------------------------------------- 1 | /* CPU */ 2 | 3 | `include "fpga-alu.v" 4 | `include "control.v" 5 | `include "fpga-ucode.v" 6 | `include "fr.v" 7 | `include "fpga-ir.v" 8 | `include "fpga-memory.v" 9 | `include "fpga-pc.v" 10 | `include "fpga-tstate.v" 11 | `include "register.v" 12 | 13 | `include "fpga-cpuimpl.v" 14 | -------------------------------------------------------------------------------- /verilog/fpga-ir.v: -------------------------------------------------------------------------------- 1 | /* Instruction register 2 | 3 | When "enl" is 1, gives val&0xff on to bus 4 | When "enh" is 1, gives 0xff00 + (val&0xff) on to bus 5 | When "load" is 1 and clock edge rises, takes in new value from the bus 6 | Always gives current value to 'value' 7 | */ 8 | module IR(clk, bus, load_bar, enl_bar, enh_bar, value); 9 | input clk; 10 | inout [15:0] bus; 11 | input load_bar; 12 | input enl_bar; 13 | input enh_bar; 14 | output [15:0] value; 15 | 16 | reg [15:0] val = 0; 17 | 18 | assign load = !load_bar; 19 | assign enl = !enl_bar; 20 | assign enh = !enh_bar; 21 | 22 | assign value = val; 23 | 24 | always @ (posedge clk) begin 25 | if (load) val <= bus; 26 | end 27 | endmodule 28 | -------------------------------------------------------------------------------- /verilog/fpga-memory.v: -------------------------------------------------------------------------------- 1 | /* Memory 2 | 3 | When "en" is 1, gives current value to the bus 4 | When "load" is 1 and clock edge rises, RAM takes in new value from the bus 5 | Always gives current value to 'value' 6 | */ 7 | 8 | `include "fpga-rom.v" 9 | `include "fpga-ram.v" 10 | 11 | module Memory(clk, bus, load, en, address, value); 12 | input clk; 13 | input [15:0] bus; 14 | input load; 15 | input en; 16 | input [15:0] address; 17 | output [15:0] value; 18 | 19 | wire [15:0] rom_value; 20 | wire [15:0] ram_value; 21 | 22 | ROM rom (clk, address[7:0], rom_value); 23 | RAM ram (clk, bus, !load, address, ram_value); 24 | 25 | assign value = address < 256 ? rom_value : ram_value; 26 | endmodule 27 | -------------------------------------------------------------------------------- /verilog/fpga-pc.v: -------------------------------------------------------------------------------- 1 | /* Program Counter */ 2 | 3 | module PC(clk, bus, load_bar, en_bar, value, inc, reset_bar); 4 | input clk; 5 | inout [15:0] bus; 6 | input load_bar; 7 | input en_bar; 8 | output [15:0] value; 9 | input inc; 10 | input reset_bar; 11 | 12 | assign load = !load_bar; 13 | assign en = !en_bar; 14 | 15 | reg [15:0] val; 16 | 17 | assign value = val; 18 | 19 | always @ (posedge clk or negedge reset_bar) begin 20 | if (reset_bar == 0) val <= 0; 21 | else if (load) val <= bus; 22 | else if (inc) val <= val + 1; 23 | end 24 | endmodule 25 | -------------------------------------------------------------------------------- /verilog/fpga-ram.v: -------------------------------------------------------------------------------- 1 | /* RAM 2 | 3 | When "en" is 1, gives current value to the bus 4 | When "load" is 1 and clock edge rises, takes in new value from the bus 5 | Always gives current value to 'value' 6 | */ 7 | 8 | module RAM(clk, in, load_bar, address, value); 9 | input clk; 10 | input [15:0] in; 11 | input load_bar; 12 | input [15:0] address; 13 | output [15:0] value; 14 | 15 | reg [15:0] ram [0:255]; 16 | 17 | reg [15:0] out; 18 | assign value = out; 19 | 20 | always @ (posedge clk) begin 21 | if (!load_bar) ram[address[7:0]] <= in; 22 | out <= ram[address[7:0]]; 23 | end 24 | endmodule 25 | -------------------------------------------------------------------------------- /verilog/fpga-rom.v: -------------------------------------------------------------------------------- 1 | /* Boot ROM */ 2 | 3 | module ROM(clk, address, value); 4 | input clk; 5 | input [7:0] address; 6 | output [15:0] value; 7 | 8 | reg [15:0] rom [0:255]; 9 | 10 | initial begin 11 | $readmemh("bootrom.hex", rom); 12 | end 13 | 14 | reg [15:0] out; 15 | assign value = out; 16 | 17 | always @ (posedge clk) begin 18 | out <= rom[address]; 19 | end 20 | endmodule 21 | -------------------------------------------------------------------------------- /verilog/fpga-tstate.v: -------------------------------------------------------------------------------- 1 | /* T-state counter 2 | 3 | Counts up on the *negative* edge of the clock 4 | */ 5 | 6 | module TState (clk, reset1, reset2_bar, T); 7 | input clk; 8 | input reset1, reset2_bar; 9 | output [2:0] T; 10 | 11 | reg [2:0] Treg; 12 | 13 | assign T = Treg; 14 | 15 | // strictly, this should be: 16 | // always @ (negedge clk or posedge reset1 or negedge reset2_bar) begin 17 | // but yosys won't allow it :( 18 | always @ (negedge clk) begin 19 | if (reset1 || !reset2_bar) Treg <= 0; 20 | else Treg <= Treg + 1; 21 | end 22 | endmodule 23 | -------------------------------------------------------------------------------- /verilog/fpga-ucode.v: -------------------------------------------------------------------------------- 1 | /* Ucode: Turn an instruction into a microinstruction 2 | 3 | T0: PO AI 4 | T1: MO II P+ 5 | T2+: look in DecodeROM at {instr[15:8],T} 6 | */ 7 | 8 | module Ucode(clk, instr, T, uinstr); 9 | input clk; 10 | input [15:0] instr; 11 | input [2:0] T; 12 | output reg [15:0] uinstr; 13 | 14 | reg [15:0] rom [0:2047]; 15 | 16 | wire [10:0] addr; 17 | assign addr = {instr[15:8], T}; 18 | 19 | initial begin 20 | $readmemh("ucode.hex", rom); 21 | end 22 | 23 | always @ (posedge clk) begin 24 | uinstr <= rom[addr]; 25 | end 26 | endmodule 27 | -------------------------------------------------------------------------------- /verilog/fpga_tb.v: -------------------------------------------------------------------------------- 1 | /* CPU testbench */ 2 | `include "fpga-cpu.v" 3 | 4 | module test; 5 | reg clk, clk90; 6 | reg reset_bar = 1; 7 | wire [15:0] addr; 8 | wire [15:0] bus; 9 | 10 | wire [15:0] PC_val; 11 | wire [15:0] busin; 12 | 13 | CPU cpu (clk, clk90, reset_bar, addr, bus, busin, DI, DO, PC_val); 14 | 15 | reg [15:0] cycle = 0; 16 | 17 | parameter EXPECT_OUTPUTS = 25; 18 | reg [15:0] outputs = 0; 19 | 20 | initial begin 21 | reset_bar = 0; clk90 = 0; clk = 0; 22 | #1 clk = 1; 23 | #1 clk = 0; reset_bar = 1; 24 | 25 | /* run the CPU for 2000 cycles */ 26 | while (cycle < 2000) begin 27 | cycle = cycle + 1; 28 | 29 | #1 clk90 = 1; 30 | #1 clk = 1; 31 | 32 | #1 if (addr == 0 && DI) begin 33 | if (bus !== outputs) $display("Bad: output ",outputs, " != ", outputs, ": ", bus); 34 | outputs = outputs + 1; 35 | end 36 | 37 | #1 clk90 = 0; 38 | #1 clk = 0; 39 | end 40 | 41 | if (outputs !== EXPECT_OUTPUTS) $display("Bad: got ", outputs, " outputs, expected ", EXPECT_OUTPUTS); 42 | end 43 | endmodule 44 | -------------------------------------------------------------------------------- /verilog/fpgacpu.v: -------------------------------------------------------------------------------- 1 | /* CPU */ 2 | 3 | `include "alu.v" 4 | `include "control.v" 5 | `include "ucode.v" 6 | `include "fr.v" 7 | `include "ir.v" 8 | `include "memory.v" 9 | `include "pc.v" 10 | `include "tstate.v" 11 | `include "register.v" 12 | 13 | `include "cpuimpl.v" 14 | -------------------------------------------------------------------------------- /verilog/fr.v: -------------------------------------------------------------------------------- 1 | /* Flags register 2 | 3 | Loads content if "load", on rising edge of clock 4 | */ 5 | 6 | module FR(clk, in, load_bar, out); 7 | input clk; 8 | input [1:0] in; 9 | input load_bar; 10 | output [1:0] out; 11 | 12 | reg [1:0] val = 0; 13 | 14 | assign out = val; 15 | 16 | always @ (posedge clk) begin 17 | if (!load_bar) val <= in; 18 | end 19 | endmodule 20 | -------------------------------------------------------------------------------- /verilog/fr_tb.v: -------------------------------------------------------------------------------- 1 | /* Flags register testbench */ 2 | `include "fr.v" 3 | 4 | module test; 5 | reg clk; 6 | 7 | reg [1:0] in; 8 | wire [1:0] out; 9 | reg load; 10 | 11 | assign load_bar = !load; 12 | 13 | FR fr (clk, in, load_bar, out); 14 | 15 | initial begin 16 | clk = 0; 17 | #1 18 | in = 3'b01; 19 | #1 if (out === 3'b01) $display("Bad: loaded value without load or posedge"); 20 | load = 1; 21 | #1 if (out === 3'b01) $display("Bad: loaded value without posedge"); 22 | clk = 1; 23 | #1 if (out !== 3'b01) $display("Bad: didn't load value at posedge,",out); 24 | clk = 0; 25 | in = 0; load = 0; 26 | #1 if (out !== 3'b01) $display("Bad: lost value without load or posedge,",out); 27 | clk = 1; 28 | #1 if (out != 3'b01) $display("Bad: lost value without load,",out); 29 | clk = 0; 30 | #1 if (out != 3'b01) $display("Bad: lost value at negedge,",out); 31 | load = 1; 32 | #1 33 | clk = 1; 34 | #1 if (out != 0) $display("Bad: didn't load value at posedge (2nd time),",out); 35 | end 36 | endmodule 37 | -------------------------------------------------------------------------------- /verilog/iceFUN.pcf: -------------------------------------------------------------------------------- 1 | # For iceFUN board 2 | 3 | set_io --warn-no-port led1 C10 4 | set_io --warn-no-port led2 A10 5 | set_io --warn-no-port led3 D7 6 | set_io --warn-no-port led4 D6 7 | set_io --warn-no-port led5 A7 8 | set_io --warn-no-port led6 C7 9 | set_io --warn-no-port led7 A4 10 | set_io --warn-no-port led8 C4 11 | set_io --warn-no-port lcol1 A12 12 | set_io --warn-no-port lcol2 D10 13 | set_io --warn-no-port lcol3 A6 14 | set_io --warn-no-port lcol4 C5 15 | set_io --warn-no-port clk P7 16 | set_io --warn-no-port key1 A5 17 | set_io --warn-no-port key2 A11 18 | set_io --warn-no-port key3 C6 19 | set_io --warn-no-port key4 C11 20 | -------------------------------------------------------------------------------- /verilog/ir.v: -------------------------------------------------------------------------------- 1 | /* Instruction register 2 | 3 | When "enl" is 1, gives val&0xff on to bus 4 | When "enh" is 1, gives 0xff00 + (val&0xff) on to bus 5 | When "load" is 1 and clock edge rises, takes in new value from the bus 6 | Always gives current value to 'value' 7 | */ 8 | module IR(clk, bus, load_bar, enl_bar, enh_bar, value); 9 | input clk; 10 | inout [15:0] bus; 11 | input load_bar; 12 | input enl_bar; 13 | input enh_bar; 14 | output [15:0] value; 15 | 16 | reg [15:0] val = 0; 17 | 18 | assign load = !load_bar; 19 | assign enl = !enl_bar; 20 | assign enh = !enh_bar; 21 | 22 | assign bus = enl ? (16'h0000 | (val&8'hff)) : (enh ? (16'hff00 | (val&8'hff)) : 16'hZZZZ); 23 | assign value = val; 24 | 25 | always @ (posedge clk) begin 26 | if (load) val <= bus; 27 | end 28 | endmodule 29 | -------------------------------------------------------------------------------- /verilog/ir_tb.v: -------------------------------------------------------------------------------- 1 | /* Instruction register testbench */ 2 | `include "ir.v" 3 | 4 | module test; 5 | reg clk; 6 | wire [15:0] bus; 7 | reg load; 8 | reg enl, enh; 9 | wire [15:0] value; 10 | 11 | reg [15:0] busreg; 12 | 13 | assign bus = (enl | enh) ? 16'hZZZZ : busreg; 14 | 15 | assign load_bar = !load; 16 | assign enl_bar = !enl; 17 | assign enh_bar = !enh; 18 | 19 | IR ir (clk, bus, load_bar, enl_bar, enh_bar, value); 20 | 21 | initial begin 22 | clk = 0; 23 | #1 24 | busreg = 40400; load = 1; enl = 0; enh = 0; 25 | #1 26 | clk = 1; 27 | #1 28 | busreg = 0; load = 0; enl = 1; 29 | #1 if (value !== 40400) $display("Bad: value didn't update on clock rising edge,", value); 30 | 31 | clk = 0; 32 | #1 33 | enl = 1; load = 0; 34 | #1 if (bus !== 208) $display("Bad: enl doesn't drive bus,",bus); 35 | 36 | clk = 1; 37 | #1 38 | enl = 0; load = 0; 39 | #1 if (bus === 40400) $display("Bad: bus driven even without enl,",bus); 40 | 41 | clk = 0; 42 | #1 43 | busreg = 65535; load = 1; enl = 1; 44 | #1 45 | clk = 1; 46 | #1 if (bus !== 208) $display("Bad: loading with enl enabled shouldn't do anything,",bus); 47 | 48 | clk = 0; 49 | #1 50 | busreg = 65535; load = 1; enl = 0; 51 | #1 52 | clk = 1; 53 | #1 if (bus !== 65535) $display("Bad: loading 65535 didn't work",bus); 54 | end 55 | endmodule 56 | -------------------------------------------------------------------------------- /verilog/ledscan.v: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright(C) 2018 Gerald Coe, Devantech Ltd 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any purpose with or 6 | * without fee is hereby granted, provided that the above copyright notice and 7 | * this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO 10 | * THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 11 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 13 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | * 16 | */ 17 | 18 | // LedScan takes the four led columns as inputs and outputs them to the led matrix 19 | 20 | module LedScan ( 21 | input clk12MHz, 22 | input [7:0] leds1, 23 | input [7:0] leds2, 24 | input [7:0] leds3, 25 | input [7:0] leds4, 26 | output reg [7:0] leds, 27 | output reg [3:0] lcol 28 | ); 29 | 30 | 31 | /* Counter register */ 32 | reg [11:0] timer = 12'b0; 33 | 34 | 35 | always @ (posedge clk12MHz) begin 36 | case (timer[11:10]) 37 | 2'b00: begin 38 | leds[7:0] <= leds1[7:0]; 39 | lcol[3:0] <= 4'b1110; 40 | end 41 | 2'b01: begin 42 | leds[7:0] <= leds2[7:0]; 43 | lcol[3:0] <= 4'b1101; 44 | end 45 | 2'b10: begin 46 | leds[7:0] <= leds3[7:0]; 47 | lcol[3:0] <= 4'b1011; 48 | end 49 | 2'b11: begin 50 | leds[7:0] <= leds4[7:0]; 51 | lcol[3:0] <= 4'b0111; 52 | end 53 | endcase 54 | end 55 | 56 | 57 | // increment the scan timer 58 | always @ (posedge clk12MHz) begin 59 | timer <= timer + 1; 60 | end 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /verilog/memory.v: -------------------------------------------------------------------------------- 1 | /* Memory 2 | 3 | When "en" is 1, gives current value to the bus 4 | When "load" is 1 and clock edge rises, RAM takes in new value from the bus 5 | Always gives current value to 'value' 6 | */ 7 | 8 | `include "rom.v" 9 | `include "ram.v" 10 | 11 | module Memory(clk, bus, load, en, address); 12 | input clk; 13 | inout [15:0] bus; 14 | input load; 15 | input en; 16 | input [15:0] address; 17 | 18 | wire [15:0] rom_value; 19 | wire [15:0] ram_value; 20 | 21 | ROM rom (address[7:0], rom_value); 22 | RAM ram (clk, bus, !load, address, ram_value); 23 | 24 | wire [15:0] value; 25 | 26 | assign value = address < 256 ? rom_value : ram_value; 27 | assign bus = en ? value : 16'bZ; 28 | endmodule 29 | -------------------------------------------------------------------------------- /verilog/pc.v: -------------------------------------------------------------------------------- 1 | /* Program Counter */ 2 | 3 | module PC(clk, bus, load_bar, en_bar, value, inc, reset_bar); 4 | input clk; 5 | inout [15:0] bus; 6 | input load_bar; 7 | input en_bar; 8 | output [15:0] value; 9 | input inc; 10 | input reset_bar; 11 | 12 | assign load = !load_bar; 13 | assign en = !en_bar; 14 | 15 | reg [15:0] val; 16 | 17 | assign bus = en ? val : 16'hZZZZ; 18 | assign value = val; 19 | 20 | always @ (posedge clk or negedge reset_bar) begin 21 | if (reset_bar == 0) val <= 0; 22 | else if (load) val <= bus; 23 | else if (inc) val <= val + 1; 24 | end 25 | endmodule 26 | -------------------------------------------------------------------------------- /verilog/ram.v: -------------------------------------------------------------------------------- 1 | /* RAM 2 | 3 | When "en" is 1, gives current value to the bus 4 | When "load" is 1 and clock edge rises, takes in new value from the bus 5 | Always gives current value to 'value' 6 | */ 7 | 8 | module RAM(clk, in, load_bar, address, value); 9 | input clk; 10 | input [15:0] in; 11 | input load_bar; 12 | input [15:0] address; 13 | output [15:0] value; 14 | 15 | reg [15:0] ram [0:65535]; 16 | 17 | assign value = ram[address]; 18 | 19 | always @ (posedge clk) begin 20 | if (!load_bar) ram[address] <= in; 21 | end 22 | endmodule 23 | -------------------------------------------------------------------------------- /verilog/register.v: -------------------------------------------------------------------------------- 1 | /* General-purpose register for TTL CPU 2 | 3 | When "en" is 1, gives current value to the bus 4 | When "load" is 1 and clock edge rises, takes in new value from the bus 5 | Always gives current value to 'value' 6 | */ 7 | module Register(clk, bus, load_bar, value); 8 | input clk; 9 | input [15:0] bus; 10 | input load_bar; 11 | output [15:0] value; 12 | 13 | reg [15:0] val = 0; 14 | 15 | assign load = !load_bar; 16 | 17 | assign value = val; 18 | 19 | always @ (posedge clk) begin 20 | if (load) val <= bus; 21 | end 22 | endmodule 23 | -------------------------------------------------------------------------------- /verilog/register_tb.v: -------------------------------------------------------------------------------- 1 | /* Register testbench */ 2 | `include "register.v" 3 | 4 | module test; 5 | reg clk; 6 | reg load; 7 | wire [15:0] value; 8 | 9 | reg [15:0] bus; 10 | 11 | assign load_bar = !load; 12 | 13 | Register register (clk, bus, load_bar, value); 14 | 15 | initial begin 16 | clk = 0; 17 | #1 18 | bus = 40400; load = 1; 19 | #1 20 | clk = 1; 21 | #1 22 | bus = 0; load = 0; 23 | #1 if (value !== 40400) $display("Bad: value didn't update on clock rising edge,", value); 24 | 25 | clk = 0; 26 | #1 27 | bus = 65535; load = 1; 28 | #1 29 | clk = 1; 30 | #1 if (value !== 65535) $display("Bad: loading 65535 didn't work,",value); 31 | 32 | clk = 0; 33 | #1 34 | bus = 34567; load = 1; 35 | #1 if (value != 65535) $display("Bad: value updated without a rising edge,",value); 36 | 37 | clk = 0; 38 | bus = 10101; load = 1; 39 | #100 if (value != 65535) $display("Bad: value updated without clock rising edge,",value); 40 | clk = 1; 41 | #1 if (value != 10101) $display("Bad: value didn't update on 2nd clock rising edge,",value); 42 | end 43 | endmodule 44 | -------------------------------------------------------------------------------- /verilog/rom.v: -------------------------------------------------------------------------------- 1 | /* Boot ROM */ 2 | 3 | module ROM(address, value); 4 | input [7:0] address; 5 | output [15:0] value; 6 | 7 | reg [15:0] rom [0:255]; 8 | 9 | initial begin 10 | $readmemh("testrom.hex", rom); 11 | end 12 | 13 | assign value = rom[address]; 14 | endmodule 15 | -------------------------------------------------------------------------------- /verilog/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TESTS="register pc control tstate ir fr memory alu cpu" 4 | 5 | if [ "$1" ]; then 6 | TESTS=$1 7 | fi 8 | 9 | for t in $TESTS; do 10 | echo $t... 11 | iverilog ${t}_tb.v 12 | ./a.out 13 | rm -f a.out 14 | 15 | echo ttl-$t... 16 | cat ${t}_tb.v | sed "s/include \"${t}.v\"/include \"ttl-${t}.v\"/" > ttl-${t}_tb.v 17 | iverilog ttl-${t}_tb.v 18 | ./a.out 19 | rm -f ttl-${t}_tb.v a.out 20 | done 21 | 22 | if [ ! "$1" ]; then 23 | echo verbose... 24 | t=verbose 25 | 26 | iverilog ${t}_tb.v 27 | ./a.out > out 28 | rm -f a.out 29 | cat ${t}_tb.v | sed "s/include \"cpu.v\"/include \"ttl-cpu.v\"/" > ttl-${t}_tb.v 30 | iverilog ttl-${t}_tb.v 31 | ./a.out > ttl-out 32 | rm -f ttl-${t}_tb.v a.out 33 | 34 | diff -u out ttl-out 35 | 36 | echo computer... 37 | iverilog computer.v 38 | ./a.out 39 | rm -f a.out 40 | fi 41 | -------------------------------------------------------------------------------- /verilog/testrom-high.hex: -------------------------------------------------------------------------------- 1 | ../testrom-high.hex -------------------------------------------------------------------------------- /verilog/testrom-low.hex: -------------------------------------------------------------------------------- 1 | ../testrom-low.hex -------------------------------------------------------------------------------- /verilog/testrom.hex: -------------------------------------------------------------------------------- 1 | ../testrom.hex -------------------------------------------------------------------------------- /verilog/top.v: -------------------------------------------------------------------------------- 1 | `include "ttl-cpu.v" 2 | 3 | module top(clk); 4 | input clk; 5 | 6 | wire [15:0] addr; 7 | wire [15:0] bus; 8 | 9 | CPU cpu(clk, 1'b1, addr, bus, DI, DO); 10 | 11 | endmodule 12 | -------------------------------------------------------------------------------- /verilog/tstate.v: -------------------------------------------------------------------------------- 1 | /* T-state counter 2 | 3 | Counts up on the *negative* edge of the clock 4 | */ 5 | 6 | module TState (clk, reset1, reset2_bar, T); 7 | input clk; 8 | input reset1, reset2_bar; 9 | output [2:0] T; 10 | 11 | reg [2:0] Treg; 12 | 13 | assign T = Treg; 14 | 15 | always @ (negedge clk or posedge reset1 or negedge reset2_bar) begin 16 | if (reset1 || !reset2_bar) Treg <= 0; 17 | else Treg <= Treg + 1; 18 | end 19 | endmodule 20 | -------------------------------------------------------------------------------- /verilog/ttl-alu.v: -------------------------------------------------------------------------------- 1 | /* Nand2Tetris ALU, but with zx/zy inverted 2 | 3 | This ALU is purely combinational. 4 | 5 | X,Y are 16-bit inputs 6 | 7 | C is 6 control bits: 8 | 5 4 3 2 1 0 9 | ex nx ey ny f no 10 | 11 | ex,ey: enable the respective operand (instead of using 0) 12 | nx,ny: invert the bits of the operand (applied after ex,ey) 13 | f: function select: 0 for '&', 1 for '+' 14 | no: invert the bits of the output 15 | 16 | Output to bus is enabled when en_bar is lo. Output to val always. 17 | */ 18 | 19 | `include "ttl/7402.v" 20 | `include "ttl/7432.v" 21 | `include "ttl/74244.v" 22 | `include "ttl-alu4.v" 23 | 24 | module ALU(X, Y, C, en_bar, bus, val, Z_flag, LT_flag); 25 | input [15:0] X; 26 | input [15:0] Y; 27 | input [5:0] C; 28 | input en_bar; 29 | output [15:0] bus; 30 | output [15:0] val; 31 | output Z_flag, LT_flag; 32 | 33 | ALU4 alu1 (X[3:0], Y[3:0], C, 1'b0, carry1, val[3:0], nonzero1); 34 | ALU4 alu2 (X[7:4], Y[7:4], C, carry1, carry2, val[7:4], nonzero2); 35 | ALU4 alu3 (X[11:8], Y[11:8], C, carry2, carry3, val[11:8], nonzero3); 36 | ALU4 alu4 (X[15:12], Y[15:12], C, carry3, nc, val[15:12], nonzero4); 37 | 38 | ttl_74244 buflow ({en_bar,en_bar}, val[7:0], bus[7:0]); 39 | ttl_74244 bufhigh ({en_bar,en_bar}, val[15:8], bus[15:8]); 40 | 41 | assign LT_flag = val[15]; 42 | 43 | ttl_7432 orer ({1'bZ, nonzero1, nonzero2, or1}, {1'bZ, nonzero3, nonzero4, or2}, {nc, or1, or2, nonzero}); 44 | ttl_7402 norer ({3'bZ, nonzero}, {3'bZ, nonzero}, {nc,nc,nc, Z_flag}); 45 | endmodule 46 | -------------------------------------------------------------------------------- /verilog/ttl-alu4.v: -------------------------------------------------------------------------------- 1 | /* 4-bit slice of Nand2Tetris ALU, but with zx/zy inverted 2 | 3 | This ALU is purely combinational. 4 | 5 | X,Y are 4-bit inputs 6 | 7 | C is 6 control bits: 8 | 5 4 3 2 1 0 9 | ex nx ey ny f no 10 | 11 | ex,ey: enable the respective operand (instead of using 0) 12 | nx,ny: invert the bits of the operand (applied after ex,ey) 13 | f: function select: 0 for '&', 1 for '+' 14 | no: invert the bits of the output 15 | */ 16 | 17 | `include "ttl/7408.v" 18 | `include "ttl/7432.v" 19 | `include "ttl/7486.v" 20 | `include "ttl/74157.v" 21 | `include "ttl/74283.v" 22 | 23 | module ALU4(X, Y, C, carry_in, carry_out, out, NZ_flag); 24 | input [3:0] X; 25 | input [3:0] Y; 26 | input [5:0] C; 27 | input carry_in; 28 | output carry_out; 29 | output [3:0] out; 30 | output NZ_flag; 31 | 32 | assign {ex,nx,ey,ny,f,no} = C; 33 | 34 | wire [3:0] inx; 35 | wire [3:0] iny; 36 | wire [3:0] argx; 37 | wire [3:0] argy; 38 | wire [3:0] val; 39 | wire [3:0] add_result; 40 | wire [3:0] and_result; 41 | 42 | ttl_7408 andx ({ex,ex,ex,ex}, X, inx); 43 | ttl_7408 andy ({ey,ey,ey,ey}, Y, iny); 44 | 45 | ttl_7486 xorx ({nx,nx,nx,nx}, inx, argx); 46 | ttl_7486 xory ({ny,ny,ny,ny}, iny, argy); 47 | 48 | ttl_74283 adder (argx, argy, carry_in, add_result, carry_out); 49 | ttl_7408 ander (argx, argy, and_result); 50 | 51 | ttl_74157 mux (1'b0, f, and_result, add_result, val); 52 | ttl_7486 outputxor ({no,no,no,no}, val, out); 53 | 54 | ttl_7432 orer ({out[0],out[1],or1,1'bZ},{out[2],out[3],or2,1'bZ},{or1,or2,NZ_flag,nc}); 55 | endmodule 56 | -------------------------------------------------------------------------------- /verilog/ttl-cpu.v: -------------------------------------------------------------------------------- 1 | /* CPU */ 2 | 3 | `include "ttl-alu.v" 4 | `include "ttl-control.v" 5 | `include "ttl-ucode.v" 6 | `include "ttl-fr.v" 7 | `include "ttl-ir.v" 8 | `include "ttl-memory.v" 9 | `include "ttl-pc.v" 10 | `include "ttl-tstate.v" 11 | `include "ttl-register.v" 12 | 13 | `include "cpuimpl.v" 14 | -------------------------------------------------------------------------------- /verilog/ttl-fr.v: -------------------------------------------------------------------------------- 1 | /* Flags register 2 | 3 | Loads content if "load", on rising edge of clock 4 | */ 5 | 6 | `include "ttl/74377.v" 7 | 8 | module FR(clk, in, load_bar, out); 9 | input clk; 10 | input [1:0] in; 11 | input load_bar; 12 | output [1:0] out; 13 | 14 | ttl_74377 register (load_bar, {6'bZ, in}, clk, {nc,nc,nc,nc,nc,nc, out}); 15 | endmodule 16 | -------------------------------------------------------------------------------- /verilog/ttl-ir.v: -------------------------------------------------------------------------------- 1 | /* Instruction register 2 | 3 | When "enl" is 1, gives val&0xff on to bus 4 | When "enh" is 1, gives 0xff00 + (val&0xff) on to bus 5 | When "load" is 1 and clock edge rises, takes in new value from the bus 6 | Always gives current value to 'value' 7 | */ 8 | 9 | `include "ttl/74244.v" 10 | `include "ttl/74377.v" 11 | 12 | module IR(clk, bus, load_bar, enl_bar, enh_bar, value); 13 | input clk; 14 | inout [15:0] bus; 15 | input load_bar; 16 | input enl_bar, enh_bar; 17 | output [15:0] value; 18 | 19 | wire load_bar; 20 | wire nc; 21 | 22 | ttl_74244 outbuflow1 ({enl_bar,enl_bar}, value[7:0], bus[7:0]); 23 | ttl_74244 outbufhigh1 ({enl_bar,enl_bar}, 8'h00, bus[15:8]); 24 | 25 | ttl_74244 outbuflow2 ({enh_bar,enh_bar}, value[7:0], bus[7:0]); 26 | ttl_74244 outbufhigh2 ({enh_bar,enh_bar}, 8'hff, bus[15:8]); 27 | 28 | ttl_74377 reglow (load_bar, bus[7:0], clk, value[7:0]); 29 | ttl_74377 reghigh (load_bar, bus[15:8], clk, value[15:8]); 30 | endmodule 31 | -------------------------------------------------------------------------------- /verilog/ttl-memory.v: -------------------------------------------------------------------------------- 1 | /* Memory 2 | 3 | When "en" is 1, gives current value to the bus 4 | When "load" is 1 and clock edge rises, RAM takes in new value from the bus 5 | */ 6 | 7 | `include "ttl/7400.v" 8 | `include "ttl/7432.v" 9 | `include "ttl/at28c16.v" 10 | `include "ttl/w24512a.v" 11 | 12 | module Memory(clk, bus, load, en, address); 13 | input clk; 14 | inout [15:0] bus; 15 | input load; 16 | input en; 17 | input [15:0] address; 18 | 19 | at28c16 #(.ROM_FILE("testrom-low.hex"), .ROM_BYTES(256)) rom1 ({3'b0, address[7:0]}, bus[7:0], romen_bar, 1'b0); 20 | at28c16 #(.ROM_FILE("testrom-high.hex"), .ROM_BYTES(256)) rom2 ({3'b0, address[7:0]}, bus[15:8], romen_bar, 1'b0); 21 | 22 | w24512a ram1 (address, bus[7:0], 1'b0, 1'b1, load_clk_bar, ramen_bar); 23 | w24512a ram2 (address, bus[15:8], 1'b0, 1'b1, load_clk_bar, ramen_bar); 24 | 25 | // we want the RAM chip if any of the first 8 bits are 1, and the ROM 26 | // chip otherwise (i.e. ROM if address < 256, else RAM) 27 | ttl_7432 orer1 ({address[15], address[14], address[13], address[12]}, {address[11], address[10], address[9], address[8]}, {or1, or2, or3, or4}); 28 | ttl_7432 orer2 ({1'bZ, or5, or1, or2}, {1'bZ, or6, or3, or4}, {nc, want_ram, or5, or6}); 29 | 30 | // ramen_bar = want_ram NAND en 31 | // want_rom = want_ram NAND want_ram = !want_ram 32 | // romen_bar = want_rom NAND en 33 | ttl_7400 nander ({load, en, en, want_ram}, {clk, want_ram, want_rom, want_ram}, {load_clk_bar, ramen_bar, romen_bar, want_rom}); 34 | endmodule 35 | -------------------------------------------------------------------------------- /verilog/ttl-pc.v: -------------------------------------------------------------------------------- 1 | /* Program Counter */ 2 | 3 | `include "ttl/74161.v" 4 | `include "ttl/74244.v" 5 | 6 | module PC(clk, bus, load_bar, en_bar, value, inc, reset_bar); 7 | input clk; 8 | inout [15:0] bus; 9 | input load_bar; 10 | input en_bar; 11 | output [15:0] value; 12 | input inc; 13 | input reset_bar; 14 | 15 | ttl_74244 outbuflow ({en_bar,en_bar}, value[7:0], bus[7:0]); 16 | ttl_74244 outbufhigh ({en_bar,en_bar}, value[15:8], bus[15:8]); 17 | 18 | ttl_74161 counter1 (reset_bar, load_bar, inc, inc, bus[3:0], clk, RCO1, value[3:0]); 19 | ttl_74161 counter2 (reset_bar, load_bar, RCO1, inc, bus[7:4], clk, RCO2, value[7:4]); 20 | ttl_74161 counter3 (reset_bar, load_bar, RCO2, inc, bus[11:8], clk, RCO3, value[11:8]); 21 | ttl_74161 counter4 (reset_bar, load_bar, RCO3, inc, bus[15:12], clk, RCO4, value[15:12]); 22 | endmodule 23 | -------------------------------------------------------------------------------- /verilog/ttl-register.v: -------------------------------------------------------------------------------- 1 | /* General-purpose 16-bit register for TTL CPU 2 | 3 | Likely to be used for: 4 | X register, Y register 5 | 6 | When "en" is 1, gives current value to the bus 7 | When "load" is 1 and clock edge rises, takes in new value from the bus 8 | Always gives current value to 'value' 9 | */ 10 | 11 | `include "ttl/74377.v" 12 | 13 | module Register(clk, bus, load_bar, value); 14 | input clk; 15 | input [15:0] bus; 16 | input load_bar; 17 | output [15:0] value; 18 | 19 | ttl_74377 reglow (load_bar, bus[7:0], clk, value[7:0]); 20 | ttl_74377 reghigh (load_bar, bus[15:8], clk, value[15:8]); 21 | endmodule 22 | -------------------------------------------------------------------------------- /verilog/ttl-tstate.v: -------------------------------------------------------------------------------- 1 | /* T-state counter 2 | 3 | Counts up on the *negative* edge of the clock 4 | */ 5 | 6 | `include "ttl/7400.v" 7 | `include "ttl/74161.v" 8 | 9 | module TState (clk, reset1, reset2_bar, T); 10 | input clk; 11 | input reset1, reset2_bar; 12 | output [2:0] T; 13 | 14 | ttl_7400 nander ({clk, reset1, inv_reset1, wantreset}, {clk, reset1, reset2_bar, wantreset}, {inv_clk, inv_reset1, wantreset, wantreset_bar}); 15 | 16 | ttl_74161 counter (wantreset_bar, 1'b1, 1'b1, 1'b1, 4'bZZZZ, inv_clk, RCO, {nc, T}); 17 | endmodule 18 | -------------------------------------------------------------------------------- /verilog/ttl-ucode.v: -------------------------------------------------------------------------------- 1 | /* Ucode: Turn an instruction into a microinstruction 2 | 3 | T0: PO AI 4 | T1: MO II P+ 5 | T2+: look in DecodeROM at {instr[15:8],T} 6 | */ 7 | 8 | `include "ttl/at28c16.v" 9 | 10 | module Ucode(instr, T, uinstr); 11 | input [15:0] instr; 12 | input [2:0] T; 13 | output [15:0] uinstr; 14 | 15 | wire [10:0] addr; 16 | assign addr = {instr[15:8], T}; 17 | 18 | at28c16 #(.ROM_FILE("ucode-low.hex")) rom2 (addr, uinstr[7:0], 1'b0, 1'b0); 19 | at28c16 #(.ROM_FILE("ucode-high.hex")) rom1 (addr, uinstr[15:8], 1'b0, 1'b0); 20 | endmodule 21 | -------------------------------------------------------------------------------- /verilog/ttl/7400.v: -------------------------------------------------------------------------------- 1 | // Quad 2-input NAND gate 2 | 3 | `ifndef TTL_7400 4 | `define TTL_7400 5 | 6 | module ttl_7400 #(parameter BLOCKS = 4, WIDTH_IN = 2, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input [BLOCKS-1:0] A, 9 | input [BLOCKS-1:0] B, 10 | output [BLOCKS-1:0] Y 11 | ); 12 | 13 | //------------------------------------------------// 14 | reg [BLOCKS-1:0] computed; 15 | integer i; 16 | 17 | always @(*) 18 | begin 19 | for (i = 0; i < BLOCKS; i++) 20 | computed[i] = ~(A[i]&B[i]); 21 | end 22 | //------------------------------------------------// 23 | 24 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 25 | 26 | endmodule 27 | 28 | `endif 29 | -------------------------------------------------------------------------------- /verilog/ttl/7402.v: -------------------------------------------------------------------------------- 1 | // Quad 2-input NOR gate 2 | 3 | module ttl_7402 #(parameter BLOCKS = 4, WIDTH_IN = 2, DELAY_RISE = 0, DELAY_FALL = 0) 4 | ( 5 | input [BLOCKS-1:0] A, 6 | input [BLOCKS-1:0] B, 7 | output [BLOCKS-1:0] Y 8 | ); 9 | 10 | //------------------------------------------------// 11 | reg [BLOCKS-1:0] computed; 12 | integer i; 13 | 14 | always @(*) 15 | begin 16 | for (i = 0; i < BLOCKS; i++) 17 | computed[i] = ~(A[i]|B[i]); 18 | end 19 | //------------------------------------------------// 20 | 21 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /verilog/ttl/7404.v: -------------------------------------------------------------------------------- 1 | // Hex inverter 2 | 3 | `ifndef TTL_7404 4 | `define TTL_7404 5 | 6 | module ttl_7404 #(parameter BLOCKS = 6, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input [BLOCKS-1:0] A, 9 | output [BLOCKS-1:0] Y 10 | ); 11 | 12 | //------------------------------------------------// 13 | reg [BLOCKS-1:0] computed; 14 | 15 | always @(*) 16 | begin 17 | computed = ~A; 18 | end 19 | //------------------------------------------------// 20 | 21 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 22 | 23 | endmodule 24 | 25 | `endif 26 | -------------------------------------------------------------------------------- /verilog/ttl/7407.v: -------------------------------------------------------------------------------- 1 | // Hex buffer/driver (OC) 2 | 3 | module ttl_7407 #(parameter BLOCKS = 6, DELAY_RISE = 0, DELAY_FALL = 0) 4 | ( 5 | input [BLOCKS-1:0] A, 6 | output [BLOCKS-1:0] Y 7 | ); 8 | 9 | //------------------------------------------------// 10 | reg [BLOCKS-1:0] computed; 11 | 12 | always @(*) 13 | begin 14 | computed = A; 15 | end 16 | //------------------------------------------------// 17 | 18 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /verilog/ttl/7408.v: -------------------------------------------------------------------------------- 1 | // Quad 2-input AND gate 2 | 3 | `ifndef TTL_7408 4 | `define TTL_7408 5 | 6 | module ttl_7408 #(parameter BLOCKS = 4, WIDTH_IN = 2, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input [BLOCKS-1:0] A, 9 | input [BLOCKS-1:0] B, 10 | output [BLOCKS-1:0] Y 11 | ); 12 | 13 | //------------------------------------------------// 14 | reg [BLOCKS-1:0] computed; 15 | integer i; 16 | 17 | always @(*) 18 | begin 19 | for (i = 0; i < BLOCKS; i++) 20 | computed[i] = A[i]&B[i]; 21 | end 22 | //------------------------------------------------// 23 | 24 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 25 | 26 | endmodule 27 | 28 | `endif 29 | -------------------------------------------------------------------------------- /verilog/ttl/74125.v: -------------------------------------------------------------------------------- 1 | // Quad bus buffer, positive enable 2 | 3 | module ttl_74125 #(parameter BLOCKS = 4, DELAY_RISE = 0, DELAY_FALL = 0) 4 | ( 5 | input [BLOCKS-1:0] C, 6 | input [BLOCKS-1:0] A, 7 | output [BLOCKS-1:0] Y 8 | ); 9 | 10 | //------------------------------------------------// 11 | integer i; 12 | reg [BLOCKS-1:0] computed; 13 | 14 | always @(*) 15 | begin 16 | for (i = 0; i < BLOCKS; i++) 17 | computed[i] = C[i] ? 1'bZ : A[i]; 18 | end 19 | //------------------------------------------------// 20 | 21 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /verilog/ttl/74126.v: -------------------------------------------------------------------------------- 1 | // Quad bus buffer, positive enable 2 | 3 | module ttl_74126 #(parameter BLOCKS = 4, DELAY_RISE = 0, DELAY_FALL = 0) 4 | ( 5 | input [BLOCKS-1:0] C, 6 | input [BLOCKS-1:0] A, 7 | output [BLOCKS-1:0] Y 8 | ); 9 | 10 | //------------------------------------------------// 11 | integer i; 12 | reg [BLOCKS-1:0] computed; 13 | 14 | always @(*) 15 | begin 16 | for (i = 0; i < BLOCKS; i++) 17 | computed[i] = C[i] ? A[i] : 1'bZ; 18 | end 19 | //------------------------------------------------// 20 | 21 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /verilog/ttl/74138.v: -------------------------------------------------------------------------------- 1 | // 3-line to 8-line decoder/demultiplexer (inverted outputs) 2 | 3 | `ifndef TTL_74138 4 | `define TTL_74138 5 | 6 | module ttl_74138 #(parameter WIDTH_OUT = 8, WIDTH_IN = $clog2(WIDTH_OUT), 7 | DELAY_RISE = 0, DELAY_FALL = 0) 8 | ( 9 | input Enable1_bar, 10 | input Enable2_bar, 11 | input Enable3, 12 | input [WIDTH_IN-1:0] A, 13 | output [WIDTH_OUT-1:0] Y 14 | ); 15 | 16 | //------------------------------------------------// 17 | reg [WIDTH_OUT-1:0] computed; 18 | integer i; 19 | 20 | always @(*) 21 | begin 22 | for (i = 0; i < WIDTH_OUT; i++) 23 | begin 24 | if (!Enable1_bar && !Enable2_bar && Enable3 && i == A) 25 | computed[i] = 1'b0; 26 | else 27 | computed[i] = 1'b1; 28 | end 29 | end 30 | //------------------------------------------------// 31 | 32 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 33 | 34 | endmodule 35 | 36 | `endif 37 | -------------------------------------------------------------------------------- /verilog/ttl/74153.v: -------------------------------------------------------------------------------- 1 | // Dual 4-input multiplexer 2 | 3 | module ttl_74153 #(parameter BLOCKS = 2, WIDTH_IN = 4, WIDTH_SELECT = $clog2(WIDTH_IN), 4 | DELAY_RISE = 0, DELAY_FALL = 0) 5 | ( 6 | input [BLOCKS-1:0] Enable_bar, 7 | input [WIDTH_SELECT-1:0] Select, 8 | input [WIDTH_IN-1:0] A, 9 | input [WIDTH_IN-1:0] B, 10 | output [BLOCKS-1:0] Y 11 | ); 12 | 13 | //------------------------------------------------// 14 | wire [WIDTH_IN-1:0] A [0:BLOCKS-1]; 15 | reg [BLOCKS-1:0] computed; 16 | integer i; 17 | 18 | always @(*) 19 | begin 20 | for (i = 0; i < BLOCKS; i++) 21 | begin 22 | if (!Enable_bar[i]) 23 | computed[i] = Select ? A[i] : B[i]; 24 | else 25 | computed[i] = 1'b0; 26 | end 27 | end 28 | //------------------------------------------------// 29 | 30 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /verilog/ttl/74157.v: -------------------------------------------------------------------------------- 1 | // Quad 2-input multiplexer 2 | 3 | // if select is high we get B on the output, if select is low we get A 4 | 5 | `ifndef TTL_74157 6 | `define TTL_74157 7 | 8 | module ttl_74157 #(parameter BLOCKS = 4, WIDTH_IN = 2, WIDTH_SELECT = $clog2(WIDTH_IN), 9 | DELAY_RISE = 0, DELAY_FALL = 0) 10 | ( 11 | input Enable_bar, 12 | input [WIDTH_SELECT-1:0] Select, 13 | input [BLOCKS-1:0] A, 14 | input [BLOCKS-1:0] B, 15 | output [BLOCKS-1:0] Y 16 | ); 17 | 18 | //------------------------------------------------// 19 | reg [BLOCKS-1:0] computed; 20 | integer i; 21 | 22 | always @(*) 23 | begin 24 | for (i = 0; i < BLOCKS; i++) 25 | begin 26 | if (!Enable_bar) 27 | computed[i] = Select ? B[i] : A[i]; 28 | else 29 | computed[i] = 1'b0; 30 | end 31 | end 32 | //------------------------------------------------// 33 | 34 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 35 | 36 | endmodule 37 | 38 | `endif 39 | -------------------------------------------------------------------------------- /verilog/ttl/74161.v: -------------------------------------------------------------------------------- 1 | // 4-bit modulo 16 binary counter with parallel load, asynchronous clear 2 | 3 | `ifndef TTL_74161 4 | `define TTL_74161 5 | 6 | module ttl_74161 #(parameter WIDTH = 4, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input Clear_bar, 9 | input Load_bar, 10 | input ENT, 11 | input ENP, 12 | input [WIDTH-1:0] D, 13 | input Clk, 14 | output RCO, 15 | output [WIDTH-1:0] Q 16 | ); 17 | 18 | //------------------------------------------------// 19 | wire RCO_current; 20 | reg [WIDTH-1:0] Q_current; 21 | wire [WIDTH-1:0] Q_next; 22 | 23 | assign Q_next = Q_current + 1; 24 | 25 | always @(posedge Clk or negedge Clear_bar) 26 | begin 27 | if (!Clear_bar) 28 | begin 29 | Q_current <= {WIDTH{1'b0}}; 30 | end 31 | else 32 | begin 33 | if (!Load_bar) 34 | begin 35 | Q_current <= D; 36 | end 37 | 38 | if (Load_bar && ENT && ENP) 39 | begin 40 | Q_current <= Q_next; 41 | end 42 | end 43 | end 44 | 45 | // output 46 | assign RCO_current = ENT && (&Q_current); 47 | 48 | //------------------------------------------------// 49 | 50 | assign #(DELAY_RISE, DELAY_FALL) RCO = RCO_current; 51 | assign #(DELAY_RISE, DELAY_FALL) Q = Q_current; 52 | 53 | endmodule 54 | 55 | `endif 56 | -------------------------------------------------------------------------------- /verilog/ttl/74244.v: -------------------------------------------------------------------------------- 1 | // Octal buffer with 3-state output 2 | 3 | `ifndef TTL_74244 4 | `define TTL_74244 5 | 6 | module ttl_74244 #(parameter WIDTH = 8, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input [(WIDTH-1)/4:0] G_bar, 9 | input [WIDTH-1:0] A, 10 | output [WIDTH-1:0] Y 11 | ); 12 | 13 | //------------------------------------------------// 14 | integer i; 15 | reg [WIDTH-1:0] computed; 16 | 17 | always @(*) 18 | begin 19 | for (i = 0; i < WIDTH; i++) 20 | computed[i] = G_bar[i/4] ? 1'bZ : A[i]; 21 | end 22 | //------------------------------------------------// 23 | 24 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 25 | 26 | endmodule 27 | 28 | `endif 29 | -------------------------------------------------------------------------------- /verilog/ttl/74283.v: -------------------------------------------------------------------------------- 1 | // 4-bit binary full adder with fast carry 2 | 3 | `ifndef TTL_74283 4 | `define TTL_74283 5 | 6 | module ttl_74283 #(parameter WIDTH = 4, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input [WIDTH-1:0] A, 9 | input [WIDTH-1:0] B, 10 | input C_in, 11 | output [WIDTH-1:0] Sum, 12 | output C_out 13 | ); 14 | 15 | //------------------------------------------------// 16 | reg [WIDTH-1:0] Sum_computed; 17 | reg C_computed; 18 | 19 | always @(*) 20 | begin 21 | {C_computed, Sum_computed} = {1'b0, A} + {1'b0, B} + C_in; 22 | end 23 | //------------------------------------------------// 24 | 25 | assign #(DELAY_RISE, DELAY_FALL) Sum = Sum_computed; 26 | assign #(DELAY_RISE, DELAY_FALL) C_out = C_computed; 27 | 28 | endmodule 29 | 30 | `endif 31 | -------------------------------------------------------------------------------- /verilog/ttl/7432.v: -------------------------------------------------------------------------------- 1 | // Quad 2-input OR gate 2 | 3 | `ifndef TTL_7432 4 | `define TTL_7432 5 | 6 | module ttl_7432 #(parameter BLOCKS = 4, WIDTH_IN = 2, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input [BLOCKS-1:0] A, 9 | input [BLOCKS-1:0] B, 10 | output [BLOCKS-1:0] Y 11 | ); 12 | 13 | //------------------------------------------------// 14 | reg [BLOCKS-1:0] computed; 15 | integer i; 16 | 17 | always @(*) 18 | begin 19 | for (i = 0; i < BLOCKS; i++) 20 | computed[i] = A[i]|B[i]; 21 | end 22 | //------------------------------------------------// 23 | 24 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 25 | 26 | endmodule 27 | 28 | `endif 29 | -------------------------------------------------------------------------------- /verilog/ttl/74377.v: -------------------------------------------------------------------------------- 1 | // Octal D flip-flop with enable 2 | 3 | `ifndef TTL_74377 4 | `define TTL_74377 5 | 6 | module ttl_74377 #(parameter WIDTH = 8, DELAY_RISE = 0, DELAY_FALL = 0) 7 | ( 8 | input Enable_bar, 9 | input [WIDTH-1:0] D, 10 | input Clk, 11 | output [WIDTH-1:0] Q 12 | ); 13 | 14 | //------------------------------------------------// 15 | reg [WIDTH-1:0] Q_current = 0; // XXX: initialise to *something* so that Icarus Verilog doesn't propagate "unknown" everywhere 16 | 17 | always @(posedge Clk) 18 | begin 19 | if (!Enable_bar) 20 | Q_current <= D; 21 | end 22 | //------------------------------------------------// 23 | 24 | assign #(DELAY_RISE, DELAY_FALL) Q = Q_current; 25 | 26 | endmodule 27 | 28 | `endif 29 | -------------------------------------------------------------------------------- /verilog/ttl/7486.v: -------------------------------------------------------------------------------- 1 | // Quad 2-input XOR gate 2 | 3 | // Note: For WIDTH_IN > 2, this is the "parity checker" interpretation of multi-input XOR 4 | // - conforms to chaining of XOR to create arbitrary wider input, e.g. "(A XOR B) XOR C" 5 | 6 | `ifndef TTL_7486 7 | `define TTL_7486 8 | 9 | module ttl_7486 #(parameter BLOCKS = 4, WIDTH_IN = 2, DELAY_RISE = 0, DELAY_FALL = 0) 10 | ( 11 | input [BLOCKS-1:0] A, 12 | input [BLOCKS-1:0] B, 13 | output [BLOCKS-1:0] Y 14 | ); 15 | 16 | //------------------------------------------------// 17 | reg [BLOCKS-1:0] computed; 18 | integer i; 19 | 20 | always @(*) 21 | begin 22 | for (i = 0; i < BLOCKS; i++) 23 | computed[i] = A[i] ^ B[i]; 24 | end 25 | //------------------------------------------------// 26 | 27 | assign #(DELAY_RISE, DELAY_FALL) Y = computed; 28 | 29 | endmodule 30 | 31 | `endif 32 | -------------------------------------------------------------------------------- /verilog/ttl/README.md: -------------------------------------------------------------------------------- 1 | Files in this directory are copied from https://github.com/TimRudy/ice-chips-verilog 2 | -------------------------------------------------------------------------------- /verilog/ttl/at28c16.v: -------------------------------------------------------------------------------- 1 | /* Atmel AT28C16, 2K*8bit EEPROM 2 | 3 | (Writing mode not implemented) 4 | 5 | Pass the ROM contents as a parameter, e.g.: 6 | 7 | at28c16 rom #(ROM_FILE="bootrom.hex") (addr, bus, oe_bar, ce_bar); 8 | */ 9 | 10 | `ifndef AT28C16 11 | `define AT28C16 12 | 13 | module at28c16 #(parameter ROM_FILE = "/dev/null", parameter ROM_BYTES = 2048) (addr, bus, oe_bar, ce_bar); 14 | input [10:0] addr; 15 | output [7:0] bus; 16 | input oe_bar, ce_bar; 17 | 18 | reg [7:0] rom [0:2047]; 19 | 20 | initial begin 21 | $readmemh(ROM_FILE, rom, 0, ROM_BYTES-1); 22 | end 23 | 24 | assign en = !oe_bar && !ce_bar; 25 | 26 | assign bus = en ? rom[addr] : 8'bZ; 27 | endmodule 28 | 29 | `endif 30 | -------------------------------------------------------------------------------- /verilog/ttl/w24512a.v: -------------------------------------------------------------------------------- 1 | /* Winbond W24512A, 64k*8bit SRAM */ 2 | 3 | module w24512a (addr, bus, cs1_bar, cs2, we_bar, oe_bar); 4 | input [15:0] addr; 5 | inout [7:0] bus; 6 | input cs1_bar, cs2, we_bar, oe_bar; 7 | 8 | reg [7:0] ram [0:65535]; 9 | 10 | assign we = !cs1_bar & cs2 & !we_bar; 11 | assign oe = !cs1_bar & cs2 & !oe_bar & we_bar; 12 | 13 | assign bus = oe ? ram[addr] : 8'bZ; 14 | 15 | always @ (negedge we_bar or posedge cs2 or negedge cs1_bar or posedge oe) begin 16 | if (we) ram[addr] <= bus; 17 | end 18 | 19 | endmodule 20 | -------------------------------------------------------------------------------- /verilog/ucode-high.hex: -------------------------------------------------------------------------------- 1 | ../ucode-high.hex -------------------------------------------------------------------------------- /verilog/ucode-low.hex: -------------------------------------------------------------------------------- 1 | ../ucode-low.hex -------------------------------------------------------------------------------- /verilog/ucode.hex: -------------------------------------------------------------------------------- 1 | ../ucode.hex -------------------------------------------------------------------------------- /verilog/ucode.v: -------------------------------------------------------------------------------- 1 | /* Ucode: Turn an instruction into a microinstruction 2 | 3 | T0: PO AI 4 | T1: MO II P+ 5 | T2+: look in DecodeROM at {instr[15:8],T} 6 | */ 7 | 8 | module Ucode(instr, T, uinstr); 9 | input [15:0] instr; 10 | input [2:0] T; 11 | output [15:0] uinstr; 12 | 13 | reg [15:0] rom [0:2047]; 14 | 15 | wire [10:0] addr; 16 | assign addr = {instr[15:8], T}; 17 | 18 | initial begin 19 | $readmemh("ucode.hex", rom); 20 | end 21 | 22 | assign uinstr = rom[addr]; 23 | endmodule 24 | -------------------------------------------------------------------------------- /verilog/verbose_tb.v: -------------------------------------------------------------------------------- 1 | /* CPU testbench */ 2 | `include "cpu.v" 3 | 4 | module test; 5 | reg clk; 6 | reg reset_bar = 1; 7 | wire [15:0] addr; 8 | wire [15:0] bus; 9 | 10 | CPU #(.DEBUG(1)) cpu (clk, reset_bar, addr, bus, DI, DO); 11 | 12 | reg [15:0] cycle = 0; 13 | 14 | reg [15:0] outputs = 0; 15 | 16 | initial begin 17 | reset_bar = 0; clk = 0; 18 | #1 clk = 1; 19 | #1 clk = 0; #1 reset_bar = 1; 20 | 21 | /* run the CPU for 3000 cycles */ 22 | while (cycle < 3000) begin 23 | cycle = cycle + 1; 24 | 25 | #1 clk = 1; 26 | 27 | #1 if (addr == 0 && DI) begin 28 | if (bus !== outputs) $display("Bad: output ",outputs, " != ", outputs, ": ", bus); 29 | outputs = outputs + 1; 30 | end 31 | 32 | clk = 0; 33 | end 34 | 35 | $display("Got ", outputs, " outputs"); 36 | end 37 | endmodule 38 | -------------------------------------------------------------------------------- /web/Makefile: -------------------------------------------------------------------------------- 1 | all: scamp.js 2 | 3 | scamp.js: ../emulator/scamp.c os.disk ucode.hex bootrom.hex 4 | emcc -o scamp.js ../emulator/scamp.c --preload-file os.disk --preload-file ucode.hex --preload-file bootrom.hex -s WASM=1 -O3 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=['ccall'] -s ALLOW_MEMORY_GROWTH=1 -DEMSCRIPTEN 5 | cp scamp.data scamp.wasm scamp.js public/ 6 | 7 | ucode.hex: ../ucode.hex 8 | cp ../ucode.hex . 9 | 10 | bootrom.hex: ../bootrom.hex 11 | cp ../bootrom.hex . 12 | 13 | os.disk: ../kernel/os.disk 14 | cp ../kernel/os.disk os.disk 15 | 16 | clean: 17 | -rm -f scamp.js scamp.wasm scamp.data os.disk ucode.hex bootrom.hex 18 | -------------------------------------------------------------------------------- /web/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "xterm": { 6 | "version": "4.13.0", 7 | "resolved": "https://registry.npmjs.org/xterm/-/xterm-4.13.0.tgz", 8 | "integrity": "sha512-HVW1gdoLOTnkMaqQCr2r3mQy4fX9iSa5gWxKZ2UTYdLa4iqavv7QxJ8n1Ypse32shPVkhTYPLS6vHEFZp5ghzw==" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js) 2 | Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com) 3 | Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/ColorContrastCache.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { IColor, IColorContrastCache } from 'browser/Types'; 7 | 8 | export class ColorContrastCache implements IColorContrastCache { 9 | private _color: { [bg: number]: { [fg: number]: IColor | null | undefined } | undefined } = {}; 10 | private _rgba: { [bg: number]: { [fg: number]: string | null | undefined } | undefined } = {}; 11 | 12 | public clear(): void { 13 | this._color = {}; 14 | this._rgba = {}; 15 | } 16 | 17 | public setCss(bg: number, fg: number, value: string | null): void { 18 | if (!this._rgba[bg]) { 19 | this._rgba[bg] = {}; 20 | } 21 | this._rgba[bg]![fg] = value; 22 | } 23 | 24 | public getCss(bg: number, fg: number): string | null | undefined { 25 | return this._rgba[bg] ? this._rgba[bg]![fg] : undefined; 26 | } 27 | 28 | public setColor(bg: number, fg: number, value: IColor | null): void { 29 | if (!this._color[bg]) { 30 | this._color[bg] = {}; 31 | } 32 | this._color[bg]![fg] = value; 33 | } 34 | 35 | public getColor(bg: number, fg: number): IColor | null | undefined { 36 | return this._color[bg] ? this._color[bg]![fg] : undefined; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/Dom.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | export function removeElementFromParent(...elements: (HTMLElement | undefined)[]): void { 7 | for (const e of elements) { 8 | e?.parentElement?.removeChild(e); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/Lifecycle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { IDisposable } from 'common/Types'; 7 | 8 | /** 9 | * Adds a disposable listener to a node in the DOM, returning the disposable. 10 | * @param type The event type. 11 | * @param handler The handler for the listener. 12 | */ 13 | export function addDisposableDomListener( 14 | node: Element | Window | Document, 15 | type: string, 16 | handler: (e: any) => void, 17 | options?: boolean | AddEventListenerOptions 18 | ): IDisposable { 19 | node.addEventListener(type, handler, options); 20 | let disposed = false; 21 | return { 22 | dispose: () => { 23 | if (disposed) { 24 | return; 25 | } 26 | disposed = true; 27 | node.removeEventListener(type, handler, options); 28 | } 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/LocalizableStrings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | // eslint-disable-next-line prefer-const 7 | export let promptLabel = 'Terminal input'; 8 | 9 | // eslint-disable-next-line prefer-const 10 | export let tooMuchOutput = 'Too much output to announce, navigate to rows manually to read'; 11 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/public/AddonManager.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { ITerminalAddon, IDisposable, Terminal } from 'xterm'; 7 | 8 | export interface ILoadedAddon { 9 | instance: ITerminalAddon; 10 | dispose: () => void; 11 | isDisposed: boolean; 12 | } 13 | 14 | export class AddonManager implements IDisposable { 15 | protected _addons: ILoadedAddon[] = []; 16 | 17 | constructor() { 18 | } 19 | 20 | public dispose(): void { 21 | for (let i = this._addons.length - 1; i >= 0; i--) { 22 | this._addons[i].instance.dispose(); 23 | } 24 | } 25 | 26 | public loadAddon(terminal: Terminal, instance: ITerminalAddon): void { 27 | const loadedAddon: ILoadedAddon = { 28 | instance, 29 | dispose: instance.dispose, 30 | isDisposed: false 31 | }; 32 | this._addons.push(loadedAddon); 33 | instance.dispose = () => this._wrappedAddonDispose(loadedAddon); 34 | instance.activate(terminal as any); 35 | } 36 | 37 | private _wrappedAddonDispose(loadedAddon: ILoadedAddon): void { 38 | if (loadedAddon.isDisposed) { 39 | // Do nothing if already disposed 40 | return; 41 | } 42 | let index = -1; 43 | for (let i = 0; i < this._addons.length; i++) { 44 | if (this._addons[i] === loadedAddon) { 45 | index = i; 46 | break; 47 | } 48 | } 49 | if (index === -1) { 50 | throw new Error('Could not dispose an addon that has not been loaded'); 51 | } 52 | loadedAddon.isDisposed = true; 53 | loadedAddon.dispose.apply(loadedAddon.instance); 54 | this._addons.splice(index, 1); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/renderer/GridCache.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | export class GridCache { 7 | public cache: (T | undefined)[][]; 8 | 9 | public constructor() { 10 | this.cache = []; 11 | } 12 | 13 | public resize(width: number, height: number): void { 14 | for (let x = 0; x < width; x++) { 15 | if (this.cache.length <= x) { 16 | this.cache.push([]); 17 | } 18 | for (let y = this.cache[x].length; y < height; y++) { 19 | this.cache[x].push(undefined); 20 | } 21 | this.cache[x].length = height; 22 | } 23 | this.cache.length = width; 24 | } 25 | 26 | public clear(): void { 27 | for (let x = 0; x < this.cache.length; x++) { 28 | for (let y = 0; y < this.cache[x].length; y++) { 29 | this.cache[x][y] = undefined; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/renderer/RendererUtils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | export function throwIfFalsy(value: T | undefined | null): T { 7 | if (!value) { 8 | throw new Error('value must not be falsy'); 9 | } 10 | return value; 11 | } 12 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/renderer/atlas/BaseCharAtlas.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { IGlyphIdentifier } from 'browser/renderer/atlas/Types'; 7 | import { IDisposable } from 'common/Types'; 8 | 9 | export abstract class BaseCharAtlas implements IDisposable { 10 | private _didWarmUp: boolean = false; 11 | 12 | public dispose(): void { } 13 | 14 | /** 15 | * Perform any work needed to warm the cache before it can be used. May be called multiple times. 16 | * Implement _doWarmUp instead if you only want to get called once. 17 | */ 18 | public warmUp(): void { 19 | if (!this._didWarmUp) { 20 | this._doWarmUp(); 21 | this._didWarmUp = true; 22 | } 23 | } 24 | 25 | /** 26 | * Perform any work needed to warm the cache before it can be used. Used by the default 27 | * implementation of warmUp(), and will only be called once. 28 | */ 29 | private _doWarmUp(): void { } 30 | 31 | /** 32 | * Called when we start drawing a new frame. 33 | * 34 | * TODO: We rely on this getting called by TextRenderLayer. This should really be called by 35 | * Renderer instead, but we need to make Renderer the source-of-truth for the char atlas, instead 36 | * of BaseRenderLayer. 37 | */ 38 | public beginFrame(): void { } 39 | 40 | /** 41 | * May be called before warmUp finishes, however it is okay for the implementation to 42 | * do nothing and return false in that case. 43 | * 44 | * @param ctx Where to draw the character onto. 45 | * @param glyph Information about what to draw 46 | * @param x The position on the context to start drawing at 47 | * @param y The position on the context to start drawing at 48 | * @returns The success state. True if we drew the character. 49 | */ 50 | public abstract draw( 51 | ctx: CanvasRenderingContext2D, 52 | glyph: IGlyphIdentifier, 53 | x: number, 54 | y: number 55 | ): boolean; 56 | } 57 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/renderer/atlas/Constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | export const INVERTED_DEFAULT_COLOR = 257; 7 | export const DIM_OPACITY = 0.5; 8 | 9 | export const CHAR_ATLAS_CELL_SPACING = 1; 10 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/renderer/atlas/Types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { FontWeight } from 'common/services/Services'; 7 | import { IPartialColorSet } from 'browser/Types'; 8 | 9 | export interface IGlyphIdentifier { 10 | chars: string; 11 | code: number; 12 | bg: number; 13 | fg: number; 14 | bold: boolean; 15 | dim: boolean; 16 | italic: boolean; 17 | } 18 | 19 | export interface ICharAtlasConfig { 20 | devicePixelRatio: number; 21 | fontSize: number; 22 | fontFamily: string; 23 | fontWeight: FontWeight; 24 | fontWeightBold: FontWeight; 25 | scaledCharWidth: number; 26 | scaledCharHeight: number; 27 | allowTransparency: boolean; 28 | colors: IPartialColorSet; 29 | } 30 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/selection/Types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | export interface ISelectionRedrawRequestEvent { 7 | start: [number, number] | undefined; 8 | end: [number, number] | undefined; 9 | columnSelectMode: boolean; 10 | } 11 | 12 | export interface ISelectionRequestScrollLinesEvent { 13 | amount: number; 14 | suppressScrollEvent: boolean; 15 | } 16 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/services/CoreBrowserService.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { ICoreBrowserService } from './Services'; 7 | 8 | export class CoreBrowserService implements ICoreBrowserService { 9 | public serviceBrand: undefined; 10 | 11 | constructor( 12 | private _textarea: HTMLTextAreaElement 13 | ) { 14 | } 15 | 16 | public get isFocused(): boolean { 17 | const docOrShadowRoot = this._textarea.getRootNode ? this._textarea.getRootNode() as Document | ShadowRoot : document; 18 | return docOrShadowRoot.activeElement === this._textarea && document.hasFocus(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/services/MouseService.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { ICharSizeService, IRenderService, IMouseService } from './Services'; 7 | import { getCoords, getRawByteCoords } from 'browser/input/Mouse'; 8 | 9 | export class MouseService implements IMouseService { 10 | public serviceBrand: undefined; 11 | 12 | constructor( 13 | @IRenderService private readonly _renderService: IRenderService, 14 | @ICharSizeService private readonly _charSizeService: ICharSizeService 15 | ) { 16 | } 17 | 18 | public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined { 19 | return getCoords( 20 | event, 21 | element, 22 | colCount, 23 | rowCount, 24 | this._charSizeService.hasValidSize, 25 | this._renderService.dimensions.actualCellWidth, 26 | this._renderService.dimensions.actualCellHeight, 27 | isSelection 28 | ); 29 | } 30 | 31 | public getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined { 32 | const coords = this.getCoords(event, element, colCount, rowCount); 33 | return getRawByteCoords(coords); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/browser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig-library-base", 3 | "compilerOptions": { 4 | "lib": [ 5 | "dom", 6 | "es2015", 7 | "es2016.Array.Include" 8 | ], 9 | "outDir": "../../out", 10 | "types": [ 11 | "../../node_modules/@types/mocha" 12 | ], 13 | "baseUrl": "..", 14 | "paths": { 15 | "common/*": [ "./common/*" ] 16 | } 17 | }, 18 | "include": [ 19 | "./**/*", 20 | "../../typings/xterm.d.ts" 21 | ], 22 | "references": [ 23 | { "path": "../common" } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/Clone.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | /* 7 | * A simple utility for cloning values 8 | */ 9 | export function clone(val: T, depth: number = 5): T { 10 | if (typeof val !== 'object') { 11 | return val; 12 | } 13 | 14 | // If we're cloning an array, use an array as the base, otherwise use an object 15 | const clonedObject: any = Array.isArray(val) ? [] : {}; 16 | 17 | for (const key in val) { 18 | // Recursively clone eack item unless we're at the maximum depth 19 | clonedObject[key] = depth <= 1 ? val[key] : (val[key] && clone(val[key], depth - 1)); 20 | } 21 | 22 | return clonedObject as T; 23 | } 24 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/EventEmitter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { IDisposable } from 'common/Types'; 7 | 8 | interface IListener { 9 | (arg1: T, arg2: U): void; 10 | } 11 | 12 | export interface IEvent { 13 | (listener: (arg1: T, arg2: U) => any): IDisposable; 14 | } 15 | 16 | export interface IEventEmitter { 17 | event: IEvent; 18 | fire(arg1: T, arg2: U): void; 19 | dispose(): void; 20 | } 21 | 22 | export class EventEmitter implements IEventEmitter { 23 | private _listeners: IListener[] = []; 24 | private _event?: IEvent; 25 | private _disposed: boolean = false; 26 | 27 | public get event(): IEvent { 28 | if (!this._event) { 29 | this._event = (listener: (arg1: T, arg2: U) => any) => { 30 | this._listeners.push(listener); 31 | const disposable = { 32 | dispose: () => { 33 | if (!this._disposed) { 34 | for (let i = 0; i < this._listeners.length; i++) { 35 | if (this._listeners[i] === listener) { 36 | this._listeners.splice(i, 1); 37 | return; 38 | } 39 | } 40 | } 41 | } 42 | }; 43 | return disposable; 44 | }; 45 | } 46 | return this._event; 47 | } 48 | 49 | public fire(arg1: T, arg2: U): void { 50 | const queue: IListener[] = []; 51 | for (let i = 0; i < this._listeners.length; i++) { 52 | queue.push(this._listeners[i]); 53 | } 54 | for (let i = 0; i < queue.length; i++) { 55 | queue[i].call(undefined, arg1, arg2); 56 | } 57 | } 58 | 59 | public dispose(): void { 60 | if (this._listeners) { 61 | this._listeners.length = 0; 62 | } 63 | this._disposed = true; 64 | } 65 | } 66 | 67 | export function forwardEvent(from: IEvent, to: IEventEmitter): IDisposable { 68 | return from(e => to.fire(e)); 69 | } 70 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/Lifecycle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { IDisposable } from 'common/Types'; 7 | 8 | /** 9 | * A base class that can be extended to provide convenience methods for managing the lifecycle of an 10 | * object and its components. 11 | */ 12 | export abstract class Disposable implements IDisposable { 13 | protected _disposables: IDisposable[] = []; 14 | protected _isDisposed: boolean = false; 15 | 16 | constructor() { 17 | } 18 | 19 | /** 20 | * Disposes the object, triggering the `dispose` method on all registered IDisposables. 21 | */ 22 | public dispose(): void { 23 | this._isDisposed = true; 24 | for (const d of this._disposables) { 25 | d.dispose(); 26 | } 27 | this._disposables.length = 0; 28 | } 29 | 30 | /** 31 | * Registers a disposable object. 32 | * @param d The disposable to register. 33 | * @returns The disposable. 34 | */ 35 | public register(d: T): T { 36 | this._disposables.push(d); 37 | return d; 38 | } 39 | 40 | /** 41 | * Unregisters a disposable object if it has been registered, if not do 42 | * nothing. 43 | * @param d The disposable to unregister. 44 | */ 45 | public unregister(d: T): void { 46 | const index = this._disposables.indexOf(d); 47 | if (index !== -1) { 48 | this._disposables.splice(index, 1); 49 | } 50 | } 51 | } 52 | 53 | /** 54 | * Dispose of all disposables in an array and set its length to 0. 55 | */ 56 | export function disposeArray(disposables: IDisposable[]): void { 57 | for (const d of disposables) { 58 | d.dispose(); 59 | } 60 | disposables.length = 0; 61 | } 62 | 63 | /** 64 | * Creates a disposable that will dispose of an array of disposables when disposed. 65 | */ 66 | export function getDisposeArrayDisposable(array: IDisposable[]): IDisposable { 67 | return { dispose: () => disposeArray(array) }; 68 | } 69 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/Platform.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | interface INavigator { 7 | userAgent: string; 8 | language: string; 9 | platform: string; 10 | } 11 | 12 | // We're declaring a navigator global here as we expect it in all runtimes (node and browser), but 13 | // we want this module to live in common. 14 | declare const navigator: INavigator; 15 | 16 | const isNode = (typeof navigator === 'undefined') ? true : false; 17 | const userAgent = (isNode) ? 'node' : navigator.userAgent; 18 | const platform = (isNode) ? 'node' : navigator.platform; 19 | 20 | export const isFirefox = userAgent.includes('Firefox'); 21 | export const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent); 22 | 23 | // Find the users platform. We use this to interpret the meta key 24 | // and ISO third level shifts. 25 | // http://stackoverflow.com/q/19877924/577598 26 | export const isMac = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'].includes(platform); 27 | export const isIpad = platform === 'iPad'; 28 | export const isIphone = platform === 'iPhone'; 29 | export const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(platform); 30 | export const isLinux = platform.indexOf('Linux') >= 0; 31 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/TypedArrayUtils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | export type TypedArray = Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array; 7 | 8 | 9 | /** 10 | * polyfill for TypedArray.fill 11 | * This is needed to support .fill in all safari versions and IE 11. 12 | */ 13 | export function fill(array: T, value: number, start?: number, end?: number): T { 14 | // all modern engines that support .fill 15 | if (array.fill) { 16 | return array.fill(value, start, end) as T; 17 | } 18 | return fillFallback(array, value, start, end); 19 | } 20 | 21 | export function fillFallback(array: T, value: number, start: number = 0, end: number = array.length): T { 22 | // safari and IE 11 23 | // since IE 11 does not support Array.prototype.fill either 24 | // we cannot use the suggested polyfill from MDN 25 | // instead we simply fall back to looping 26 | if (start >= array.length) { 27 | return array; 28 | } 29 | start = (array.length + start) % array.length; 30 | if (end >= array.length) { 31 | end = array.length; 32 | } else { 33 | end = (array.length + end) % array.length; 34 | } 35 | for (let i = start; i < end; ++i) { 36 | array[i] = value; 37 | } 38 | return array; 39 | } 40 | 41 | /** 42 | * Concat two typed arrays `a` and `b`. 43 | * Returns a new typed array. 44 | */ 45 | export function concat(a: T, b: T): T { 46 | const result = new (a.constructor as any)(a.length + b.length); 47 | result.set(a); 48 | result.set(b, a.length); 49 | return result; 50 | } 51 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/WindowsMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from 'common/buffer/Constants'; 7 | import { IBufferService } from 'common/services/Services'; 8 | 9 | export function updateWindowsModeWrappedState(bufferService: IBufferService): void { 10 | // Winpty does not support wraparound mode which means that lines will never 11 | // be marked as wrapped. This causes issues for things like copying a line 12 | // retaining the wrapped new line characters or if consumers are listening 13 | // in on the data stream. 14 | // 15 | // The workaround for this is to listen to every incoming line feed and mark 16 | // the line as wrapped if the last character in the previous line is not a 17 | // space. This is certainly not without its problems, but generally on 18 | // Windows when text reaches the end of the terminal it's likely going to be 19 | // wrapped. 20 | const line = bufferService.buffer.lines.get(bufferService.buffer.ybase + bufferService.buffer.y - 1); 21 | const lastChar = line?.get(bufferService.cols - 1); 22 | 23 | const nextLine = bufferService.buffer.lines.get(bufferService.buffer.ybase + bufferService.buffer.y); 24 | if (nextLine && lastChar) { 25 | nextLine.isWrapped = (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/buffer/BufferRange.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2021 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { IBufferRange } from 'xterm'; 7 | 8 | export function getRangeLength(range: IBufferRange, bufferCols: number): number { 9 | if (range.start.y > range.end.y) { 10 | throw new Error(`Buffer range end (${range.end.x}, ${range.end.y}) cannot be before start (${range.start.x}, ${range.start.y})`); 11 | } 12 | return bufferCols * (range.end.y - range.start.y) + (range.end.x - range.start.x + 1); 13 | } 14 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/buffer/Marker.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { EventEmitter, IEvent } from 'common/EventEmitter'; 7 | import { Disposable } from 'common/Lifecycle'; 8 | import { IMarker } from 'common/Types'; 9 | 10 | export class Marker extends Disposable implements IMarker { 11 | private static _nextId = 1; 12 | 13 | private _id: number = Marker._nextId++; 14 | public isDisposed: boolean = false; 15 | 16 | public get id(): number { return this._id; } 17 | 18 | private _onDispose = new EventEmitter(); 19 | public get onDispose(): IEvent { return this._onDispose.event; } 20 | 21 | constructor( 22 | public line: number 23 | ) { 24 | super(); 25 | } 26 | 27 | public dispose(): void { 28 | if (this.isDisposed) { 29 | return; 30 | } 31 | this.isDisposed = true; 32 | this.line = -1; 33 | // Emit before super.dispose such that dispose listeners get a change to react 34 | this._onDispose.fire(); 35 | super.dispose(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/parser/Constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | /** 7 | * Internal states of EscapeSequenceParser. 8 | */ 9 | export const enum ParserState { 10 | GROUND = 0, 11 | ESCAPE = 1, 12 | ESCAPE_INTERMEDIATE = 2, 13 | CSI_ENTRY = 3, 14 | CSI_PARAM = 4, 15 | CSI_INTERMEDIATE = 5, 16 | CSI_IGNORE = 6, 17 | SOS_PM_APC_STRING = 7, 18 | OSC_STRING = 8, 19 | DCS_ENTRY = 9, 20 | DCS_PARAM = 10, 21 | DCS_IGNORE = 11, 22 | DCS_INTERMEDIATE = 12, 23 | DCS_PASSTHROUGH = 13 24 | } 25 | 26 | /** 27 | * Internal actions of EscapeSequenceParser. 28 | */ 29 | export const enum ParserAction { 30 | IGNORE = 0, 31 | ERROR = 1, 32 | PRINT = 2, 33 | EXECUTE = 3, 34 | OSC_START = 4, 35 | OSC_PUT = 5, 36 | OSC_END = 6, 37 | CSI_DISPATCH = 7, 38 | PARAM = 8, 39 | COLLECT = 9, 40 | ESC_DISPATCH = 10, 41 | CLEAR = 11, 42 | DCS_HOOK = 12, 43 | DCS_PUT = 13, 44 | DCS_UNHOOK = 14 45 | } 46 | 47 | /** 48 | * Internal states of OscParser. 49 | */ 50 | export const enum OscState { 51 | START = 0, 52 | ID = 1, 53 | PAYLOAD = 2, 54 | ABORT = 3 55 | } 56 | 57 | // payload limit for OSC and DCS 58 | export const PAYLOAD_LIMIT = 10000000; 59 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/services/CharsetService.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { ICharsetService } from 'common/services/Services'; 7 | import { ICharset } from 'common/Types'; 8 | 9 | export class CharsetService implements ICharsetService { 10 | public serviceBrand: any; 11 | 12 | public charset: ICharset | undefined; 13 | public glevel: number = 0; 14 | 15 | private _charsets: (ICharset | undefined)[] = []; 16 | 17 | public reset(): void { 18 | this.charset = undefined; 19 | this._charsets = []; 20 | this.glevel = 0; 21 | } 22 | 23 | public setgLevel(g: number): void { 24 | this.glevel = g; 25 | this.charset = this._charsets[g]; 26 | } 27 | 28 | public setgCharset(g: number, charset: ICharset | undefined): void { 29 | this._charsets[g] = charset; 30 | if (this.glevel === g) { 31 | this.charset = charset; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/services/DirtyRowService.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | */ 5 | 6 | import { IBufferService, IDirtyRowService } from 'common/services/Services'; 7 | 8 | export class DirtyRowService implements IDirtyRowService { 9 | public serviceBrand: any; 10 | 11 | private _start!: number; 12 | private _end!: number; 13 | 14 | public get start(): number { return this._start; } 15 | public get end(): number { return this._end; } 16 | 17 | constructor( 18 | @IBufferService private readonly _bufferService: IBufferService 19 | ) { 20 | this.clearRange(); 21 | } 22 | 23 | public clearRange(): void { 24 | this._start = this._bufferService.buffer.y; 25 | this._end = this._bufferService.buffer.y; 26 | } 27 | 28 | public markDirty(y: number): void { 29 | if (y < this._start) { 30 | this._start = y; 31 | } else if (y > this._end) { 32 | this._end = y; 33 | } 34 | } 35 | 36 | public markRangeDirty(y1: number, y2: number): void { 37 | if (y1 > y2) { 38 | const temp = y1; 39 | y1 = y2; 40 | y2 = temp; 41 | } 42 | if (y1 < this._start) { 43 | this._start = y1; 44 | } 45 | if (y2 > this._end) { 46 | this._end = y2; 47 | } 48 | } 49 | 50 | public markAllDirty(): void { 51 | this.markRangeDirty(0, this._bufferService.rows - 1); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/services/ServiceRegistry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 The xterm.js authors. All rights reserved. 3 | * @license MIT 4 | * 5 | * This was heavily inspired from microsoft/vscode's dependency injection system (MIT). 6 | */ 7 | /*--------------------------------------------------------------------------------------------- 8 | * Copyright (c) Microsoft Corporation. All rights reserved. 9 | * Licensed under the MIT License. See License.txt in the project root for license information. 10 | *--------------------------------------------------------------------------------------------*/ 11 | 12 | import { IServiceIdentifier } from 'common/services/Services'; 13 | 14 | const DI_TARGET = 'di$target'; 15 | const DI_DEPENDENCIES = 'di$dependencies'; 16 | 17 | export const serviceRegistry: Map> = new Map(); 18 | 19 | export function getServiceDependencies(ctor: any): { id: IServiceIdentifier, index: number, optional: boolean }[] { 20 | return ctor[DI_DEPENDENCIES] || []; 21 | } 22 | 23 | export function createDecorator(id: string): IServiceIdentifier { 24 | if (serviceRegistry.has(id)) { 25 | return serviceRegistry.get(id)!; 26 | } 27 | 28 | const decorator: any = function (target: Function, key: string, index: number): any { 29 | if (arguments.length !== 3) { 30 | throw new Error('@IServiceName-decorator can only be used to decorate a parameter'); 31 | } 32 | 33 | storeServiceDependency(decorator, target, index); 34 | }; 35 | 36 | decorator.toString = () => id; 37 | 38 | serviceRegistry.set(id, decorator); 39 | return decorator; 40 | } 41 | 42 | function storeServiceDependency(id: Function, target: Function, index: number): void { 43 | if ((target as any)[DI_TARGET] === target) { 44 | (target as any)[DI_DEPENDENCIES].push({ id, index }); 45 | } else { 46 | (target as any)[DI_DEPENDENCIES] = [{ id, index }]; 47 | (target as any)[DI_TARGET] = target; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig-library-base", 3 | "compilerOptions": { 4 | "lib": [ 5 | "es2015", 6 | "es2016.Array.Include" 7 | ], 8 | "outDir": "../../out", 9 | "types": [ 10 | "../../node_modules/@types/mocha" 11 | ], 12 | "baseUrl": ".." 13 | }, 14 | "include": [ 15 | "./**/*", 16 | "../../typings/xterm.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/tsconfig-base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ "es5" ], 5 | "rootDir": ".", 6 | 7 | "sourceMap": true, 8 | "removeComments": true, 9 | "pretty": true, 10 | 11 | "incremental": true, 12 | "experimentalDecorators": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/src/tsconfig-library-base.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig-base.json", 3 | "compilerOptions": { 4 | "composite": true, 5 | "strict": true, 6 | "declarationMap": true, 7 | "experimentalDecorators": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/public/node_modules/xterm/tsconfig.all.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "include": [], 4 | "references": [ 5 | { "path": "./src/browser" }, 6 | { "path": "./test/api" }, 7 | { "path": "./test/benchmark" }, 8 | { "path": "./addons/xterm-addon-attach" }, 9 | { "path": "./addons/xterm-addon-fit" }, 10 | { "path": "./addons/xterm-addon-ligatures" }, 11 | { "path": "./addons/xterm-addon-search" }, 12 | { "path": "./addons/xterm-addon-serialize" }, 13 | { "path": "./addons/xterm-addon-unicode11" }, 14 | { "path": "./addons/xterm-addon-web-links" }, 15 | { "path": "./addons/xterm-addon-webgl" } 16 | ] 17 | } 18 | --------------------------------------------------------------------------------