Compare commits
27 Commits
RamEditor
...
user-im-n-
Author | SHA1 | Date | |
---|---|---|---|
964d34f73a | |||
f2fe410cc1 | |||
8b3d2d525b | |||
a92da271d1 | |||
c4a1884c6d | |||
1d7169ddb2 | |||
8867374f85 | |||
b3478d7eb3 | |||
f4ad57b544 | |||
51d8ccf148 | |||
87ec19157b | |||
5664e0483b | |||
95985eb92a | |||
c4a54ee2e4 | |||
8d0aded26f | |||
ca60d8bae8 | |||
a8195a3fba | |||
88f84a9c25 | |||
6bbed4c655 | |||
49863a0079 | |||
9b789a1378 | |||
1b7a502cd4 | |||
8e131d3ee4 | |||
182662e2e0 | |||
dc9b5c725e | |||
20fb9914ef | |||
0aa08315d1 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,8 @@
|
||||
desktop.ini
|
||||
|
||||
elm-stuff/*
|
||||
out/js/elm.js
|
||||
*.zip
|
||||
|
||||
*.sublime*
|
||||
|
||||
|
25
build.sh
Normal file
25
build.sh
Normal file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
echo "Building..."
|
||||
|
||||
# Create folders
|
||||
mkdir -p out/css
|
||||
mkdir -p out/js
|
||||
|
||||
|
||||
# JS + TS
|
||||
#cp src/js/*.js out/js/
|
||||
# tsc --lib es2015 --lib dom --outDir out/js src/js/*.ts
|
||||
|
||||
|
||||
# Compile Elm
|
||||
elm make src/Main.elm --output out/js/elm.js --optimize
|
||||
|
||||
# CSS
|
||||
#cp src/css/*.css out/css/
|
||||
|
||||
# cp out/main.js js/main.julius
|
||||
|
||||
echo "Build complete"
|
3
elm-tooling.json
Normal file
3
elm-tooling.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"entrypoints": ["./src/Main.elm"]
|
||||
}
|
3
elm.json
3
elm.json
@ -8,10 +8,13 @@
|
||||
"direct": {
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/core": "1.0.5",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/html": "1.0.0",
|
||||
"elm/http": "2.0.0",
|
||||
"elm/json": "1.1.3"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/url": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
|
@ -1,3 +1,4 @@
|
||||
@media (prefers-color-scheme: dark){
|
||||
:root {
|
||||
--color-black: #05050F;
|
||||
--color-white: #FFFFFF;
|
||||
@ -39,7 +40,7 @@
|
||||
|
||||
|
||||
--color-body: var(--color-black);
|
||||
--color-body-text: var(--color-black);
|
||||
--color-body-text: var(--color-white);
|
||||
|
||||
--color-addressbus: var(--color-addressbus-main);
|
||||
--color-addressbus-text: var(--color-white);
|
||||
@ -50,6 +51,7 @@
|
||||
--color-controls-button-text: var(--color-white);
|
||||
--color-controls-button-border: var(--color-white);
|
||||
--color-controls-button-text-hover: var(--color-white-light1);
|
||||
--color-controls-scroller-label-text: var(--color-black);
|
||||
|
||||
--color-header: var(--color-grey);
|
||||
--color-header-text: var(--color-white);
|
||||
@ -73,18 +75,40 @@
|
||||
--color-table-ram-head-text: var(--color-white);
|
||||
--color-table-ram-highlight: var(--color-ram-light2);
|
||||
--color-table-ram-highlight-text: var(--color-black);
|
||||
--color-table-ram-select: transparent;
|
||||
--color-table-ram-select-text: inherit;
|
||||
--color-table-ram-select-border: var(--color-grey-light2);
|
||||
--color-table-ram-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-table-cu-head: var(--color-cu-dark1);
|
||||
--color-table-cu-head-text: var(--color-white);
|
||||
--color-table-cu-highlight: var(--color-cu-light2);
|
||||
--color-table-cu-highlight-text: var(--color-black);
|
||||
--color-table-cu-select: transparent;
|
||||
--color-table-cu-select-text: inherit;
|
||||
--color-table-cu-select-border: var(--color-grey-light2);
|
||||
--color-table-cu-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-arrow: var(--color-arrow-main);
|
||||
--color-arrow-text: var(--color-white);
|
||||
--color-arrow-text-hover: var(--color-white-light2);
|
||||
--color-arrow-border: var(--color-black-light1);
|
||||
|
||||
--color-modal: var(--color-black);
|
||||
--color-modal-text: var(--color-white);
|
||||
--color-modal-shadow: rgba( 0,0,0, 0.4 );
|
||||
|
||||
--color-code: var(--color-black-light1);
|
||||
--color-code-text: var(--color-white);
|
||||
|
||||
--color-dragdrop: var(--color-code);
|
||||
--color-dragdrop-text: var(--color-white);
|
||||
--color-dragdrop-processing: var(--color-cu-main);
|
||||
--color-dragdrop-processing-text: var(--color-white);
|
||||
}
|
||||
|
||||
|
||||
/* https://coolors.co/aa8f66-ed9b40-ffeedb-61c9a8-ba3b46-071013 */
|
||||
/* https://coolors.co/faf3dd-000022-9c528b-62a87c-247ba0-429ea6-8fb8de-72705b */
|
||||
|
||||
}
|
@ -50,6 +50,7 @@
|
||||
--color-controls-button-text: var(--color-black);
|
||||
--color-controls-button-border: var(--color-black);
|
||||
--color-controls-button-text-hover: var(--color-black-light1);
|
||||
--color-controls-scroller-label-text: var(--color-white);
|
||||
|
||||
--color-header: var(--color-grey);
|
||||
--color-header-text: var(--color-white);
|
||||
@ -76,6 +77,7 @@
|
||||
--color-table-ram-select: transparent;
|
||||
--color-table-ram-select-text: inherit;
|
||||
--color-table-ram-select-border: var(--color-grey-light2);
|
||||
--color-table-ram-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-table-cu-head: var(--color-cu-dark1);
|
||||
--color-table-cu-head-text: var(--color-white);
|
||||
@ -84,11 +86,24 @@
|
||||
--color-table-cu-select: transparent;
|
||||
--color-table-cu-select-text: inherit;
|
||||
--color-table-cu-select-border: var(--color-grey-light2);
|
||||
--color-table-cu-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-arrow: var(--color-arrow-main);
|
||||
--color-arrow-text: var(--color-white);
|
||||
--color-arrow-text-hover: var(--color-white-light2);
|
||||
--color-arrow-border: var(--color-black-light1);
|
||||
|
||||
--color-modal: var(--color-white-light1);
|
||||
--color-modal-text: var(--color-black);
|
||||
--color-modal-shadow: rgba( 0,0,0, 0.4 );
|
||||
|
||||
--color-code: var(--color-white-light2);
|
||||
--color-code-text: var(--color-black);
|
||||
|
||||
--color-dragdrop: var(--color-code);
|
||||
--color-dragdrop-text: var(--color-black);
|
||||
--color-dragdrop-processing: var(--color-cu-light1);
|
||||
--color-dragdrop-processing-text: var(--color-black);
|
||||
}
|
||||
|
||||
|
||||
|
53
out/css/cookie.css
Normal file
53
out/css/cookie.css
Normal file
@ -0,0 +1,53 @@
|
||||
.cookie-banner{
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
height: min-content;
|
||||
|
||||
color: black;
|
||||
background-color: white;
|
||||
border-top: 1px solid black;
|
||||
|
||||
padding: .75rem 2rem;
|
||||
z-index: 2500;
|
||||
}
|
||||
|
||||
.cookie-banner button {
|
||||
display: inline;
|
||||
height: 2.5rem;
|
||||
padding: .5rem 1rem;
|
||||
margin: 0;
|
||||
line-height: 1em;
|
||||
|
||||
color: black;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
.cookie-banner * {
|
||||
margin-right: 1rem !important;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.cookie-banner > :first-child {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.cookie-banner > :last-child {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark){
|
||||
.cookie-banner {
|
||||
background-color: black;
|
||||
border-color: white;
|
||||
color: white;
|
||||
}
|
||||
.cookie-banner button{
|
||||
color: white;
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
}
|
310
out/css/loader.css
Normal file
310
out/css/loader.css
Normal file
@ -0,0 +1,310 @@
|
||||
/* Variables */
|
||||
* {
|
||||
--loaderDivCol: var(--color-dragdrop-processing-text);
|
||||
|
||||
--circR: 1rem;
|
||||
--circD: 2rem;
|
||||
--circ6D: 12rem;
|
||||
|
||||
--timing: ease-in-out;
|
||||
--fullCycle: 5s;
|
||||
}
|
||||
|
||||
.loader.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loader {
|
||||
position: relative;
|
||||
|
||||
box-sizing: border-box;
|
||||
height: var(--circD);
|
||||
width: var(--circ6D);
|
||||
|
||||
margin: calc(var(--circD) * 3) var(--circD);
|
||||
padding: var(--circR) 0;
|
||||
}
|
||||
|
||||
.loader > * {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
height: 0;
|
||||
width: calc(2 * var(--circD));
|
||||
opacity: 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
--keyframe-sequence: "loading0";
|
||||
--delay: 0;
|
||||
--animation: var(--keyframe-sequence) var(--fullCycle) var(--timing) calc(0s - var(--fullCycle) * (1 - (var(--delay)) / 8) ) infinite;
|
||||
|
||||
-webkit-animation: var(--animation);
|
||||
-moz-animation: var(--animation);
|
||||
-ms-animation: var(--animation);
|
||||
-o-animation: var(--animation);
|
||||
animation: var(--animation);
|
||||
}
|
||||
|
||||
.loader div::before,
|
||||
.loader div::after {
|
||||
content: "";
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: var(--circD);
|
||||
height: var(--circD);
|
||||
border: 1px solid var(--loaderDivCol);
|
||||
background: var(--loaderDivCol);
|
||||
border-radius: 100%;
|
||||
|
||||
position: absolute;
|
||||
top: calc(0px - var(--circR));
|
||||
}
|
||||
|
||||
.loader div::before {
|
||||
left: calc(0px - var(--circR));
|
||||
}
|
||||
.loader div::after {
|
||||
right: calc(0px - var(--circR));
|
||||
}
|
||||
|
||||
|
||||
@keyframes loading0 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.56% {
|
||||
opacity: 0;
|
||||
}
|
||||
99.7% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading2 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.56% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
24.6% {
|
||||
opacity: 0;
|
||||
}
|
||||
24.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.57% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
99.95% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading3 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.56% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
37.4% {
|
||||
opacity: 0;
|
||||
}
|
||||
37.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
50.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
50.1% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
99.8% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading5 {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.58% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
62.4% {
|
||||
opacity: 0;
|
||||
}
|
||||
62.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
75.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
75.1% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
99.7% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading6 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.57% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
74.85% {
|
||||
opacity: 0;
|
||||
}
|
||||
74.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.6% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
99.8% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.loader :nth-child(1) {
|
||||
width: 66.66%;
|
||||
--keyframe-sequence: "loading5";
|
||||
--delay: 0;
|
||||
}
|
||||
.loader :nth-child(2) {
|
||||
width: 66.66%;
|
||||
margin-left: 0;
|
||||
--keyframe-sequence: "loading2";
|
||||
--delay: 0;
|
||||
}
|
||||
.loader :nth-child(3) {
|
||||
width: 33.33%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading2";
|
||||
--delay: 1;
|
||||
}
|
||||
.loader :nth-child(4) {
|
||||
width: 66.66%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading6";
|
||||
--delay: 2;
|
||||
}
|
||||
|
||||
.loader :nth-child(5) {
|
||||
width: 100%;
|
||||
--keyframe-sequence: "loading6";
|
||||
--delay: 3;
|
||||
}
|
||||
.loader :nth-child(6) {
|
||||
width: 100%;
|
||||
--keyframe-sequence: "loading3";
|
||||
--delay: 3;
|
||||
}
|
||||
.loader :nth-child(7) {
|
||||
width: 33.33%;
|
||||
--keyframe-sequence: "loading3";
|
||||
--delay: 4;
|
||||
}
|
||||
.loader :nth-child(8) {
|
||||
width: 66.66%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading3";
|
||||
--delay: 5;
|
||||
}
|
||||
.loader :nth-child(9) {
|
||||
width: 33.33%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading5";
|
||||
--delay: 6;
|
||||
}
|
||||
.loader :nth-child(10) {
|
||||
width: 33.33%;
|
||||
margin-left: 66.66%;
|
||||
--keyframe-sequence: "loading5";
|
||||
--delay: 7;
|
||||
}
|
827
out/css/pc.css
Normal file
827
out/css/pc.css
Normal file
@ -0,0 +1,827 @@
|
||||
/* COLORS */
|
||||
.pc .ram {
|
||||
background-color: var(--color-ram);
|
||||
color: var(--color-ram-text);
|
||||
}
|
||||
|
||||
.pc .cu {
|
||||
background-color: var(--color-cu);
|
||||
color: var(--color-cu-text);
|
||||
}
|
||||
|
||||
.pc .alu {
|
||||
background-color: var(--color-alu);
|
||||
color: var(--color-alu-text);
|
||||
}
|
||||
|
||||
.pc .section h1.header {
|
||||
background-color: var(--color-header);
|
||||
color: var(--color-header-text);
|
||||
}
|
||||
|
||||
|
||||
/* TABLE COLORS */
|
||||
.pc .ram .scroller table thead.head th {
|
||||
background-color: var(--color-table-ram-head);
|
||||
color: var(--color-table-ram-head-text);
|
||||
}
|
||||
|
||||
.pc .cu .scroller table thead.head th {
|
||||
background-color: var(--color-table-cu-head);
|
||||
color: var(--color-table-cu-head-text);
|
||||
}
|
||||
|
||||
.pc .scroller table tr td {
|
||||
background-color: var(--color-table-row);
|
||||
color: var(--color-table-text);
|
||||
border-bottom: 1px solid var(--color-table-border);
|
||||
}
|
||||
|
||||
.pc .scroller table tr:nth-child(even) td{
|
||||
background-color: var(--color-table-row-alt);
|
||||
}
|
||||
|
||||
.pc .scroller table tr.empty td {
|
||||
color: var(--color-table-text-empty);
|
||||
}
|
||||
|
||||
.pc .ram .scroller table tr.current td {
|
||||
background-color: var(--color-table-ram-highlight);
|
||||
color: var(--color-table-ram-highlight-text);
|
||||
}
|
||||
|
||||
.pc .cu .scroller table tr.current td {
|
||||
background-color: var(--color-table-cu-highlight);
|
||||
color: var(--color-table-cu-highlight-text);
|
||||
}
|
||||
|
||||
|
||||
.pc button,
|
||||
.pc .button{
|
||||
text-transform: none !important;
|
||||
font-weight: 600;
|
||||
height: 2.5em;
|
||||
line-height: 1em;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
padding: 0.25em 2em;
|
||||
}
|
||||
|
||||
/* CONTROLS COLORS */
|
||||
.pc .controls .checker::before {
|
||||
border: 1px solid var(--color-controls-button-border);
|
||||
}
|
||||
|
||||
.pc .controls .checker.checked::before {
|
||||
color: var(--color-controls-button-text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FORMATTING STUFF */
|
||||
|
||||
.pc {
|
||||
/*height: 400px;
|
||||
height: 99vh;*/
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
padding: 1em;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
/* grid-template-columns: max-content auto max-content; */
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.pc .grid-fullwidth{
|
||||
grid-column: 1 / span 3;
|
||||
}
|
||||
|
||||
.pc .pc-main {
|
||||
width: 100%;
|
||||
grid-column: 1 / span 3;
|
||||
}
|
||||
|
||||
.pc .pc-main > div {
|
||||
/*height: 400px;
|
||||
height: 99vh;*/
|
||||
width: 100%;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
padding: 1em 0;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
/* grid-template-columns: max-content auto max-content; */
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.pc .section {
|
||||
min-height: 25em;
|
||||
max-height: calc(80vh - 8em);
|
||||
min-width: 20%;
|
||||
|
||||
box-sizing: border-box;
|
||||
padding: 2.5em 1em 1em 1em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
position: relative;
|
||||
/*top: 0;
|
||||
left: 0;*/
|
||||
}
|
||||
|
||||
.pc .section h1.header {
|
||||
font-size: 1.2em;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 4px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.pc .row {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.pc .scroller {
|
||||
overflow-x: auto;
|
||||
overflow-y: scroll;
|
||||
|
||||
/*position: relative;*/
|
||||
|
||||
/* max-height: 60%; */
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
margin: 1em 0 0 0;
|
||||
}
|
||||
|
||||
/*.pc .scroller:last-child {
|
||||
margin-bottom: -1em;
|
||||
}*/
|
||||
|
||||
.pc .scroller table {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head {
|
||||
position: sticky;
|
||||
top: -2px;
|
||||
left: 0;
|
||||
/*height: 1em;*/
|
||||
/*padding: 1em;*/
|
||||
font-size: .8em;
|
||||
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.pc .scroller table thead th {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: min-content;
|
||||
}
|
||||
.pc .scroller table thead th:last-child {
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head.shrunk {
|
||||
/*height: .5rem;*/
|
||||
/*font-size: .8em;*/
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head th {
|
||||
padding: .2em 3px;
|
||||
transition: 0.2s;
|
||||
text-align: center;
|
||||
/*border: 1px solid black !important;*/
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head.shrunk th {
|
||||
/*padding-top: .2em;
|
||||
padding-bottom: .2em;*/
|
||||
}
|
||||
|
||||
.pc .scroller table .num {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pc .scroller table td {
|
||||
padding: 6px 3px;
|
||||
vertical-align: baseline;
|
||||
/*border: 1px solid black !important;*/
|
||||
}
|
||||
|
||||
.pc .scroller table tr td:first-child {
|
||||
padding: 12px 8px;
|
||||
}
|
||||
|
||||
.pc .scroller table tr.empty td:first-child {
|
||||
padding: 3px 8px;
|
||||
}
|
||||
|
||||
.pc .cu .scroller table tr.empty select {
|
||||
padding: 3px 8px;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.pc .scroller table tr td :last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pc .scroller tr:first-child td {
|
||||
padding-top: 1.5rem !important;
|
||||
}
|
||||
|
||||
/*.pc .ram .comment {
|
||||
padding: 12px 5px;
|
||||
}*/
|
||||
|
||||
.pc .scroller table tbody button:last-child {
|
||||
text-decoration: none;
|
||||
text-transform: none;
|
||||
height: max-content;
|
||||
line-height: 2em;
|
||||
font-weight: normal;
|
||||
font-size: inherit;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
th.address {
|
||||
width: 5rem;
|
||||
padding-left: 8px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.pc input[type=number] {
|
||||
margin: 0 .5em 0 0;
|
||||
padding: 0 .25em;
|
||||
height: 2.5rem;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.pc input[type=number].instruction {
|
||||
width: 4em !important;
|
||||
}
|
||||
|
||||
.pc input[type=number].address {
|
||||
width: 5em !important;
|
||||
}
|
||||
|
||||
|
||||
/* CONTROLS */
|
||||
.pc .controls > :not(:last-child) {
|
||||
margin-right: 0.75em;
|
||||
}
|
||||
|
||||
.pc .controls .checker {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding-left: 3em;
|
||||
}
|
||||
|
||||
.pc .controls .checker label {
|
||||
display: inline;
|
||||
/*font-size: 0.8em;*/
|
||||
white-space: initial;
|
||||
white-space: break-spaces;
|
||||
text-transform: none;
|
||||
width: 6em;
|
||||
width: min-content;
|
||||
vertical-align: middle;
|
||||
line-height: .9em;
|
||||
|
||||
margin: 0;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pc .controls input[type=checkbox]{
|
||||
display: none;
|
||||
margin-left: -1em;
|
||||
margin-right: 1em;
|
||||
opacity: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.pc .controls .checker::before{
|
||||
content: "✔";
|
||||
display: inline-block;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
color: rgba(0,0,0,0);
|
||||
border-radius: 4px;
|
||||
vertical-align: middle;
|
||||
margin: 0 .5em 0 -1em;
|
||||
|
||||
line-height: 1.8rem;
|
||||
font-size: 1.4em;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* END CONTROLS */
|
||||
|
||||
/* RAM */
|
||||
|
||||
.pc .ram .scroller {
|
||||
/* height: 100%; */
|
||||
/* padding: 0.2em; */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pc .ram .scroller table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pc .ram input {
|
||||
background-color: var(--color-table-ram-select);
|
||||
color: var(--color-table-ram-select-text);
|
||||
border-color: var(--color-table-ram-select-border);
|
||||
}
|
||||
|
||||
.pc .ram table tr td:nth-child(2){
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pc .ram .scroller table tbody tr:last-child button{
|
||||
background-color: var(--color-table-ram-select);
|
||||
color: var(--color-table-ram-select-text);
|
||||
border-color: var(--color-table-ram-button-border);
|
||||
width: 9.5em;
|
||||
height: 2.5rem;
|
||||
padding: 2px 1px;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.pc .ram .ram-entry:last-child {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.pc .ram .comment input{
|
||||
border: none;
|
||||
margin: 0;
|
||||
font-size: .8em;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* CONTROL UNIT */
|
||||
|
||||
.pc .cu p {
|
||||
margin: 0 0 .2em 0;
|
||||
}
|
||||
|
||||
.pc .cu .scroller table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pc .cu .input-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 0 0 .5em 0;
|
||||
}
|
||||
|
||||
.pc .cu .input-row:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pc .cu input {
|
||||
color: var(--color-cu-text);
|
||||
border-color: var(--color-cu-text);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.pc .cu input[type=number] {
|
||||
width: 9.5em;
|
||||
}
|
||||
|
||||
.pc .cu label {
|
||||
display: inline;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.pc .cu select{
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
|
||||
background-color: var(--color-table-cu-select);
|
||||
color: var(--color-table-cu-select-text);
|
||||
border: 1px solid var(--color-table-cu-select-border);
|
||||
}
|
||||
|
||||
.pc .cu .scroller table tbody tr:last-child button {
|
||||
background-color: var(--color-table-cu-select);
|
||||
color: var(--color-table-cu-select-text);
|
||||
border: 1px solid var(--color-table-cu-button-border);
|
||||
|
||||
width: 100%;
|
||||
height: min-content;
|
||||
padding: 3px 15px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.pc .cu .scroller table tr td:first-child {
|
||||
padding: 12px 12px 12px 8px;
|
||||
}
|
||||
|
||||
.pc .cu button,
|
||||
.pc .cu .button {
|
||||
height: 2.5rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
color: var(--color-cu-text);
|
||||
border-color: var(--color-cu-text);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.pc .modal .download-button {
|
||||
display: block;
|
||||
margin-bottom: 2em;
|
||||
padding: 2px 15px;
|
||||
font-weight: normal;
|
||||
font-size: inherit;
|
||||
height: min-content;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.pc .action-button {
|
||||
width: 8em;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.pc .cu .input-group button {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
/* ALU */
|
||||
.pc .alu input, .pc .alu .button, .pc .alu button{
|
||||
color: var(--color-alu-text);
|
||||
border-color: var(--color-alu-text);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.pc .alu button {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.pc .alu button:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* BUSSES */
|
||||
|
||||
.pc .databus,
|
||||
.pc .addressbus{
|
||||
/*position: relative;*/
|
||||
text-align: left;
|
||||
|
||||
margin: 0;
|
||||
padding: .75em .5em;
|
||||
}
|
||||
.pc .databus .label,
|
||||
.pc .addressbus .label {
|
||||
/* position: absolute; */
|
||||
/* left: .5em; */
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.pc .addressbus input {
|
||||
color: var(--color-addressbus-text);
|
||||
border-color: var(--color-addressbus-text);
|
||||
background-color: var(--color-addressbus);
|
||||
}
|
||||
|
||||
.pc .databus input {
|
||||
color: var(--color-databus-text);
|
||||
border-color: var(--color-databus-text);
|
||||
background-color: var(--color-databus);
|
||||
}
|
||||
|
||||
.pc .addressbus {
|
||||
margin-bottom: 1em;
|
||||
|
||||
background-color: var(--color-addressbus);
|
||||
color: var(--color-addressbus-text);
|
||||
}
|
||||
|
||||
.pc .databus {
|
||||
margin-top: 2em;
|
||||
|
||||
background-color: var(--color-databus);
|
||||
color: var(--color-databus-text);
|
||||
}
|
||||
|
||||
/* ARROWS */
|
||||
.pc .arrow {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
width: 3rem;
|
||||
height: 5rem;
|
||||
|
||||
/* transform: rotate(90deg) translate(1.5rem, 2.5rem) ; */
|
||||
--transformation: translate(0, 3rem);
|
||||
transform: var(--transformation);
|
||||
-moz-transform: var(--transformation);
|
||||
-webkit-transform: var(--transformation);
|
||||
-o-transform: var(--transformation);
|
||||
|
||||
z-index: 100;
|
||||
|
||||
font-size: 0.5em;
|
||||
color: var(--color-arrow-text);
|
||||
background-color: var(--color-arrow);
|
||||
}
|
||||
|
||||
.pc .arrow.down {
|
||||
left: 25%;
|
||||
}
|
||||
|
||||
.pc .arrow.up {
|
||||
left: 75%;
|
||||
--transformation: rotate(180deg) translate(0, -4.5rem);
|
||||
transform: var(--transformation);
|
||||
-moz-transform: var(--transformation);
|
||||
-webkit-transform: var(--transformation);
|
||||
-o-transform: var(--transformation);
|
||||
}
|
||||
.pc .arrow.up > :nth-child(1){
|
||||
/* transform: rotate(90deg) translate(0rem, 2rem); */
|
||||
--transformation: rotate(180deg);
|
||||
|
||||
transform: var(--transformation);
|
||||
-moz-transform: var(--transformation);
|
||||
-webkit-transform: var(--transformation);
|
||||
-o-transform: var(--transformation);
|
||||
}
|
||||
|
||||
.pc .arrow.up ~ .arrow.up {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.pc .arrow.up ~ .arrow.up ~ .arrow.up {
|
||||
left: 25%;
|
||||
}
|
||||
|
||||
.pc .arrow.top {
|
||||
bottom: auto;
|
||||
top: -6rem;
|
||||
}
|
||||
|
||||
|
||||
.pc .arrow > :nth-child(1) {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.1em;
|
||||
font-weight: 600;
|
||||
color: var(--color-arrow-text) !important;
|
||||
background-color: var(--color-arrow) !important;
|
||||
border-color: var(--color-arrow-text) !important;
|
||||
text-transform: none;
|
||||
padding: 2px 10px;
|
||||
margin: 0;
|
||||
/* transform: rotate(-90deg) translate(0rem, -2rem); */
|
||||
|
||||
white-space: normal;
|
||||
height: min-content;
|
||||
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.pc .arrow > :nth-child(1) *{
|
||||
color: var(--color-arrow-text);
|
||||
display: block;
|
||||
white-space: break-spaces;
|
||||
}
|
||||
|
||||
.pc .arrow > :nth-child(1):hover, .pc .arrow > :nth-child(1) *:hover {
|
||||
color: var(--color-arrow-text-hover);
|
||||
}
|
||||
|
||||
.pc .arrow > :nth-child(2) {
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
border-left: 2.5rem solid transparent;
|
||||
border-right: 2.5rem solid transparent;
|
||||
border-top: 2rem solid var(--color-arrow);
|
||||
border-bottom: 0rem solid transparent;
|
||||
|
||||
position: absolute;
|
||||
left: -1rem;
|
||||
bottom: -2rem;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* MODALS */
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.modal.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal-card {
|
||||
z-index: 1500;
|
||||
display: block;
|
||||
width: 40em;
|
||||
min-width: 45vw;
|
||||
min-height: 5em;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
|
||||
padding: 2.5em 2em 1em 2em;
|
||||
|
||||
background-color: var(--color-modal);
|
||||
color: var(--color-modal-text);
|
||||
}
|
||||
|
||||
.modal > :first-child {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-color: var(--color-modal-shadow);
|
||||
}
|
||||
|
||||
.modal .modal-close {
|
||||
position: absolute;
|
||||
top: .5em;
|
||||
right: .5em;
|
||||
|
||||
}
|
||||
|
||||
.modal .modal-close::before {
|
||||
content: "❌";
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal .scroller table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-group > *{
|
||||
margin-right: 0.5em !important;
|
||||
}
|
||||
.input-group :last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
||||
@media(max-width: 1000px){
|
||||
.pc{
|
||||
grid-template-rows: auto max-content auto;
|
||||
justify-items: center;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.pc .section {
|
||||
grid-column: 2;
|
||||
width: 100%;
|
||||
|
||||
min-height: 25rem;
|
||||
max-height: 50rem;
|
||||
}
|
||||
|
||||
.pc .grid-fullwidth.grid-addressbus,
|
||||
.pc .grid-fullwidth.grid-databus {
|
||||
--width: 5rem;
|
||||
--text-height: 35rem;
|
||||
--margin-side: 2rem;
|
||||
|
||||
width: var(--width);
|
||||
box-sizing: border-box;
|
||||
grid-row: 2 / span 3;
|
||||
|
||||
position: relative;
|
||||
padding-bottom: var(--text-height);
|
||||
}
|
||||
|
||||
.pc .grid-fullwidth.grid-addressbus {
|
||||
grid-column: 1;
|
||||
|
||||
background-color: var(--color-addressbus);
|
||||
color: var(--color-addressbus-text);
|
||||
|
||||
justify-self: flex-end;
|
||||
margin-right: var(--margin-side);
|
||||
}
|
||||
.pc .grid-fullwidth.grid-databus {
|
||||
grid-column: 3;
|
||||
|
||||
background-color: var(--color-databus);
|
||||
color: var(--color-databus-text);
|
||||
|
||||
justify-self: flex-start;
|
||||
margin-left: var(--margin-side);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pc .grid-fullwidth.grid-addressbus > *,
|
||||
.pc .grid-fullwidth.grid-databus > * {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
height: var(--width);
|
||||
width: var(--text-height);
|
||||
|
||||
--transformation: rotate(-90deg) translate( calc(var(--width) / 2 - 50%), calc( 50% - var(--text-height) / 2));
|
||||
transform: var(--transformation);
|
||||
-moz-transform: var(--transformation);
|
||||
-webkit-transform: var(--transformation);
|
||||
-o-transform: var(--transformation);
|
||||
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.pc .controls.grid-fullwidth {
|
||||
grid-column: 1 / span 3;
|
||||
}
|
||||
|
||||
|
||||
.pc .arrow.down{
|
||||
left: inherit;
|
||||
right: 0;
|
||||
bottom: 25%;
|
||||
--transformation: rotate(-90deg) translate(0, 1rem);
|
||||
}
|
||||
.pc .arrow.down > :nth-child(1) {
|
||||
--transformation: rotate(90deg);
|
||||
|
||||
transform: var(--transformation);
|
||||
-moz-transform: var(--transformation);
|
||||
-webkit-transform: var(--transformation);
|
||||
-o-transform: var(--transformation);
|
||||
}
|
||||
|
||||
.pc .arrow.up{
|
||||
left: inherit;
|
||||
right: 0;
|
||||
top: 25%;
|
||||
--transformation: rotate(90deg) translate(0, -2.5rem);
|
||||
}
|
||||
.pc .arrow.up > :nth-child(1) {
|
||||
--transformation: rotate(-90deg);
|
||||
}
|
||||
|
||||
.pc .arrow.top {
|
||||
right: inherit;
|
||||
left: -4.5rem !important;
|
||||
top: 25%;
|
||||
}
|
||||
|
||||
.pc .arrow.arrow2{
|
||||
top: 75%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.pc .alu {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media(max-width: 800px){
|
||||
.pc .cu .input-row {
|
||||
display: block;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.pc .cu .input-row label {
|
||||
display: block;
|
||||
}
|
||||
}
|
296
out/css/roller.css
Normal file
296
out/css/roller.css
Normal file
@ -0,0 +1,296 @@
|
||||
|
||||
/*
|
||||
Roller
|
||||
*/
|
||||
|
||||
* {
|
||||
--loaderDivCol: #eee;
|
||||
|
||||
--circD: 1rem;
|
||||
--circ6D: 6rem;
|
||||
--circR: 0.5rem;
|
||||
|
||||
--scrollbarBG: #f5f5f5;
|
||||
--thumbBG: #C1DCEA;
|
||||
}
|
||||
|
||||
#elm {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.roller {
|
||||
margin: 2.5rem 0;
|
||||
}
|
||||
|
||||
@keyframes loading0 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading2 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
24.97% {
|
||||
opacity: 0;
|
||||
}
|
||||
25.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
37.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
99.95% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading3 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
37.47% {
|
||||
opacity: 0;
|
||||
}
|
||||
37.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
49.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
50.02% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading5 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
62.47% {
|
||||
opacity: 0;
|
||||
}
|
||||
62.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
74.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
75.02% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading6 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
74.97% {
|
||||
opacity: 0;
|
||||
}
|
||||
75.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
87.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
position: relative;
|
||||
height: var(--circD);
|
||||
width: var(--circ6D);
|
||||
padding: var(--circR) 0;
|
||||
box-sizing: border-box;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
.loader :nth-child(n) {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
box-sizing: border-box;
|
||||
width: 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.loader div::before,
|
||||
.loader div::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--circD);
|
||||
height: var(--circD);
|
||||
border: 1px solid var(--loaderDivCol);
|
||||
background: var(--loaderDivCol);
|
||||
border-radius: 100%;
|
||||
|
||||
position: absolute;
|
||||
top: var(--circR);
|
||||
}
|
||||
|
||||
.loader div::before {
|
||||
left: calc(-var(--circR));
|
||||
}
|
||||
.loader div::after {
|
||||
right: calc(-var(--circR));
|
||||
}
|
||||
|
||||
|
||||
.loader :nth-child(1) {
|
||||
width: 66.66%;
|
||||
/*^{animation "loading5" (timeDiv 0)}*/
|
||||
|
||||
--timing: "cubic-bezier(.39,.58,.57,1)";
|
||||
--fullCycle: "4s";
|
||||
--animation: "loading5" var(--fullCycle) var(--timing) calc(-(var(--fullCycle) * 1 / 8 )) infinite;
|
||||
-webkit-animation: var(--animation);
|
||||
-moz-animation: var(--animation);
|
||||
-ms-animation: var(--animation);
|
||||
-o-animation: var(--animation);
|
||||
animation: var(--animation);
|
||||
|
||||
/*- fromInteger fullDiv * (1 - (fromInteger a) / 8 )*/
|
||||
}
|
||||
.loader :nth-child(2) {
|
||||
width: 66.66%;
|
||||
margin-left: 0;
|
||||
/*^{animation "loading2" (timeDiv 0)}*/
|
||||
}
|
||||
.loader :nth-child(3) {
|
||||
width: 33.33%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading2" (timeDiv 1)}*/
|
||||
}
|
||||
.loader :nth-child(4) {
|
||||
width: 66.66%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading6" (timeDiv 2)}*/
|
||||
}
|
||||
|
||||
|
||||
.loader :nth-child(5) {
|
||||
width: 100%
|
||||
/*^{animation "loading6" (timeDiv 3)} */
|
||||
}
|
||||
.loader :nth-child(6) {
|
||||
width: 100%
|
||||
/*^{animation "loading3" (timeDiv 3)}*/
|
||||
}
|
||||
.loader :nth-child(7) {
|
||||
width: 33.33%
|
||||
/*^{animation "loading3" (timeDiv 4)}*/
|
||||
}
|
||||
.loader :nth-child(8) {
|
||||
width: 66.66%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading3" (timeDiv 5)}*/
|
||||
}
|
||||
.loader :nth-child(9) {
|
||||
width: 33.33%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading5" (timeDiv 6)}*/
|
||||
}
|
||||
.loader :nth-child(10) {
|
||||
width: 33.33%
|
||||
margin-left: 66.66%
|
||||
/*^{animation "loading5" (timeDiv 7)} */
|
||||
}
|
@ -1,514 +1,132 @@
|
||||
/* COLORS */
|
||||
body {
|
||||
background-color: var(--color-body);
|
||||
color: var(--color-body-text);
|
||||
background-color: var(--color-body);
|
||||
color: var(--color-body-text);
|
||||
}
|
||||
|
||||
.pc .addressbus {
|
||||
background-color: var(--color-addressbus);
|
||||
color: var(--color-addressbus-text);
|
||||
code {
|
||||
background-color: var(--color-code);
|
||||
border-color: var(--color-code-text);
|
||||
color: var(--color-code-text);
|
||||
}
|
||||
|
||||
.pc .databus {
|
||||
background-color: var(--color-databus);
|
||||
color: var(--color-databus-text);
|
||||
.noscript {
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pc .ram {
|
||||
background-color: var(--color-ram);
|
||||
color: var(--color-ram-text);
|
||||
.spacer {
|
||||
height: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pc .cu {
|
||||
background-color: var(--color-cu);
|
||||
color: var(--color-cu-text);
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.pc .alu {
|
||||
background-color: var(--color-alu);
|
||||
color: var(--color-alu-text);
|
||||
section.fullheight {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.pc .section h1.header {
|
||||
background-color: var(--color-header);
|
||||
color: var(--color-header-text);
|
||||
footer{
|
||||
margin-top: 20rem;
|
||||
}
|
||||
|
||||
|
||||
/* TABLE COLORS */
|
||||
.pc .ram .scroller table thead.head th {
|
||||
background-color: var(--color-table-ram-head);
|
||||
color: var(--color-table-ram-head-text);
|
||||
}
|
||||
|
||||
.pc .cu .scroller table thead.head th {
|
||||
background-color: var(--color-table-cu-head);
|
||||
color: var(--color-table-cu-head-text);
|
||||
}
|
||||
|
||||
.pc .scroller table tr td {
|
||||
background-color: var(--color-table-row);
|
||||
color: var(--color-table-text);
|
||||
border-bottom: 1px solid var(--color-table-border);
|
||||
}
|
||||
|
||||
.pc .scroller table tr:nth-child(even) td{
|
||||
background-color: var(--color-table-row-alt);
|
||||
}
|
||||
|
||||
.pc .scroller table tr.empty td {
|
||||
color: var(--color-table-text-empty);
|
||||
}
|
||||
|
||||
.pc .ram .scroller table tr.current td {
|
||||
background-color: var(--color-table-ram-highlight);
|
||||
color: var(--color-table-ram-highlight-text);
|
||||
}
|
||||
|
||||
.pc .cu .scroller table tr.current td {
|
||||
background-color: var(--color-table-cu-highlight);
|
||||
color: var(--color-table-cu-highlight-text);
|
||||
}
|
||||
|
||||
|
||||
/* CONTROLS COLORS */
|
||||
.controls button, .controls .button {
|
||||
/* background-color: whitesmoke; */
|
||||
color: var(--color-controls-button-text);
|
||||
border-color: var(--color-controls-button-border);
|
||||
}
|
||||
.controls button:hover, .controls .button:hover{
|
||||
color: var(--color-controls-button-text-hover);
|
||||
}
|
||||
|
||||
.pc .controls .checker::before {
|
||||
border: 1px solid var(--color-controls-button-border);
|
||||
}
|
||||
|
||||
.pc .controls .checker.checked::before {
|
||||
color: var(--color-controls-button-text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FORMATTING STUFF */
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pc {
|
||||
height: 400px;
|
||||
height: 99vh;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
padding: 1em;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
/* grid-template-columns: max-content auto max-content; */
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.pc .grid-fullwidth{
|
||||
grid-column: 1 / span 3;
|
||||
}
|
||||
|
||||
.pc .section {
|
||||
min-height: 25em;
|
||||
max-height: calc(80vh - 8em);
|
||||
min-width: 20%;
|
||||
|
||||
box-sizing: border-box;
|
||||
padding: 2.5em 1em 1em 1em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
position: relative;
|
||||
/*top: 0;
|
||||
left: 0;*/
|
||||
}
|
||||
|
||||
.pc .section h1.header {
|
||||
font-size: 1.2em;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 4px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.pc .row {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.pc .scroller {
|
||||
overflow-x: auto;
|
||||
overflow-y: scroll;
|
||||
|
||||
/*position: relative;*/
|
||||
|
||||
/* max-height: 60%; */
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
margin: 1em 0 0 0;
|
||||
}
|
||||
|
||||
.pc .scroller:last-child {
|
||||
margin-bottom: -1em;
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head {
|
||||
position: sticky;
|
||||
top: -2px;
|
||||
left: 0;
|
||||
height: 1em;
|
||||
padding: 1em;
|
||||
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.pc .scroller table thead th {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head.shrunk {
|
||||
height: .5em;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head th {
|
||||
padding: 12px 4px 12px 15px;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.pc .scroller table thead.head.shrunk th {
|
||||
padding-top: .2em;
|
||||
padding-bottom: .2em;
|
||||
}
|
||||
|
||||
.pc .scroller table .num {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.pc .scroller table td:first-child,
|
||||
.pc .scroller table td:last-child {
|
||||
padding: 12px 15px;
|
||||
}
|
||||
|
||||
.pc .scroller table tr.empty td {
|
||||
padding: 3px 15px;
|
||||
}
|
||||
|
||||
.pc .scroller table tbody button:last-child {
|
||||
text-decoration: none;
|
||||
text-transform: none;
|
||||
height: max-content;
|
||||
line-height: 2em;
|
||||
font-weight: normal;
|
||||
font-size: inherit;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
th.address {
|
||||
width: 5rem;
|
||||
padding-left: 8px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.pc input[type=number] {
|
||||
margin: 0 .5em 0 0;
|
||||
padding: 0 .25em;
|
||||
height: 1.5em;
|
||||
line-height: 1em;
|
||||
}
|
||||
.dragDrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
|
||||
/* CONTROLS */
|
||||
.pc .controls button,
|
||||
.pc .controls .button{
|
||||
text-transform: none !important;
|
||||
font-weight: 600;
|
||||
height: 2.5em;
|
||||
line-height: 1em;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
padding: 0.25em 2em;
|
||||
}
|
||||
|
||||
.pc .controls > :not(:last-child) {
|
||||
margin-right: 0.75em;
|
||||
}
|
||||
|
||||
.pc .controls .checker {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding-left: 3em;
|
||||
}
|
||||
|
||||
.pc .controls .checker label {
|
||||
display: inline;
|
||||
/*font-size: 0.8em;*/
|
||||
white-space: initial;
|
||||
white-space: break-spaces;
|
||||
text-transform: none;
|
||||
width: 6em;
|
||||
width: min-content;
|
||||
vertical-align: middle;
|
||||
line-height: .9em;
|
||||
|
||||
margin: 0;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pc .controls input[type=checkbox]{
|
||||
display: none;
|
||||
margin-left: -1em;
|
||||
margin-right: 1em;
|
||||
opacity: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.pc .controls .checker::before{
|
||||
content: "✔";
|
||||
display: inline-block;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
color: rgba(0,0,0,0);
|
||||
border-radius: 4px;
|
||||
vertical-align: middle;
|
||||
margin: 0 .5em 0 -1em;
|
||||
|
||||
line-height: 1.8rem;
|
||||
font-size: 1.4em;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* END CONTROLS */
|
||||
|
||||
/* RAM */
|
||||
|
||||
.pc .ram .scroller {
|
||||
/* height: 100%; */
|
||||
/* padding: 0.2em; */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pc .ram .scroller table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pc .ram input[type=number] {
|
||||
background-color: var(--color-table-ram-select);
|
||||
color: var(--color-table-ram-select-text);
|
||||
border-color: var(--color-table-ram-select-border);
|
||||
}
|
||||
|
||||
.pc .ram input[type=number].instruction {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
.pc .ram input[type=number].address {
|
||||
width: 7em;
|
||||
}
|
||||
|
||||
.pc .ram table tr td:nth-child(2){
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.pc .ram .scroller table tbody button:last-child{
|
||||
background-color: var(--color-table-ram-select);
|
||||
color: var(--color-table-ram-select-text);
|
||||
border-color: var(--color-table-ram-select-border);
|
||||
}
|
||||
|
||||
|
||||
/* CONTROL UNIT */
|
||||
|
||||
.pc .cu p {
|
||||
margin: 0 0 .2em 0;
|
||||
}
|
||||
|
||||
.pc .cu .scroller table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pc .cu .input-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
margin: 0 0 .5em 0;
|
||||
}
|
||||
|
||||
.pc .cu .input-row:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pc .cu input {
|
||||
color: var(--color-cu-text);
|
||||
border-color: var(--color-cu-text);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.pc .cu label {
|
||||
display: inline;
|
||||
}
|
||||
background-color: var(--color-dragdrop);
|
||||
color: var(--color-dragdrop-text);
|
||||
|
||||
.pc .cu select{
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 1000;
|
||||
|
||||
background-color: var(--color-table-cu-select);
|
||||
color: var(--color-table-cu-select-text);
|
||||
border: 1px solid var(--color-table-cu-select-border);
|
||||
}
|
||||
|
||||
.pc .cu .scroller table tbody button:last-child {
|
||||
background-color: var(--color-table-cu-select);
|
||||
color: var(--color-table-cu-select-text);
|
||||
border: 1px solid var(--color-table-cu-select-border);
|
||||
}
|
||||
|
||||
/* ALU */
|
||||
.pc .alu input {
|
||||
color: var(--color-alu-text);
|
||||
border-color: var(--color-alu-text);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* BUSSES */
|
||||
|
||||
.pc .databus,
|
||||
.pc .addressbus{
|
||||
/*position: relative;*/
|
||||
text-align: left;
|
||||
|
||||
margin: 0;
|
||||
padding: .75em .5em;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
.pc .databus .label,
|
||||
.pc .addressbus .label {
|
||||
/* position: absolute; */
|
||||
/* left: .5em; */
|
||||
margin-right: 1em;
|
||||
--transition: all 0.25s ease-in-out 0s;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.pc .addressbus input {
|
||||
color: var(--color-addressbus-text);
|
||||
border-color: var(--color-addressbus-text);
|
||||
background-color: var(--color-addressbus);
|
||||
.dragDrop.hover, .dragDrop.loading {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.pc .databus input {
|
||||
color: var(--color-databus-text);
|
||||
border-color: var(--color-databus-text);
|
||||
background-color: var(--color-databus);
|
||||
.dragDrop.loading {
|
||||
background-color: var(--color-dragdrop-processing);
|
||||
color: var(--color-dragdrop-processing-text);
|
||||
}
|
||||
|
||||
.pc .addressbus {
|
||||
margin-bottom: 1em;
|
||||
.dragDrop .loader {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pc .databus {
|
||||
margin-top: 2em;
|
||||
.dragDrop.loading .loader {
|
||||
display: block;
|
||||
}
|
||||
/*.dragDrop.loading p:first-child::before {
|
||||
content: "⋮";
|
||||
|
||||
/* ARROWS */
|
||||
.arrow {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
|
||||
width: 3rem;
|
||||
height: 5rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
transform: rotate(0);
|
||||
}*/
|
||||
|
||||
/* transform: rotate(90deg) translate(1.5rem, 2.5rem) ; */
|
||||
transform: translate(0, 3rem);
|
||||
z-index: 100;
|
||||
|
||||
font-size: 0.5em;
|
||||
color: var(--color-arrow-text);
|
||||
background-color: var(--color-arrow);
|
||||
.pc .examples-list {
|
||||
border: 1px solid var(--color-controls-button-border);
|
||||
margin: 0;
|
||||
border-radius: 0 4px 4px 4px;
|
||||
}
|
||||
|
||||
.arrow.down {
|
||||
left: 25%;
|
||||
.pc .examples-list table td:first-child {
|
||||
padding: 12px 8px 12px 15px;
|
||||
}
|
||||
|
||||
.arrow.up {
|
||||
left: 75%;
|
||||
transform: rotate(180deg) translate(0, -4.5rem);
|
||||
}
|
||||
.arrow.up > :nth-child(1){
|
||||
/* transform: rotate(90deg) translate(0rem, 2rem); */
|
||||
transform: rotate(180deg);
|
||||
.pc .example-scroller-label {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
border: 1px solid var(--color-controls-button-border);
|
||||
border-bottom-style: none;
|
||||
color: var(--color-controls-button-text);
|
||||
border-radius: 4px 4px 0 0;
|
||||
padding: 2px 15px;
|
||||
}
|
||||
|
||||
.arrow.up.arrow2 {
|
||||
left: 50%;
|
||||
button, .button {
|
||||
/* background-color: whitesmoke; */
|
||||
color: var(--color-controls-button-text);
|
||||
border-color: var(--color-controls-button-border);
|
||||
}
|
||||
|
||||
.arrow.top {
|
||||
bottom: auto;
|
||||
top: -6rem;
|
||||
button:hover, .button:hover{
|
||||
color: var(--color-controls-button-text-hover);
|
||||
}
|
||||
|
||||
|
||||
.arrow > :nth-child(1) {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.1em;
|
||||
font-weight: 600;
|
||||
color: var(--color-arrow-text);
|
||||
background-color: var(--color-arrow);
|
||||
border-color: var(--color-arrow-text);
|
||||
text-transform: none;
|
||||
padding: 2px 10px;
|
||||
margin: 0;
|
||||
/* transform: rotate(-90deg) translate(0rem, -2rem); */
|
||||
|
||||
white-space: normal;
|
||||
height: min-content;
|
||||
.button-group {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.arrow > :nth-child(1) *{
|
||||
color: var(--color-arrow-text);
|
||||
display: block;
|
||||
white-space: break-spaces;
|
||||
.button-group > * {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.arrow > :nth-child(1):hover, .arrow > :nth-child(1) *:hover {
|
||||
color: var(--color-arrow-text-hover);
|
||||
.button-group :first-child {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.arrow > :nth-child(2) {
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
border-left: 2.5rem solid transparent;
|
||||
border-right: 2.5rem solid transparent;
|
||||
border-top: 2rem solid var(--color-arrow);
|
||||
border-bottom: 0rem solid transparent;
|
||||
|
||||
position: absolute;
|
||||
left: -1rem;
|
||||
bottom: -2rem;
|
||||
|
||||
.button-group :last-child {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* HELPERS */
|
||||
.text-center {
|
||||
text-align: center;
|
||||
|
7180
out/elm.js
7180
out/elm.js
File diff suppressed because it is too large
Load Diff
23
out/examples-list.json
Normal file
23
out/examples-list.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"available":
|
||||
[
|
||||
{
|
||||
"title": "A simple Counter",
|
||||
"version": "0.3",
|
||||
"url": "examples/simple-counter.json",
|
||||
"enabled": 1
|
||||
},
|
||||
{
|
||||
"title": "Adding 2 numbers together",
|
||||
"version": "0.2",
|
||||
"url": "examples/adding.json",
|
||||
"enabled": 1
|
||||
},
|
||||
{
|
||||
"title": "Empty Canvas",
|
||||
"version": "0.1",
|
||||
"url": "examples/empty.json",
|
||||
"enabled": 1
|
||||
}
|
||||
]
|
||||
}
|
1
out/examples/adding.json
Normal file
1
out/examples/adding.json
Normal file
@ -0,0 +1 @@
|
||||
{"model-version":"3","pc_model":{"pc":{"addressBus":0,"dataBus":0,"instructionReg":0,"programmCounter":0,"uCounter":0,"accumulator":0,"ram":[[100013,"Load ValB to Acc"],[300000,"Acc ++"],[200013,"Store Acc to ValB"],[100012,"Load ValA"],[400000,"Acc --"],[200012,"Store Acc to ValA"],[600008,"Jmp If eq 0"],[500000,"Jmp #000"],[0,"END OF PROGRAM"],[0,""],[0,""],[0,""],[7,"ValA"],[14,"ValB + Result"],[0,""],[0,""],[0,""]]},"uCodes":["pc2ab","ram2db","db2ir","pcInc","ir2uc","n","n","n","n","n","ir2ab","ram2db","db2acc","ucReset","n","n","n","n","n","n","acc2db","ir2ab","db2ram","ucReset","n","n","n","n","n","n","accInc","ucReset","n","n","n","n","n","n","n","n","accDec","ucReset","n","n","n","n","n","n","n","n","ir2pc","ucReset","n","n","n","n","n","n","n","n","ir2pciacceq0","ucReset","n","n","n","n","n","n","n","n"]},"autoscroll":true}
|
1
out/examples/empty.json
Normal file
1
out/examples/empty.json
Normal file
@ -0,0 +1 @@
|
||||
{"model-version":"3","pc_model":{"pc":{"addressBus":0,"dataBus":0,"instructionReg":0,"programmCounter":0,"uCounter":0,"accumulator":0,"ram":[[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""]]},"uCodes":["pc2ab","ram2db","db2ir","pcInc","ir2uc","n","n","n","n","n","ir2ab","ram2db","db2acc","ucReset","n","n","n","n","n","n","acc2db","ir2ab","db2ram","ucReset","n","n","n","n","n","n","accInc","ucReset","n","n","n","n","n","n","n","n"]},"autoscroll":true}
|
1
out/examples/simple-counter.json
Normal file
1
out/examples/simple-counter.json
Normal file
@ -0,0 +1 @@
|
||||
{"model-version":"3","pc_model":{"pc":{"addressBus":0,"dataBus":0,"instructionReg":0,"programmCounter":0,"uCounter":0,"accumulator":0,"ram":[[100005,"LoadA #005"],[300000,"IncA"],[200005,"StoreA #005"],[400000,"JMP #000"],[0,""],[5,"val"],[0,""],[0,""],[0,""],[0,""],[0,""]]},"uCodes":["pc2ab","ram2db","db2ir","pcInc","ir2uc","n","n","n","n","n","ir2ab","ram2db","db2acc","ucReset","n","n","n","n","n","n","acc2db","ir2ab","db2ram","ucReset","n","n","n","n","n","n","accInc","ucReset","n","n","n","n","n","n","n","n","ir2pc","ucReset","n","n","n","n","n","n","n","n"]},"autoscroll":true}
|
10
out/icon/cross.svg
Normal file
10
out/icon/cross.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Cross" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
|
||||
<path d="M14.348,14.849c-0.469,0.469-1.229,0.469-1.697,0L10,11.819l-2.651,3.029c-0.469,0.469-1.229,0.469-1.697,0
|
||||
c-0.469-0.469-0.469-1.229,0-1.697l2.758-3.15L5.651,6.849c-0.469-0.469-0.469-1.228,0-1.697c0.469-0.469,1.228-0.469,1.697,0
|
||||
L10,8.183l2.651-3.031c0.469-0.469,1.228-0.469,1.697,0c0.469,0.469,0.469,1.229,0,1.697l-2.758,3.152l2.758,3.15
|
||||
C14.817,13.62,14.817,14.38,14.348,14.849z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 835 B |
367
out/index.html
367
out/index.html
@ -4,19 +4,23 @@
|
||||
<!-- Basic Page Needs
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta charset="utf-8" />
|
||||
<title>Zähler</title>
|
||||
<meta name="description" content="" />
|
||||
<meta name="author" content="" />
|
||||
<title>Johnny Simulator</title>
|
||||
<meta name="description" content="Web based Johhny-Simulator" />
|
||||
<meta name="author" content="Christian" />
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
|
||||
<!-- CSS
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="stylesheet" href="css/normalize.css" />
|
||||
<link rel="stylesheet" href="css/skeleton.css" />
|
||||
<link rel="stylesheet" href="css/cookie.css" />
|
||||
<link rel="stylesheet" href="css/colors-light.css">
|
||||
<link rel="stylesheet" href="css/colors-dark.css">
|
||||
<link rel="stylesheet" href="css/loader.css" />
|
||||
<link rel="stylesheet" href="css/pc.css" />
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
|
||||
<!-- Favicon
|
||||
@ -27,11 +31,360 @@
|
||||
<body>
|
||||
<!-- Primary Page Layout
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<div id="elm"></div>
|
||||
<div id="elm">
|
||||
<div class="noscript">Sorry, but this app needs Javascript to run :/</div>
|
||||
</div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<section class="container fullheight">
|
||||
<div id="langPicker">
|
||||
<button id="langPickerDE">German</button>
|
||||
<button id="langPickerEN">English</button>
|
||||
</div>
|
||||
<div id="langDE" class="hidden">
|
||||
<h1>Wie diese App funktioniert</h1>
|
||||
<p>
|
||||
Hallo, schön dass du dir diese Seite anschaust.<br>
|
||||
Damit du besser verstehst, wie diese Anwendung funktioniert, hier einmal die Basics:
|
||||
</p>
|
||||
|
||||
<h2>Kontrollknöpfe</h2>
|
||||
<p>
|
||||
Ganz oben findest du eine Reihe mit Kontrollknöpfen. Jeder Knopf hat seine eigene Funktion.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>µCycle</b>
|
||||
Mit diesem Knopf kannst du einen einzelnen Schritt im µCode ausführen.
|
||||
</li>
|
||||
<li>
|
||||
<b>Instruction</b>
|
||||
Hiermit kannst du eine ganze Instruction ausführen lassen und musst nicht durch jeden µCode Schritt einzeln durchdrücken.
|
||||
</li>
|
||||
<li>
|
||||
<b>Reset PC</b>
|
||||
Damit kannst du den PC zurücksetzten. Dabei bleibt der RAM und der µCode erhalten.
|
||||
</li>
|
||||
<li>
|
||||
<b>Autoscroll</b>
|
||||
Nachdem im RAM oder im µCode ein anderer Eintrag ausgewählt wurde, kann automatisch zum Eintrag gescrollt werden
|
||||
</li>
|
||||
<li>
|
||||
<b>Load Example</b>
|
||||
Mit diesem Knopf kannst du ein Beispielprogramm in den PC laden. Dabei wird dein momentanes Programm überschrieben.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Bausteine</h2>
|
||||
<p>
|
||||
Der Computer ist in mehrere Bausteine aufgeteilt. Jeder Baustein hat eine eigene spezielle Funktion. Ein echter Computer ist natürlich deutlich komplizierter, aber so ist der PC deutlich verständlicher.
|
||||
</p>
|
||||
|
||||
<h3>RAM</h3>
|
||||
<p>
|
||||
Im Arbeitsspeicher wird das Programm gespeichert. Jeder Eintrag ist dabei in ein Low-Byte und ein High-Byte unterteilt. Dadurch kann man in einem Eintrag die Instruktion und Addresse einfacher unterscheiden.<br>
|
||||
<a href="#befehl">Siehe Befehle</a>
|
||||
</p>
|
||||
|
||||
<h3>Control Unit</h3>
|
||||
<p>
|
||||
Wie der Name es schon sagt, steuert und verwaltet die Control Unit alle Vorgänge im Computer. Das passiert dadurch, dass eine Instruktion in viele kleine µCodes aufgeteilt wird.
|
||||
</p><p>
|
||||
Diese µCodes sind in der Tabelle aufgeführt. Jede Instruktion besteht hier aus bis zu 10 µCodes. <br>
|
||||
Bei einem Befehl z.B. <code>001 00000</code> ist die Instruktion in den ersten drei Stellen zu finden. Dieser Wert wird dann mit 10 multipliziert und in den µCode Counter geladen. <br>
|
||||
In diesem Fall stände dann <code>0010</code> im Counter.<br>
|
||||
In der Tabelle sind dann alle Befehle für die Instruktion <code>001</code> zu finden.
|
||||
</p>
|
||||
<h3>ALU</h3>
|
||||
<p>
|
||||
Die Arithmetik Logic Unit ist hier sehr einfach aufgebaut.
|
||||
</p>
|
||||
<p>
|
||||
Sie kann den Akkumulator nur erhöhen oder erniedrigen. Dafür können Werte aber direkt vom Datenbus geladen werden.
|
||||
</p>
|
||||
<h3>Datenbus</h3>
|
||||
<p>
|
||||
Über den Datenbus können Daten und Befehle zwischen RAM, Control Unit und ALU übertragen werden.
|
||||
</p>
|
||||
<h3>Addressbus</h3>
|
||||
<p>
|
||||
Über diesen Bus kann die Control Unit steuern, welcher Wert im RAM ausgewählt wird.<br>
|
||||
Bei normalen Rechnern sind hier natürlich noch deutlich mehr Werte angeschlossen.
|
||||
</p>
|
||||
|
||||
<a id="befehl"></a>
|
||||
<h2>Befehle</h2>
|
||||
<p>
|
||||
Ein Befehl besteht aus einer Instruktion und einem Argument. Deshalb sind im RAM und im Instruction Register alle Werte separiert.
|
||||
</p>
|
||||
<pre>
|
||||
<code>
|
||||
0 0 0 0 0 0 0 0
|
||||
Instr Argument
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<h2>µCodes</h2>
|
||||
<p>
|
||||
Eine Instruktion kann nicht direkt ausgeführt werden. Deshalb wird sie durch mehrere kleine Befehle, sog. µCodes zusammengesetzt.
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>µCode</th>
|
||||
<th>Beschreibung</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>ProgCounter -> AddrBus</td>
|
||||
<td>Lade den Wert des Programm Counters in den Adressbus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InstrReg -> ProgCounter</td>
|
||||
<td>Lade das Argument des Instruktionsregisters in den Programm Counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ProgCounter ++</td>
|
||||
<td>Erhöhe den Wert des Programm Counter um 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc == 0 => InstReg -> ProgCounter</td>
|
||||
<td>Wenn der Wert des Akkumulators 0 ist, dann lade das Arggument des Instruktionsregisters in den Programm Counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ram -> DataBus</td>
|
||||
<td>Schreibe den aktuellen Wert aus den RAM auf den Datembus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DataBus -> Ram</td>
|
||||
<td>Schreibe den Wert des Datenbus in die momentane Stelle des RAM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DataBus -> InstReg</td>
|
||||
<td>Lade den Befehl vom Datenbus in das Instruktionsregister</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DataBus -> Acc</td>
|
||||
<td>Lade den Wert vom Datenbus in den Akkumulator der ALU</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc -> DataBus</td>
|
||||
<td>Schreibe den Wert vom Akkumulator auf den Datenbus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc ++</td>
|
||||
<td>Erhöhe den Wert des Akkumulators um 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc --</td>
|
||||
<td>Verringere den Wert des Akkumulators um 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InstReg -> µCounter</td>
|
||||
<td>Nehme das Argument des Befehls im Instruktionsregister, füge am Ende eine 0 an und Lade ihn in den µCounter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InstReg -> AddrBus</td>
|
||||
<td>Lade das Argument im Instruktionsregister in den Addressbus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>µCounter = 0</td>
|
||||
<td>Setzte den µCounter zurück</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Source</h1>
|
||||
<p>
|
||||
Im Moment ist dieser Code noch nicht ordentlich genug, dass es Sinn hat ihn zu veröffentlichen.
|
||||
</p>
|
||||
<p>
|
||||
Dieses Projekt ist angelehnt an den <a href="https://sourceforge.net/projects/johnnysimulator/" target="_blank">Johnny-Simulator</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div id="langEN">
|
||||
<h1>How this App works</h1>
|
||||
<p>
|
||||
Hello. In order for you to understand what this App does, I want to show you some basics of this app.
|
||||
</p>
|
||||
|
||||
<h2>Control Buttons</h2>
|
||||
<p>
|
||||
At the top of the application you can see a row of control buttons:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>µCycle</b>
|
||||
With this button you can execute a single µCode Step.
|
||||
</li>
|
||||
<li>
|
||||
<b>Instruction</b>
|
||||
This button executes a whole instruction at a time. This way you don't have to press µCycle all the time.
|
||||
</li>
|
||||
<li>
|
||||
<b>Reset PC</b>
|
||||
With this, you can reset the pc. Please note that ram und µCodes are not reset.
|
||||
</li>
|
||||
<li>
|
||||
<b>Autoscroll</b>
|
||||
After a value in RAM or in the µCodes is selected you can automatically scroll to them
|
||||
</li>
|
||||
<li>
|
||||
<b>Load Example</b>
|
||||
Click this button and select an example you want to load. This will overwrite the whole pc including ram and µCode
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Blocks</h2>
|
||||
<p>
|
||||
This computer is made up by multiple blocks like any other neumann-maschiene. Every block has it's own unique set of functions. A normal computer is much more complex than this, but the principle is the same.
|
||||
</p>
|
||||
|
||||
<h3>RAM</h3>
|
||||
<p>
|
||||
The current programm is stored in the RAM. Every entry is seperated as mentioned in <a href="#entry">entry</a>.
|
||||
</p>
|
||||
|
||||
<h3>Control Unit</h3>
|
||||
<p>
|
||||
As the name suggests, the control unit manages everything that is done. To know what needs to be done it has a list of µCodes that gets executed when a instruction is requested.
|
||||
</p><p>
|
||||
These µCodes can be found in the table. Every instruction consists of up to 10 µCodes. <br>
|
||||
When a entry is executed, the first three digits (the instruction) gets multiplied by 10. This now is written into the µCounter and the µCodes for it get's executed.
|
||||
</p><p>
|
||||
Example:<br>
|
||||
When the entry <code>001 00000</code> gets executed, the µCounter would be set to <code>0010</code>. Now every µCode starting at location <code>0010</code> in the µCodes gets executed.
|
||||
</p>
|
||||
<h3>ALU</h3>
|
||||
<p>
|
||||
The Arithmetic Logic Unit is pretty simple in this case.
|
||||
</p>
|
||||
<p>
|
||||
The ALU can only increment or decrement the accumulator. But it can read numbers from databus.
|
||||
</p>
|
||||
<h3>Databus</h3>
|
||||
<p>
|
||||
Via the Databus values and entrys can be transported between RAM, Control Unit and ALU.
|
||||
</p>
|
||||
<h3>Addressbus</h3>
|
||||
<p>
|
||||
With the addressbus the Control Unit can control which value is selected in RAM. On a normal computer there are a lot mor things attached to this bus.
|
||||
</p>
|
||||
|
||||
<a id="entry"></a>
|
||||
<h2>Entry</h2>
|
||||
<p>
|
||||
Each entry consits of a instruction and an argument. That's why the entrys in RAM and in µCodes are displayed seperatly.
|
||||
</p>
|
||||
<pre>
|
||||
<code>
|
||||
0 0 0 0 0 0 0 0
|
||||
Instr Argument
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<h2>µCodes</h2>
|
||||
<p>
|
||||
Every instruction consists of a list of µCodes. Here is an explanaition for all of them:
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>µCode</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>ProgCounter -> AddrBus</td>
|
||||
<td>Load the value from programm counter to addressbus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InstrReg -> ProgCounter</td>
|
||||
<td>Load the argument from instruction register to programm counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ProgCounter ++</td>
|
||||
<td>Increment programm counter by 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc == 0 => InstReg -> ProgCounter</td>
|
||||
<td>If the accumulator is 0 then write the argument from instruction register to programm counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ram -> DataBus</td>
|
||||
<td>Load selected value from RAM to databus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DataBus -> Ram</td>
|
||||
<td>Write value from databus to selected value in RAM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DataBus -> InstReg</td>
|
||||
<td>Write entry from databus to instruction register</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DataBus -> Acc</td>
|
||||
<td>Write value from databus to accumulator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc -> DataBus</td>
|
||||
<td>Load value from accumulator to databus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc ++</td>
|
||||
<td>Increment accumulator by 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Acc --</td>
|
||||
<td>Decrement accumulator by 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InstReg -> µCounter</td>
|
||||
<td>Take the instruction from instruction register, add a 0 at the tail and write it to µCounter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>InstReg -> AddrBus</td>
|
||||
<td>Write the argument from instruction register to addressbus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>µCounter = 0</td>
|
||||
<td>Set µCounter to 0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h1>Source</h1>
|
||||
<p>
|
||||
At the moment the code for this project isn't good enough to share it online.
|
||||
</p>
|
||||
<p>
|
||||
This project is my take on <a href="https://sourceforge.net/projects/johnnysimulator/" target="_blank">Johnny-Simulator</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p>
|
||||
Made with ☕ <br>
|
||||
© <a href="https://github.com/ChrisgammaDE" target="_blank">Christian</a>, 2021
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://yokta.de/i/impressum.html" target="_blank">Impressum</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- End Document
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<script src="elm.js"></script>
|
||||
<script src="script.js"></script>
|
||||
<script src="js/elm.js"></script>
|
||||
<script src="js/cookie.js"></script>
|
||||
<script src="js/pc.js"></script>
|
||||
<script src="js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
65
out/js/cookie.js
Normal file
65
out/js/cookie.js
Normal file
@ -0,0 +1,65 @@
|
||||
// Check if cookie banner has been accepted by running cookieAccepted()
|
||||
|
||||
// Please import cookie.css!!!!
|
||||
|
||||
function __cookie_internal_addBanner__(){
|
||||
let banner = document.createElement("div");
|
||||
let text = document.createElement("div");
|
||||
let link_datenschutz = document.createElement("a");
|
||||
let button_accept = document.createElement("button");
|
||||
let button_deny = document.createElement("button");
|
||||
|
||||
banner.classList.add("cookie-banner");
|
||||
|
||||
text.innerText =
|
||||
"In order for this computer to keep it's data after reloading,\
|
||||
this page uses cookies and localStorage. ";
|
||||
|
||||
link_datenschutz.href = "https://yokta.de/i/datenschutz.html";
|
||||
link_datenschutz.innerText = "Privacy Policy";
|
||||
link_datenschutz.target = "_blank";
|
||||
text.appendChild( link_datenschutz );
|
||||
|
||||
button_accept.innerText = "I'm ok with that"
|
||||
button_deny.innerText = "Not on my watch!"
|
||||
|
||||
button_accept.addEventListener("click", (message) => {
|
||||
localStorage.setItem("cookie", "accepted");
|
||||
let parent = message.target.parentElement;
|
||||
document.body.removeChild(parent);
|
||||
});
|
||||
button_deny.addEventListener("click", (message) => {
|
||||
let parent = message.target.parentElement;
|
||||
document.body.removeChild(parent);
|
||||
});
|
||||
|
||||
|
||||
banner.appendChild( text );
|
||||
banner.appendChild( button_accept );
|
||||
banner.appendChild( button_deny );
|
||||
|
||||
document.body.appendChild(banner);
|
||||
}
|
||||
|
||||
// Returns true if cookies are accepted
|
||||
function cookieAccepted() {
|
||||
let maybe_cookie_status = localStorage.getItem("cookie");
|
||||
let cookie_status = 0; // 0 = not answered, 1 = accepted, 2 = denied
|
||||
|
||||
if( maybe_cookie_status == null ) cookie_status = 0;
|
||||
else if(maybe_cookie_status == "accepted") cookie_status = 1;
|
||||
else cookie_status = 2;
|
||||
|
||||
if (cookie_status == 1) return true;
|
||||
if (cookie_status == 0) {
|
||||
let maybe_banner = document.getElementsByClassName("cookie-banner")[0];
|
||||
if(maybe_banner == undefined){
|
||||
__cookie_internal_addBanner__();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
cookieAccepted();
|
75
out/js/pc.js
Normal file
75
out/js/pc.js
Normal file
@ -0,0 +1,75 @@
|
||||
// Init Elm
|
||||
var localStuff = localStorage.getItem("pc_data");
|
||||
if (typeof localStuff !== "string") localStuff = "";
|
||||
|
||||
var app = Elm.Main.init({
|
||||
node: document.getElementById("elm"),
|
||||
flags: localStuff
|
||||
});
|
||||
|
||||
// ###################################################################
|
||||
// ###################################################################
|
||||
|
||||
// Dom Objects
|
||||
let pc = document.getElementsByClassName("pc")[0];
|
||||
let pc_ram = pc.getElementsByClassName("ram")[0];
|
||||
let pc_cu = pc.getElementsByClassName("cu")[0];
|
||||
let pc_alu = pc.getElementsByClassName("alu")[0];
|
||||
|
||||
let pc_ram_scroller = pc_ram.getElementsByClassName("scroller")[0];
|
||||
let pc_cu_scroller = pc_cu.getElementsByClassName("scroller")[0];
|
||||
|
||||
let control_autoscroll = document.getElementById("enableScrolling");
|
||||
|
||||
// Methods
|
||||
function scrollToCurrent(){
|
||||
if( control_autoscroll.checked == false ) return;
|
||||
|
||||
let current_ram = pc_ram.getElementsByClassName("current")[0];
|
||||
let current_uCode = pc_cu.getElementsByClassName("current")[0];
|
||||
|
||||
if( pc.scrollIntoViewIfNeeded == undefined ){
|
||||
if( typeof current_ram != "undefined"){
|
||||
current_ram.scrollIntoView({behavior: "smooth", block: "nearest"});
|
||||
}
|
||||
if( typeof current_uCode != "undefined"){
|
||||
current_uCode.scrollIntoView({behavior: "smooth", block: "nearest"});
|
||||
}
|
||||
}else{
|
||||
if( typeof current_ram != "undefined"){
|
||||
current_ram.scrollIntoViewIfNeeded({behavior: "smooth", block: "nearest"});
|
||||
}
|
||||
if( typeof current_uCode != "undefined"){
|
||||
current_uCode.scrollIntoViewIfNeeded({behavior: "smooth", block: "nearest"});
|
||||
}
|
||||
}
|
||||
|
||||
// pc.scrollIntoView();
|
||||
}
|
||||
|
||||
// ###################################################################
|
||||
// ###################################################################
|
||||
|
||||
|
||||
// EVENT LISTENERS
|
||||
|
||||
// Recieve Elm updates via ports
|
||||
app.ports.sendUUpdate.subscribe( (message) => {
|
||||
// console.log("Update: ", message);
|
||||
scrollToCurrent();
|
||||
|
||||
// Make sure that even when the calculation takes longer it will scroll correctly
|
||||
setTimeout( scrollToCurrent, 100 );
|
||||
} );
|
||||
|
||||
// Recieve LocalSession Updates via Ports
|
||||
app.ports.localStorageSend.subscribe( (message) => {
|
||||
// console.log("localSessionSend: ", message);
|
||||
if( cookieAccepted() )
|
||||
localStorage.setItem("pc_data", message);
|
||||
} );
|
||||
|
||||
|
||||
// ###################################################################
|
||||
// ###################################################################
|
||||
// Done.
|
26
out/js/script.js
Normal file
26
out/js/script.js
Normal file
@ -0,0 +1,26 @@
|
||||
let text_de = document.getElementById("langDE");
|
||||
let text_en = document.getElementById("langEN");
|
||||
|
||||
let btn_changeToDe = document.getElementById("langPickerDE");
|
||||
let btn_changeToEn = document.getElementById("langPickerEN");
|
||||
|
||||
let lang = (typeof document.documentElement.lang == "string") ? document.documentElement.lang: "en"
|
||||
|
||||
|
||||
function changeLang(lang){
|
||||
if(lang == "de"){
|
||||
text_de.classList.remove("hidden");
|
||||
text_en.classList.add("hidden");
|
||||
}else{
|
||||
text_en.classList.remove("hidden");
|
||||
text_de.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
btn_changeToEn.addEventListener("click", () => { changeLang("en") } );
|
||||
btn_changeToDe.addEventListener("click", () => { changeLang("de") } );
|
||||
|
||||
|
||||
|
||||
// Do stuff on loading
|
||||
changeLang( lang );
|
@ -1,76 +0,0 @@
|
||||
// Init Elm
|
||||
var app = Elm.Main.init({
|
||||
node: document.getElementById("elm"),
|
||||
// flags: Date.now()
|
||||
});
|
||||
|
||||
// Dom Objects
|
||||
let pc = document.getElementsByClassName("pc")[0];
|
||||
let pc_ram = pc.getElementsByClassName("ram")[0];
|
||||
let pc_cu = pc.getElementsByClassName("cu")[0];
|
||||
let pc_alu = pc.getElementsByClassName("alu")[0];
|
||||
|
||||
let pc_ram_scroller = pc_ram.getElementsByClassName("scroller")[0];
|
||||
let pc_cu_scroller = pc_cu.getElementsByClassName("scroller")[0];
|
||||
|
||||
let control_autoscroll = document.getElementById("enableScrolling");
|
||||
|
||||
// Methods
|
||||
function scrollToCurrent(){
|
||||
if( control_autoscroll.checked == false ) return;
|
||||
|
||||
let current_ram = pc_ram.getElementsByClassName("current")[0];
|
||||
if( typeof current_ram != "undefined"){
|
||||
current_ram.scrollIntoView({behavior: "smooth", block: "center"});
|
||||
}
|
||||
|
||||
let current_uCode = pc_cu.getElementsByClassName("current")[0];
|
||||
if( typeof current_uCode != "undefined"){
|
||||
current_uCode.scrollIntoView({behavior: "smooth", block: "center"});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function shrinkTableHead(scroll){
|
||||
let scroller = scroll.target;
|
||||
let pos = scroller.scrollTop;
|
||||
let thead = scroller.getElementsByClassName("head")[0];
|
||||
|
||||
if( pos > 70 ){
|
||||
thead.classList.add("shrunk");
|
||||
}else if (pos < 40){
|
||||
thead.classList.remove("shrunk");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function loadStorage() {
|
||||
let content = localStorage.getItem("pc_data");
|
||||
if( typeof content == "string" ){
|
||||
app.ports.localStorageRecieve.send( content );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Load last state of pc
|
||||
loadStorage();
|
||||
|
||||
// EVENT LISTENERS
|
||||
pc_ram_scroller.addEventListener("scroll", shrinkTableHead);
|
||||
pc_cu_scroller.addEventListener("scroll", shrinkTableHead);
|
||||
|
||||
// Recieve Elm updates via ports
|
||||
app.ports.sendUUpdate.subscribe( (message) => {
|
||||
// console.log("Update: ", message);
|
||||
scrollToCurrent();
|
||||
|
||||
// Make sure that even when the calculation takes longer it will scroll correctly
|
||||
setTimeout( scrollToCurrent, 100 );
|
||||
} );
|
||||
|
||||
// Recieve LocalSession Updates via Ports
|
||||
app.ports.localStorageSend.subscribe( (message) => {
|
||||
console.log("localSessionSend: ", message);
|
||||
localStorage.setItem("pc_data", message);
|
||||
} );
|
1325
src/Main.elm
1325
src/Main.elm
File diff suppressed because it is too large
Load Diff
107
src/PC/Defaults.elm
Normal file
107
src/PC/Defaults.elm
Normal file
@ -0,0 +1,107 @@
|
||||
module PC.Defaults exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
|
||||
|
||||
initalModel : PC_Model
|
||||
initalModel =
|
||||
{ pc = initialPC
|
||||
, uCodes = initialUCodes
|
||||
}
|
||||
|
||||
initialPC : PC
|
||||
initialPC =
|
||||
{ ram = initialRam
|
||||
, dataBus = 0
|
||||
, addressBus = 0
|
||||
, instructionReg = 0
|
||||
, programmCounter = 0
|
||||
, uCounter = 0
|
||||
, accumulator = 0
|
||||
}
|
||||
|
||||
|
||||
initialRam : Array (Int, String)
|
||||
initialRam = Array.fromList
|
||||
[ (100005, "LoadA #005") -- 000 -- LoadA #005
|
||||
, (300000, "IncA") -- 001 -- IncA
|
||||
, (200005, "StoreA #005") -- 002 -- StoreA #005
|
||||
, (400000, "JMP #000") -- 003 -- JMP #000
|
||||
, (0,"") -- 004
|
||||
, (5,"val") -- 005
|
||||
, (0, "") -- 006
|
||||
, (0, "") -- 007
|
||||
, (0, "") -- 008
|
||||
, (0, "") -- 009
|
||||
, (0, "") -- 010
|
||||
]
|
||||
|
||||
|
||||
|
||||
initialUCodes : Array UAction
|
||||
initialUCodes = Array.fromList
|
||||
[ UA_ProgrammCounter2AddressBus -- 000
|
||||
, UA_Ram2DataBus -- 001
|
||||
, UA_DataBus2InstructionReg -- 002
|
||||
, UA_ProgrammCounterIncrement -- 003
|
||||
, UA_InstructionReg2UCounter -- 004
|
||||
, UA_Nothing -- 005
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 009
|
||||
|
||||
-- 010 LOADA
|
||||
, UA_InstructionReg2AddressBus -- 010
|
||||
, UA_Ram2DataBus -- 011
|
||||
, UA_DataBus2Accumulator -- 012
|
||||
, UA_ResetUCounter -- 013
|
||||
, UA_Nothing -- 014
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 019
|
||||
|
||||
-- 020 STOA
|
||||
, UA_Accumulator2DataBus -- 020
|
||||
, UA_InstructionReg2AddressBus -- 021
|
||||
, UA_DataBus2Ram -- 022
|
||||
, UA_ResetUCounter -- 023
|
||||
, UA_Nothing --024
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 029
|
||||
|
||||
-- 030 INCA
|
||||
, UA_AccumulatorIncrement -- 030
|
||||
, UA_ResetUCounter -- 031
|
||||
, UA_Nothing -- 032
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 039
|
||||
|
||||
-- 040 JMP
|
||||
, UA_InstructionReg2ProgrammCounter -- 040
|
||||
, UA_ResetUCounter -- 041
|
||||
, UA_Nothing -- 042
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 049
|
||||
]
|
||||
|
||||
|
||||
|
92
src/PC/Helpers.elm
Normal file
92
src/PC/Helpers.elm
Normal file
@ -0,0 +1,92 @@
|
||||
module PC.Helpers exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
import Http exposing (..)
|
||||
|
||||
-- Convert a number from 42 to 0042
|
||||
-- number : (Prefered positive) whole number
|
||||
-- length : positive whole number
|
||||
-- Please note that only 0 are added. The number will not be shortend!
|
||||
addLeadingZero : Int -> Int -> String
|
||||
addLeadingZero number length =
|
||||
let
|
||||
num_str = String.fromInt number
|
||||
in
|
||||
(String.fromList <| List.repeat (length - String.length num_str) '0'
|
||||
)
|
||||
++ num_str
|
||||
|
||||
|
||||
-- Get the value at a given position in a List.
|
||||
-- For performance reasons it might be better
|
||||
-- to use an Array instead.
|
||||
valueAt : Int -> List a -> Maybe a
|
||||
valueAt pos list = List.head <| List.drop pos list
|
||||
|
||||
|
||||
-- Change the value at a given position in a List.
|
||||
-- If your pos is greater than the length of
|
||||
-- the list, then the rest is filled with the
|
||||
-- default element.
|
||||
overwriteAt : a -> Int -> a ->List a -> List a
|
||||
overwriteAt default pos newVal list =
|
||||
let
|
||||
len = List.length list
|
||||
in
|
||||
if pos > len then
|
||||
list ++
|
||||
(List.repeat (pos-len) default) ++
|
||||
[newVal]
|
||||
else
|
||||
let
|
||||
before = List.take pos list
|
||||
after = List.drop (pos+1) list
|
||||
in
|
||||
before ++ [newVal] ++ after
|
||||
|
||||
overwriteAt_Arr : a -> Int -> a -> Array a -> Array a
|
||||
overwriteAt_Arr default pos newVal list =
|
||||
let
|
||||
len = Array.length list
|
||||
in
|
||||
if pos > len then
|
||||
Array.append list
|
||||
<| Array.append (Array.repeat (pos-len) default)
|
||||
<| Array.fromList [newVal]
|
||||
else
|
||||
Array.set pos newVal list
|
||||
|
||||
|
||||
-- Prints Http Errors into something readable
|
||||
printHttpError : Http.Error -> String
|
||||
printHttpError err =
|
||||
case err of
|
||||
Http.BadUrl str -> "Bad Url: " ++ str
|
||||
Http.Timeout -> "Timeout"
|
||||
Http.NetworkError -> "Network Error"
|
||||
Http.BadStatus num -> "Bad Status: " ++ String.fromInt num
|
||||
Http.BadBody str -> "Bad Body: " ++ str
|
||||
|
||||
|
||||
seperateInstructionsEntry : Int -> (Int, Int)
|
||||
seperateInstructionsEntry i =
|
||||
let
|
||||
instruction = i // 100000
|
||||
address = i - instruction*100000
|
||||
in
|
||||
(instruction, address)
|
||||
|
||||
|
||||
valueAtRam : Int -> Array (Int, String) -> (Int, String)
|
||||
valueAtRam pos arr =
|
||||
case Array.get pos arr of
|
||||
Just a -> a
|
||||
Nothing -> (0, "")
|
||||
|
||||
|
||||
changeAtRam : Int -> Int -> Array (Int, String) -> Array (Int,String)
|
||||
changeAtRam pos newVal list =
|
||||
let
|
||||
(_,comment) = valueAtRam pos list
|
||||
in
|
||||
overwriteAt_Arr (0, "") pos (newVal, comment) list
|
112
src/PC/JSON.elm
Normal file
112
src/PC/JSON.elm
Normal file
@ -0,0 +1,112 @@
|
||||
module PC.Json exposing ( pcModelDecoder
|
||||
, pcModelEncoder
|
||||
, tuple2Decoder
|
||||
, tuple2Encoder
|
||||
)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import Maybe
|
||||
import Array exposing (Array)
|
||||
|
||||
import Json.Encode as JE exposing (Value)
|
||||
import Json.Decode as JD exposing (Decoder)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
|
||||
|
||||
-- ##########################################################
|
||||
-- Decoders
|
||||
-- ##########################################################
|
||||
|
||||
pcModelDecoder : Decoder PC_Model
|
||||
pcModelDecoder =
|
||||
JD.map2
|
||||
PC_Model
|
||||
(JD.field "pc" pcDecoder)
|
||||
(JD.field "uCodes" uCodeDecoder)
|
||||
|
||||
|
||||
pcDecoder : Decoder PC
|
||||
pcDecoder =
|
||||
JD.map7
|
||||
PC
|
||||
(JD.field "ram" <| JD.array <| tuple2Decoder JD.int JD.string)
|
||||
(JD.field "dataBus" JD.int)
|
||||
(JD.field "addressBus" JD.int)
|
||||
(JD.field "instructionReg" JD.int)
|
||||
(JD.field "programmCounter" JD.int)
|
||||
(JD.field "uCounter" JD.int)
|
||||
(JD.field "accumulator" JD.int)
|
||||
|
||||
uCodeDecoder : Decoder (Array UAction)
|
||||
uCodeDecoder =
|
||||
JD.array <| JD.map uActionDecoder JD.string
|
||||
|
||||
uActionDecoder : String -> UAction
|
||||
uActionDecoder str =
|
||||
Maybe.withDefault UA_Nothing <| string2uAction str
|
||||
|
||||
|
||||
|
||||
tuple2Decoder : Decoder a -> Decoder b -> Decoder (a,b)
|
||||
tuple2Decoder enc1 enc2 =
|
||||
JD.map2 Tuple.pair
|
||||
(JD.index 0 enc1)
|
||||
(JD.index 1 enc2)
|
||||
|
||||
-- ##########################################################
|
||||
-- ##########################################################
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- ##########################################################
|
||||
-- Encoders
|
||||
-- ##########################################################
|
||||
|
||||
pcModelEncoder : PC_Model -> Value
|
||||
pcModelEncoder model =
|
||||
JE.object
|
||||
[ ( "pc" , pcEncoder model.pc )
|
||||
, ( "uCodes" , uCodesEncoder model.uCodes )
|
||||
]
|
||||
|
||||
pcEncoder : PC -> Value
|
||||
pcEncoder pc =
|
||||
JE.object
|
||||
[ ( "addressBus" , JE.int pc.addressBus )
|
||||
, ( "dataBus" , JE.int pc.dataBus )
|
||||
, ( "instructionReg" , JE.int pc.instructionReg )
|
||||
, ( "programmCounter" , JE.int pc.programmCounter )
|
||||
, ( "uCounter" , JE.int pc.uCounter )
|
||||
, ( "accumulator" , JE.int pc.accumulator )
|
||||
, ( "ram" , ramEncoder pc.ram )
|
||||
]
|
||||
|
||||
ramEncoder : Array (Int, String) -> Value
|
||||
ramEncoder arr =
|
||||
JE.array
|
||||
(tuple2Encoder JE.int JE.string)
|
||||
arr
|
||||
|
||||
uCodesEncoder : Array UAction -> Value
|
||||
uCodesEncoder uActions =
|
||||
JE.array encodeSingleuCode uActions
|
||||
|
||||
encodeSingleuCode : UAction -> Value
|
||||
encodeSingleuCode action =
|
||||
let
|
||||
uCode = uAction2UCode action
|
||||
in
|
||||
JE.string uCode.id
|
||||
|
||||
|
||||
tuple2Encoder : (a -> Value) -> (b -> Value) -> (a,b) -> Value
|
||||
tuple2Encoder encA encB (valA, valB) =
|
||||
JE.list identity [ encA valA, encB valB ]
|
||||
|
||||
-- ##########################################################
|
||||
-- ##########################################################
|
||||
-- Done.
|
28
src/PC/PC.elm
Normal file
28
src/PC/PC.elm
Normal file
@ -0,0 +1,28 @@
|
||||
module PC.PC exposing (..)
|
||||
|
||||
import Html exposing (Html)
|
||||
--import Json.Encode as JE
|
||||
import Json.Decode as JD
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.Defaults exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
import PC.Update exposing (..)
|
||||
import PC.View exposing (..)
|
||||
|
||||
|
||||
|
||||
update : PC_Msg -> PC_Model -> (PC_Model, PC_AfterUpdateAction)
|
||||
update = pc_update
|
||||
|
||||
|
||||
view : PC_Model -> Html PC_Msg
|
||||
view = pc_view
|
||||
|
||||
init : PC_Model
|
||||
init = initalModel
|
||||
|
||||
|
||||
|
||||
|
||||
|
78
src/PC/Types.elm
Normal file
78
src/PC/Types.elm
Normal file
@ -0,0 +1,78 @@
|
||||
module PC.Types exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
|
||||
pcModelVersion = "3"
|
||||
|
||||
type alias PC_Model =
|
||||
{ pc : PC
|
||||
, uCodes : Array UAction
|
||||
}
|
||||
|
||||
type alias PC =
|
||||
{ ram : Array (Int, String)
|
||||
, dataBus : Int
|
||||
, addressBus : Int
|
||||
, instructionReg : Int
|
||||
, programmCounter : Int
|
||||
, uCounter : Int
|
||||
, accumulator : Int
|
||||
}
|
||||
|
||||
type alias UCode =
|
||||
{ variant : UAction
|
||||
, id : String
|
||||
, action : PC -> PC
|
||||
, label : String
|
||||
}
|
||||
|
||||
type UAction
|
||||
= UA_Accumulator2DataBus
|
||||
| UA_AccumulatorDecrement
|
||||
| UA_AccumulatorIncrement
|
||||
| UA_DataBus2Accumulator
|
||||
| UA_DataBus2InstructionReg
|
||||
| UA_DataBus2Ram
|
||||
| UA_InstructionReg2AddressBus
|
||||
| UA_InstructionReg2ProgrammCounter
|
||||
| UA_InstructionReg2UCounter
|
||||
| UA_ProgrammCounterIncrement
|
||||
| UA_InstructionReg2ProgrammCounterIfAccEq0
|
||||
| UA_Ram2DataBus
|
||||
| UA_ResetUCounter
|
||||
| UA_ProgrammCounter2AddressBus
|
||||
| UA_Nothing
|
||||
|
||||
|
||||
-- To make it easier to understand everything has name convention
|
||||
-- PM_ -> PC_Msg in general
|
||||
-- PM_B_ -> for a Button
|
||||
-- PM_C_ -> for a Checkbox
|
||||
-- PM_F_ -> for a TextField
|
||||
type PC_Msg
|
||||
= PM_B_UCycleStep
|
||||
| PM_B_InstructionStep
|
||||
| PM_B_Reset
|
||||
| PM_B_RamAddBelow
|
||||
| PM_B_CuAddBelow
|
||||
| PM_F_RamEditInstr Int String
|
||||
| PM_F_RamEditAddress Int String
|
||||
| PM_F_RamEditComment Int String
|
||||
| PM_F_CuEditAction Int String
|
||||
| PM_F_CuInstrRegEditAddr String
|
||||
| PM_F_CuInstrRegEditInstr String
|
||||
| PM_F_CuProgCounterEdit String
|
||||
| PM_F_CuUCounterEdit String
|
||||
| PM_F_EditAddressBus String
|
||||
| PM_F_EditDataBus String
|
||||
| PM_F_AluEdit String
|
||||
| PM_ManualStep UAction
|
||||
|
||||
|
||||
-- Tells main what is supposed
|
||||
-- to happen after a update
|
||||
type PC_AfterUpdateAction
|
||||
= PUA_Nothing -- Do nothing
|
||||
| PUA_Storage -- Update localStorage
|
||||
| PUA_Scroller -- Scroll to value
|
||||
| PUA_Storage_And_Scroller -- Update localStorage and scroll to values
|
163
src/PC/UActions.elm
Normal file
163
src/PC/UActions.elm
Normal file
@ -0,0 +1,163 @@
|
||||
module PC.UActions exposing ( uCodes
|
||||
, uAction2Label
|
||||
, string2uAction
|
||||
, uAction2UCode )
|
||||
|
||||
import Array exposing (Array)
|
||||
import Tuple
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
|
||||
uCodes : List UCode
|
||||
uCodes =
|
||||
[ UCode UA_Accumulator2DataBus "acc2db" actAccumulator2DataBus "Acc -> DataBus"
|
||||
, UCode UA_AccumulatorDecrement "accDec" actAccumulatorDecrement "Acc --"
|
||||
, UCode UA_AccumulatorIncrement "accInc" actAccumulatorIncrement "Acc ++"
|
||||
, UCode UA_DataBus2Accumulator "db2acc" actDataBus2Accumulator "DataBus -> Acc"
|
||||
, UCode UA_DataBus2InstructionReg "db2ir" actDataBus2InstructionReg "DataBus -> InstReg"
|
||||
, UCode UA_DataBus2Ram "db2ram" actDataBus2Ram "DataBus -> Ram"
|
||||
, UCode UA_InstructionReg2AddressBus "ir2ab" actInstructionReg2AddressBus "InstReg -> AddrBus"
|
||||
, UCode UA_InstructionReg2ProgrammCounter "ir2pc" actInstructionReg2ProgrammCounter "InstReg -> ProgCount"
|
||||
, UCode UA_InstructionReg2UCounter "ir2uc" actInstructionReg2UCounter "InstReg -> µCounter"
|
||||
, UCode UA_ProgrammCounterIncrement "pcInc" actProgrammCounterIncrement "ProgCounter ++"
|
||||
, UCode UA_Ram2DataBus "ram2db" actRam2DataBus "Ram -> DataBus"
|
||||
, UCode UA_ResetUCounter "ucReset" actResetUCounter "µCounter = 0"
|
||||
, UCode UA_ProgrammCounter2AddressBus "pc2ab" actProgrammCounter2AddressBus "ProgCounter -> AddrBus"
|
||||
, UCode UA_Nothing "n" (\s -> s) "Empty"
|
||||
, UCode UA_InstructionReg2ProgrammCounterIfAccEq0
|
||||
"ir2pciacceq0" actInstructionReg2ProgrammCounterIfAccEq0 "Acc == 0 => InstReg -> ProgCounter"
|
||||
]
|
||||
|
||||
|
||||
-- #######################################################################################
|
||||
-- ACTIONS
|
||||
-- #######################################################################################
|
||||
|
||||
actRam2DataBus : PC -> PC
|
||||
actRam2DataBus pc =
|
||||
let
|
||||
ab =
|
||||
pc.addressBus
|
||||
|
||||
db =
|
||||
Tuple.first <| valueAtRam ab pc.ram
|
||||
in
|
||||
{ pc | dataBus = db }
|
||||
|
||||
|
||||
actDataBus2InstructionReg : PC -> PC
|
||||
actDataBus2InstructionReg pc =
|
||||
{ pc | instructionReg = pc.dataBus }
|
||||
|
||||
|
||||
actResetUCounter : PC -> PC
|
||||
actResetUCounter pc =
|
||||
{ pc | uCounter = 0 }
|
||||
|
||||
|
||||
actInstructionReg2UCounter : PC -> PC
|
||||
actInstructionReg2UCounter pc =
|
||||
-- Multiply by ten, because every instruction is 10 uCodes long
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | uCounter = instruction * 10}
|
||||
|
||||
|
||||
actInstructionReg2AddressBus : PC -> PC
|
||||
actInstructionReg2AddressBus pc =
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | addressBus = address }
|
||||
|
||||
|
||||
actInstructionReg2ProgrammCounter : PC -> PC
|
||||
actInstructionReg2ProgrammCounter pc =
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
|
||||
{ pc | programmCounter = address }
|
||||
|
||||
|
||||
actProgrammCounterIncrement : PC -> PC
|
||||
actProgrammCounterIncrement pc =
|
||||
{ pc | programmCounter = pc.programmCounter + 1 }
|
||||
|
||||
|
||||
actProgrammCounter2AddressBus : PC -> PC
|
||||
actProgrammCounter2AddressBus pc =
|
||||
{ pc | addressBus = pc.programmCounter }
|
||||
|
||||
actInstructionReg2ProgrammCounterIfAccEq0 : PC -> PC
|
||||
actInstructionReg2ProgrammCounterIfAccEq0 pc =
|
||||
if pc.accumulator == 0 then
|
||||
let
|
||||
(_,addr) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | programmCounter = addr }
|
||||
else
|
||||
pc
|
||||
|
||||
actDataBus2Accumulator : PC -> PC
|
||||
actDataBus2Accumulator pc =
|
||||
{ pc | accumulator = pc.dataBus }
|
||||
|
||||
|
||||
actAccumulator2DataBus : PC -> PC
|
||||
actAccumulator2DataBus pc =
|
||||
{ pc | dataBus = pc.accumulator }
|
||||
|
||||
|
||||
actAccumulatorIncrement : PC -> PC
|
||||
actAccumulatorIncrement pc =
|
||||
{ pc | accumulator = pc.accumulator + 1 }
|
||||
|
||||
|
||||
actAccumulatorDecrement : PC -> PC
|
||||
actAccumulatorDecrement pc =
|
||||
{ pc | accumulator = pc.accumulator - 1 }
|
||||
|
||||
|
||||
actDataBus2Ram : PC -> PC
|
||||
actDataBus2Ram pc =
|
||||
let
|
||||
newRam =
|
||||
changeAtRam pc.addressBus pc.dataBus pc.ram
|
||||
in
|
||||
{ pc | ram = newRam }
|
||||
|
||||
|
||||
-- #################################################################
|
||||
-- Helpers
|
||||
-- #################################################################
|
||||
|
||||
uAction2Label : UAction -> String
|
||||
uAction2Label variant =
|
||||
let
|
||||
filtered_list = List.filter (\u -> u.variant == variant ) uCodes
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just uCode -> uCode.label
|
||||
Nothing -> "IDK"
|
||||
|
||||
uAction2UCode : UAction -> UCode
|
||||
uAction2UCode variant =
|
||||
let
|
||||
filtered_list = List.filter (\u -> u.variant == variant ) uCodes
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just uCode -> uCode
|
||||
Nothing -> UCode UA_Nothing "n" (\s -> s) "Empty"
|
||||
|
||||
string2uAction : String -> Maybe UAction
|
||||
string2uAction str =
|
||||
let
|
||||
filtered_list = List.filter (\u -> u.id == str) uCodes
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just uCode -> Just uCode.variant
|
||||
_ -> Nothing
|
||||
|
246
src/PC/Update.elm
Normal file
246
src/PC/Update.elm
Normal file
@ -0,0 +1,246 @@
|
||||
module PC.Update exposing (pc_update)
|
||||
|
||||
import Array exposing (Array)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
import PC.Defaults exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
|
||||
|
||||
pc_update : PC_Msg -> PC_Model -> (PC_Model, PC_AfterUpdateAction)
|
||||
pc_update msg model =
|
||||
case msg of
|
||||
PM_B_UCycleStep ->
|
||||
( uStepPC model
|
||||
, if model.pc.uCounter == 0 then PUA_Storage_And_Scroller
|
||||
else PUA_Scroller
|
||||
)
|
||||
|
||||
PM_B_InstructionStep ->
|
||||
( executeInstruction model
|
||||
, PUA_Storage_And_Scroller )
|
||||
|
||||
|
||||
PM_B_Reset ->
|
||||
( { model | pc = { initialPC | ram = model.pc.ram } }
|
||||
, PUA_Storage_And_Scroller )
|
||||
|
||||
PM_B_RamAddBelow ->
|
||||
let
|
||||
old_pc = model.pc
|
||||
new_pc = {old_pc | ram = Array.append old_pc.ram <| Array.fromList [(0, "")]}
|
||||
in
|
||||
({model | pc = new_pc}
|
||||
, PUA_Storage)
|
||||
|
||||
PM_B_CuAddBelow ->
|
||||
({model | uCodes = Array.append model.uCodes <| Array.repeat 10 UA_Nothing}
|
||||
, PUA_Storage)
|
||||
|
||||
PM_F_RamEditAddress addr may_int ->
|
||||
case String.toInt may_int of
|
||||
Just int ->
|
||||
let
|
||||
(inst,_) = seperateInstructionsEntry ( Tuple.first <| valueAtRam addr model.pc.ram )
|
||||
new_val = inst * 100000 + int
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = (changeAtRam addr new_val old_pc.ram) }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> (model, PUA_Nothing)
|
||||
|
||||
PM_F_RamEditInstr addr may_int ->
|
||||
case String.toInt may_int of
|
||||
Just int ->
|
||||
let
|
||||
(_,address) = seperateInstructionsEntry ( Tuple.first <| valueAtRam addr model.pc.ram )
|
||||
new_val = int * 100000 + address
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = (changeAtRam addr new_val old_pc.ram) }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
|
||||
PM_F_RamEditComment addr str ->
|
||||
let
|
||||
(val, _) = valueAtRam addr model.pc.ram
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = overwriteAt_Arr (0,"") addr (val, str) old_pc.ram }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
|
||||
PM_F_CuEditAction addr may_action ->
|
||||
case string2uAction may_action of
|
||||
Just action ->
|
||||
let
|
||||
newCode = Array.set addr action model.uCodes
|
||||
in
|
||||
({ model | uCodes = newCode }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
|
||||
PM_F_CuInstrRegEditAddr text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
(instr,_) = seperateInstructionsEntry old_pc.instructionReg
|
||||
new_pc = { old_pc | instructionReg = instr * 100000 + int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_CuInstrRegEditInstr text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
(_,addr) = seperateInstructionsEntry old_pc.instructionReg
|
||||
new_pc = { old_pc | instructionReg = int * 100000 + addr }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_CuProgCounterEdit text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | programmCounter = int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_CuUCounterEdit text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | uCounter = int }
|
||||
in
|
||||
( { model | pc = new_pc }, PUA_Storage_And_Scroller )
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_EditAddressBus text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | addressBus = int }
|
||||
in
|
||||
( { model | pc = new_pc }, PUA_Storage_And_Scroller )
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_EditDataBus text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | dataBus = int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_AluEdit text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | accumulator = int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
|
||||
PM_ManualStep action ->
|
||||
let
|
||||
instruction = getAction action
|
||||
new_model = { model | pc = instruction model.pc }
|
||||
in
|
||||
( new_model, PUA_Storage_And_Scroller )
|
||||
|
||||
-- ###############################################################################
|
||||
-- ###############################################################################
|
||||
|
||||
|
||||
|
||||
-- ###############################################################################
|
||||
-- Update Helpers
|
||||
-- ###############################################################################
|
||||
|
||||
-- Practically a part of uStepPC but sepeated for manual mode
|
||||
getAction : UAction -> (PC -> PC)
|
||||
getAction uAction =
|
||||
let
|
||||
possible_instructions =
|
||||
List.filter (\u -> u.variant == uAction) uCodes
|
||||
in
|
||||
case List.head possible_instructions of
|
||||
Just uCode ->
|
||||
uCode.action
|
||||
_ ->
|
||||
(\s -> s)
|
||||
|
||||
|
||||
uStepPC : PC_Model -> PC_Model
|
||||
uStepPC model =
|
||||
let
|
||||
uCounter =
|
||||
model.pc.uCounter
|
||||
|
||||
may_code : Maybe UAction
|
||||
may_code = Array.get uCounter model.uCodes
|
||||
--valueAt uCounter model.uCodes
|
||||
in
|
||||
case may_code of
|
||||
Just code ->
|
||||
let
|
||||
-- code :: UAction
|
||||
old_pc = model.pc
|
||||
temp_pc = { old_pc | uCounter = uCounter + 1 }
|
||||
|
||||
uCode = uAction2UCode code
|
||||
f = uCode.action
|
||||
new_pc = f temp_pc
|
||||
in
|
||||
{ model | pc = new_pc }
|
||||
|
||||
|
||||
--let
|
||||
-- possible_instructions =
|
||||
-- List.filter (\s -> Tuple.first s == action) uCodeMaps
|
||||
--in
|
||||
--case List.head possible_instructions of
|
||||
-- Just ( name, instruction ) ->
|
||||
-- let
|
||||
-- old_pc =
|
||||
-- model.pc
|
||||
|
||||
-- new_pc =
|
||||
-- { old_pc | uCounter = old_pc.uCounter + 1 }
|
||||
-- in
|
||||
-- { model | pc = instruction new_pc }
|
||||
|
||||
-- _ ->
|
||||
-- let
|
||||
-- old_pc =
|
||||
-- model.pc
|
||||
|
||||
-- new_pc =
|
||||
-- { old_pc | uCounter = 0 }
|
||||
-- in
|
||||
-- { model | pc = new_pc }
|
||||
|
||||
_ ->
|
||||
model
|
||||
|
||||
|
||||
executeInstruction : PC_Model -> PC_Model
|
||||
executeInstruction model =
|
||||
let
|
||||
new_model = uStepPC model
|
||||
in
|
||||
if new_model.pc.uCounter == 0 then
|
||||
uStepPC new_model
|
||||
else
|
||||
executeInstruction new_model
|
||||
|
||||
|
||||
-- ###############################################################################
|
||||
-- ###############################################################################
|
||||
-- Done.
|
383
src/PC/View.elm
Normal file
383
src/PC/View.elm
Normal file
@ -0,0 +1,383 @@
|
||||
module PC.View exposing (pc_view)
|
||||
|
||||
import Html exposing (Html, button, div, h1, p, text)
|
||||
import Html.Attributes as HAttr exposing (class, classList, value)
|
||||
import Html.Events as HEvent exposing (onClick, onInput)
|
||||
import Html.Lazy exposing (lazy)
|
||||
import Array exposing (Array)
|
||||
import Json.Decode as JD
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
|
||||
pc_view : PC_Model -> Html PC_Msg
|
||||
pc_view model = div []
|
||||
[ div
|
||||
[ class "grid-fullwidth", class "grid-addressbus" ]
|
||||
[ lazy viewAddressBus model ]
|
||||
, lazy viewRam model
|
||||
, lazy viewCu model
|
||||
, lazy viewAlu model
|
||||
, div
|
||||
[ class "grid-fullwidth", class "grid-databus" ]
|
||||
[ lazy viewDataBus model ]
|
||||
]
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- RAM
|
||||
-- #####################################################################
|
||||
|
||||
viewRam : PC_Model -> Html PC_Msg
|
||||
viewRam model =
|
||||
div [ class "section", class "ram" ]
|
||||
[ h1 [ class "header" ] [ text "RAM" ]
|
||||
, div [ class "arrow", class "down", class "top"] [ div [] [] , div [] [] ]
|
||||
, div [ class "scroller" ]
|
||||
[ Html.table [ class "" ]
|
||||
[ Html.thead [ class "head" ]
|
||||
[ Html.tr []
|
||||
[ Html.th [ class "address" ] [ text "Addr" ]
|
||||
, Html.th [] [ text "Value" ]
|
||||
, Html.th [] [ text "Comment" ]
|
||||
]
|
||||
]
|
||||
, lazy viewRamContent model
|
||||
]
|
||||
]
|
||||
, drawArrow Bottom Down UA_Ram2DataBus "Ram -> DataBus"
|
||||
, drawArrow Bottom Up UA_DataBus2Ram "DataBus -> Ram"
|
||||
]
|
||||
|
||||
|
||||
viewRamContent : PC_Model -> Html PC_Msg
|
||||
viewRamContent model =
|
||||
let
|
||||
--indexedRam =
|
||||
-- List.indexedMap Tuple.pair <| Array.toList model.pc.ram
|
||||
|
||||
ram2table : Int -> (Int, String) -> Html PC_Msg
|
||||
ram2table id entry =
|
||||
let
|
||||
(val,comment) = entry
|
||||
|
||||
(instruction, address) = seperateInstructionsEntry val
|
||||
in
|
||||
Html.tr
|
||||
[ classList [ ( "current", id == model.pc.addressBus ) ] ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 3) ]
|
||||
, Html.td [ class "num " ]
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.value <| addLeadingZero instruction 3
|
||||
, onInput <| PM_F_RamEditInstr id
|
||||
, class "ram-entry"
|
||||
, class "instruction"
|
||||
]
|
||||
[]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.value <| addLeadingZero address 5
|
||||
, onInput <| PM_F_RamEditAddress id
|
||||
, class "ram-entry"
|
||||
, class "address"
|
||||
]
|
||||
[]
|
||||
]
|
||||
, Html.td[ class "comment" ]
|
||||
[ Html.input
|
||||
[ HAttr.type_ "text"
|
||||
, HAttr.value comment
|
||||
, onInput <| PM_F_RamEditComment id ]
|
||||
[]
|
||||
]
|
||||
]
|
||||
in
|
||||
Html.tbody []
|
||||
((Array.toList <| Array.indexedMap ram2table model.pc.ram)
|
||||
++
|
||||
[ Html.tr []
|
||||
[ Html.td [] []
|
||||
, Html.td []
|
||||
[ button
|
||||
[ onClick PM_B_RamAddBelow ]
|
||||
[ text "Add Entry"]
|
||||
]
|
||||
, Html.td [][]
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- Control Unit
|
||||
-- #####################################################################
|
||||
|
||||
viewCu : PC_Model -> Html PC_Msg
|
||||
viewCu model =
|
||||
let
|
||||
( instrRegInst, instrRegAddr ) = seperateInstructionsEntry model.pc.instructionReg
|
||||
in
|
||||
div [ class "section", class "cu" ]
|
||||
[ drawArrow Top Up UA_InstructionReg2AddressBus "InstR -> AddrB"
|
||||
, drawArrow Top Up UA_ProgrammCounter2AddressBus "ProgCounter -> AddrB"
|
||||
--, div [ class "arrow", class "up", class "top"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (PM_ManualStep ActInstructionReg2AddressBus)] [ text "InstR -> AddrB" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
--, div [ class "arrow", class "up", class "top", class "arrow2"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (PM_ManualStep ActProgrammCounter2AddressBus)] [ text "ProgCounter -> AddrB" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
|
||||
|
||||
, h1 [ class "header" ] [ text "Control Unit" ]
|
||||
, p []
|
||||
[ div [class "input-row"]
|
||||
[ Html.label [ HAttr.for "cu-progcounter" ] [ text "Programm Counter:" ]
|
||||
, div [ class "input-group" ]
|
||||
[ button
|
||||
[ onClick <| PM_ManualStep UA_InstructionReg2ProgrammCounter ]
|
||||
[ text "InstRA -> " ]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-progcounter"
|
||||
, value (addLeadingZero model.pc.programmCounter 3)
|
||||
, onInput PM_F_CuProgCounterEdit
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
, div [class "input-row"]
|
||||
[ Html.label [ HAttr.for "cu-instrReg" ] [ text "Instruction Register:" ]
|
||||
, div []
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-instrReg"
|
||||
, class "instruction"
|
||||
, value (addLeadingZero instrRegInst 3)
|
||||
, onInput PM_F_CuInstrRegEditInstr
|
||||
] []
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-instrReg"
|
||||
, class "address"
|
||||
, value (addLeadingZero instrRegAddr 5)
|
||||
, onInput PM_F_CuInstrRegEditAddr
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
, div [class "input-row"]
|
||||
[ Html.label [ HAttr.for "cu-uCounter" ] [ text "µCode Counter:" ]
|
||||
, div [ class "input-group" ]
|
||||
[ button
|
||||
[ onClick <| PM_ManualStep UA_InstructionReg2UCounter ]
|
||||
[ text "IntrRI ->" ]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-uCounter"
|
||||
, value (addLeadingZero model.pc.uCounter 4)
|
||||
, onInput PM_F_CuUCounterEdit
|
||||
] []
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "scroller" ]
|
||||
[ viewCuUCode model
|
||||
]
|
||||
--, div [ class "arrow", class "up"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (MsgManualStep ActDataBus2InstructionReg) ] [ text "DB -> InstR" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
, drawArrow Bottom Up UA_DataBus2InstructionReg "DB -> InstR"
|
||||
]
|
||||
|
||||
|
||||
viewCuUCode : PC_Model -> Html PC_Msg
|
||||
viewCuUCode model =
|
||||
Html.table []
|
||||
[ Html.thead [ class "head" ]
|
||||
[ Html.tr []
|
||||
[ Html.th [ class "address" ] [ text "µCounter" ]
|
||||
, Html.th [] [ text "µCode" ]
|
||||
]
|
||||
]
|
||||
, lazy viewCuUCodeContent model
|
||||
]
|
||||
|
||||
|
||||
viewCuUCodeContent : PC_Model -> Html PC_Msg
|
||||
viewCuUCodeContent model =
|
||||
let
|
||||
list2table : Int -> UAction -> Html PC_Msg
|
||||
list2table id code =
|
||||
Html.tr
|
||||
[ classList [ ( "current", id == model.pc.uCounter ), ("empty", code == UA_Nothing) ] ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 4) ]
|
||||
, Html.td [] [ viewCuInstrSelect id code ]
|
||||
]
|
||||
|
||||
in
|
||||
Html.tbody []
|
||||
((Array.toList <| Array.indexedMap list2table model.uCodes)
|
||||
++
|
||||
[ Html.tr []
|
||||
[ Html.td [] []
|
||||
, Html.td []
|
||||
[ button
|
||||
[ onClick PM_B_CuAddBelow ]
|
||||
[ text "Add Entry"]
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
viewCuInstrSelect : Int -> UAction -> Html PC_Msg
|
||||
viewCuInstrSelect id current =
|
||||
let
|
||||
info2option uCode =
|
||||
Html.option
|
||||
[ HAttr.selected (uCode.variant == current)
|
||||
, HAttr.value uCode.id ]
|
||||
[ text uCode.label ]
|
||||
listOptions = List.map info2option uCodes
|
||||
in
|
||||
Html.select
|
||||
[ HEvent.on "change" ( JD.map (PM_F_CuEditAction id) selectCuValueDecoder) ]
|
||||
listOptions
|
||||
|
||||
viewInstrEntry : Int -> Html PC_Msg
|
||||
viewInstrEntry i =
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry i
|
||||
in
|
||||
text ( (addLeadingZero instruction 3) ++ " " ++ (addLeadingZero address 5) )
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- ALU
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
viewAlu : PC_Model -> Html PC_Msg
|
||||
viewAlu model =
|
||||
div [ class "section", class "alu" ]
|
||||
[ h1 [ class "header" ] [ text "ALU" ]
|
||||
, p []
|
||||
[ Html.label [ HAttr.for "alu-accumulator" ] [ text "Accumulator:" ]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "alu-accumulator"
|
||||
, value (addLeadingZero model.pc.accumulator 8)
|
||||
, onInput PM_F_AluEdit
|
||||
] []
|
||||
]
|
||||
, p []
|
||||
[ button [ onClick <| PM_ManualStep UA_AccumulatorIncrement ] [ text "Acc ++" ]
|
||||
, button [ onClick <| PM_ManualStep UA_AccumulatorDecrement ] [ text "Acc --" ]
|
||||
]
|
||||
, drawArrow Bottom Up UA_DataBus2Accumulator "DB -> ALU"
|
||||
, drawArrow Bottom Down UA_Accumulator2DataBus "ALU -> DB"
|
||||
--, div [ class "arrow", class "up"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (MsgManualStep ActDataBus2Accumulator)] [ text "DB -> ALU" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
--, div [ class "arrow", class "down"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (MsgManualStep ActAccumulator2DataBus)] [ text "ALU -> DB" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
]
|
||||
|
||||
-- #####################################################################
|
||||
-- Busses
|
||||
-- #####################################################################
|
||||
|
||||
viewDataBus : PC_Model -> Html PC_Msg
|
||||
viewDataBus model =
|
||||
div [ class "databus" ]
|
||||
[ Html.span [ class "label" ] [ text "Databus" ]
|
||||
, Html.span []
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, value (addLeadingZero model.pc.dataBus 8)
|
||||
, onInput PM_F_EditDataBus
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
viewAddressBus : PC_Model -> Html PC_Msg
|
||||
viewAddressBus model =
|
||||
div [ class "addressbus" ]
|
||||
[ Html.span [ class "label" ] [ text "Addressbus" ]
|
||||
, Html.span []
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, value (addLeadingZero model.pc.addressBus 3)
|
||||
, onInput PM_F_EditAddressBus
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- Helpers
|
||||
-- #####################################################################
|
||||
|
||||
type Arrow_Pos = Top | Bottom
|
||||
type Arrow_Dir = Up | Down
|
||||
|
||||
drawArrow : Arrow_Pos -> Arrow_Dir -> UAction -> String -> Html PC_Msg
|
||||
drawArrow pos dir act str =
|
||||
div
|
||||
[ HAttr.classList
|
||||
[ ("arrow", True)
|
||||
, ("top", pos == Top)
|
||||
, ("up", dir == Up)
|
||||
, ("down", dir == Down)]
|
||||
]
|
||||
[ div [ class "button" ]
|
||||
[ Html.a
|
||||
[ onClick (PM_ManualStep act) ]
|
||||
[ text str ]
|
||||
]
|
||||
, div [] []
|
||||
]
|
||||
|
||||
|
||||
selectCuValueDecoder : JD.Decoder String
|
||||
selectCuValueDecoder =
|
||||
JD.field "target" ( JD.field "value" JD.string)
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
-- Done.
|
||||
|
||||
|
Reference in New Issue
Block a user