├── 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 |
--------------------------------------------------------------------------------