reoganised project

This commit is contained in:
2026-02-23 20:32:45 +00:00
parent 42bc666c11
commit 71b36dc6b5
96 changed files with 662 additions and 46 deletions
+5 -1
View File
@@ -1,7 +1,11 @@
cargo-features = ["codegen-backend"] cargo-features = ["codegen-backend"]
[workspace] [workspace]
members = ["emulator", "common", "assembler", "dsa_editor", "compiler", "dsx_server"] members = [
"core/dsa_common", "core/assembler", "core/compiler",
"emulator", "emulator/dsa_editor",
"dsx/dsx_server", "dsx/dsx_common", "dsx/dsx"
]
resolver = "3" resolver = "3"
[workspace.package] [workspace.package]
@@ -13,6 +13,6 @@ name = "assembler"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
common = { path = "../common" } common = { path = "../dsa_common" }
num_cpus = "1.17.0" num_cpus = "1.17.0"
threadpool = "1.8.1" threadpool = "1.8.1"
@@ -6,5 +6,5 @@ authors.workspace = true
[dependencies] [dependencies]
chrono = "0.4.43" chrono = "0.4.43"
common = { path = "../common" } common = { path = "../dsa_common" }
uuid = { version = "1.20.0", features = ["v4"] } uuid = { version = "1.20.0", features = ["v4"] }
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "dsx"
version.workspace = true
edition.workspace = true
authors.workspace = true
[[bin]]
name = "dsx"
path = "src/main.rs"
[dependencies]
compiler = { path = "../../core/compiler" }
assembler = { path = "../../core/assembler" }
common = { path = "../../core/dsa_common" }
dsx_common = { path = "../dsx_common" }
toml = "1.0.3"
chrono = "0.4.44"
@@ -1,12 +1,9 @@
use std::process::{Command, Stdio}; use std::{env, path::PathBuf};
use std::{
env, fs,
path::{Path, PathBuf},
};
use dsx::common::builder; use dsx_common::builder;
pub mod new; pub mod new;
pub mod templates;
fn main() { fn main() {
// Very small CLI only three subcommands. // Very small CLI only three subcommands.
@@ -1,9 +1,8 @@
use std::{env, fmt, fs, path::PathBuf}; use std::{env, fmt, fs};
use dsx::common::{ use dsx_common::config::DsxConfig;
config::DsxConfig,
templates::{self, Dsa, Dsc, Template}, use crate::templates::{self, Dsa, Dsc, Template};
};
// ---------- new project ---------------------------------------------------- // ---------- new project ----------------------------------------------------
pub fn new_project(args: &[String]) { pub fn new_project(args: &[String]) {
+589
View File
@@ -0,0 +1,589 @@
pub trait Template {
fn lib(project: &str) -> String;
fn bin(project: &str) -> String;
fn create(project: &str, lib: bool) -> String {
if lib {
Self::lib(project)
} else {
Self::bin(project)
}
}
}
pub struct Dsa;
pub struct Dsc;
impl Template for Dsa {
fn lib(project: &str) -> String {
format!(
r#"//
lib.dsa
// usage:
//
// include {project} "<relative path>"
//
// usage for {project}_main:
// push (arg1)
// push (arg0)
// call {project}::{project}_main
// pop (arg0)
// pop (arg1)
// Example data declarations
// dw example_data: 0x0000
// Main function template
{project}_main:
// the correct way to start a function as defined by the calling convention
push bpr
mov spr, bpr
// explanation of how to access args
ldw bpr, rg0, 8 // arg 0
ldw bpr, rg0, 12 // arg 1
// your code goes here
// Example: load example_data into rg1
// ldw example_data, rg1
// the correct way to end a function as defined by the calling convention
mov bpr, spr
pop bpr
return
"#,
)
}
fn bin(project: &str) -> String {
format!(
r#"
// GENERATED BY DSX-BUILD
// Generated at: {timestamp}
// Project name: {project}
// Imports
include print: "./lib/print.dsa"
// Globals & Reserved Memory
dw stack: 0x10000
db message: "Process Exited with code:"
// Entry Point
_init:
ldw stack, bpr
mov bpr, spr
push zero
call main
call print::print_newline
lwi message, rg0
push rg0
call print::print
pop zero
call print::print_hex_word
pop zero
hlt
main:
push bpr
mov spr, bpr
// Your code goes here
// Return zero
stw zero, bpr, 8
mov bpr, spr
pop bpr
return"#,
timestamp = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S")
)
}
}
impl Template for Dsc {
fn lib(project: &str) -> String {
format!(
r#"
// GENERATED BY DSX-BUILD
// Generated at: {timestamp}
// Project name: {project}
// Imports
include print: "./lib/print.dsa";
// Main Function
fn {project}_main() -> u32 {{
return 0;
}}"#,
timestamp = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S")
)
}
fn bin(project: &str) -> String {
format!(
r#"
// GENERATED BY DSX-BUILD
// Generated at: {timestamp}
// Project name: {project}
// Imports
include print: "./lib/print.dsa";
// Main Function
fn main() -> u32 {{
return 0;
}}"#,
timestamp = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S")
)
}
}
pub fn create_print_lib() -> String {
String::from(
r#"
// lib:
// print.dsa
// usage:
//
// include print "<relative path>""
//
// usage for print:
// push (register containing address of string)
// push pcx
// jmp print::print
//
// usage for reset:
// push pcx
// jmp print::reset
//
// usage for clear:
// push pcx
// jmp print::clear
//
// usage for print_byte:
// push (register containing byte)
// push pcx
// jmp print::print_byte
//
// usage for print_word:
// push (register containing word)
// push pcx
// jmp print::print_word
//
// usage for print_num:
// push (register containing number to print in decimal)
// push pcx
// jmp print::print_num
//
include maths "./maths.dsa"
dw display: 0x20000
dw current: 0x20000
// ------------------------------------------
// prints the string at addr(arg[0]) to the screen. (no trailing whitespace unless explicitly provided)
print:
push bpr
mov spr, bpr
ldw bpr, rg0, 8
ldw current, rg1
_print_loop:
ldb rg0, acc
cmp acc, zero
jeq _end
stb acc, rg1
addi rg0, 1
addi rg1, 1
jmp _print_loop
// ------------------------------------------
println:
push bpr
mov spr, bpr
ldw bpr, rg0, 8
ldw current, rg1
_println_loop:
ldb rg0, acc
cmp acc, zero
jeq _println_end
stb acc, rg1
addi rg0, 1
addi rg1, 1
jmp _println_loop
_println_end:
call print_newline
jmp _end
// ------------------------------------------
// prints the value of arg[0] to the screen.
print_word:
// initialise
push bpr
mov spr, bpr
// load byte into acc
ldw bpr, rg0, 8
ldw current, rg1
addi rg1, 3
stb rg0, rg1
subi rg1, 1
shr rg0, 8
stb rg0, rg1
subi rg1, 1
shr rg0, 8
stb rg0, rg1
subi rg1, 1
shr rg0, 8
stb rg0, rg1
addi rg1, 4
jmp _end
// ------------------------------------------
// prints the last byte of arg[0] to the screen.
print_byte:
push bpr
mov spr, bpr
ldw bpr, rg0, 8
ldw current, rg1
stb rg0, rg1
addi rg1, 1
jmp _end
// ------------------------------------------
// prints the value of arg[0] to the screen in hex.
print_hex_word:
push bpr
mov spr, bpr
ldw current, rg1
ldb bpr, rg0, 8
push rg0
call _print_hex_byte
addi spr, 4
ldb bpr, rg0, 9
push rg0
call _print_hex_byte
addi spr, 4
ldb bpr, rg0, 10
push rg0
call _print_hex_byte
addi spr, 4
ldb bpr, rg0, 11
push rg0
call _print_hex_byte
addi spr, 4
jmp _end
// ------------------------------------------
// prints the last byte of arg[0] to the screen in hex.
print_hex_byte:
push bpr
mov spr, bpr
ldw bpr, rg0, 8
ldw current, rg1
call _print_hex_byte
jmp _end
// function body
_print_hex_byte:
// mask to get lower nibble
lli 0xF, rg2
// save rg0 state
push rg0
shr rg0, 4
and rg0, rg2, rg0
call _print_hex_nibble
pop rg0
and rg0, rg2, rg0
call _print_hex_nibble
return
// print a hex digit
_print_hex_nibble:
lli 10, rg3
cmp rg0, rg3
jlt _print_hex_nibble_number
addi rg0, 0x37, rg0
stb rg0, rg1
addi rg1, 1
return
// helper function.
_print_hex_nibble_number:
addi rg0, 0x30, rg0
stb rg0, rg1
addi rg1, 1
return
// ------------------------------------------
// print whitespace
print_whitespace:
push bpr
mov spr, bpr
ldw current, rg1
lli 0x20, rg0
stb rg0, rg1
addi rg1, 1
jmp _end
// ------------------------------------------
// print newline
print_newline:
push bpr
mov spr, bpr
// load variables into registers
ldw display, rg0
ldw current, rg1
// get the offset from the display base
sub rg1, rg0, rg0
lwi 80, rg2
pusha 3
push rg0
push rg2
call maths::divmod
pop zero // result
pop rg3 // remainder
popa 3
sub rg1, rg3, rg2
addi rg2, 80, rg1
// _end saves the display state
jmp _end
// ------------------------------------------
// prints arg[0] as a decimal number to the screen.
print_num:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // load number to print
lli 0, rg5 // rg5 = digit counter
// check if number is zero
cmp rg0, zero
jne _print_num_extract_digits
// special case: print '0' for zero
lli 0x30, rg6
push rg6 // push digit to stack buffer
lli 1, rg5 // we have 1 digit
jmp _print_num_output
_print_num_extract_digits:
// divide by 10 repeatedly to get digits
cmp rg0, zero
jeq _print_num_output
// call divmod(rg0, 10)
push rg0 // dividend
lli 10, rg1
push rg1 // divisor (10)
call maths::divmod
pop rg0 // quotient (continue dividing this)
pop rg1 // remainder (the digit)
// convert digit to ASCII and push to stack buffer
addi rg1, 0x30, rg6 // convert to ASCII
push rg6 // push digit to stack
inc rg5 // increment digit counter
jmp _print_num_extract_digits
_print_num_output:
// now print digits (pop them off in reverse order)
ldw current, rg1 // get display pointer
_print_num_output_loop:
// check if we've printed all digits
cmp rg5, zero
jeq _print_num_done
// pop digit and print it
pop rg6
stb rg6, rg1
addi rg1, 1
dec rg5
jmp _print_num_output_loop
_print_num_done:
jmp _end
// ------------------------------------------
// resets the cursor position on the screen to 0x20000. (0,0)
reset:
push bpr
mov spr, bpr
ldw display, rg1
jmp _end
// ------------------------------------------
// clears the screen
clear:
push bpr
mov spr, bpr
// display size = 2000 bytes / 500 words
lli 500 rg0
ldw display, rg1
_clear_loop:
dec rg0
stw zero, rg1
addi rg1, 4
cmp rg0, zero
jgt _clear_loop
jmp _end
// ------------------------------------------
// return
_end:
stw rg1, current
mov bpr, spr
pop bpr
return
"#,
)
}
pub fn create_maths_lib() -> String {
String::from(
r#"
// multiply.dsa
// usage:
//
// include multiply "<relative path>"
//
// usage for multiply:
// push (arg1)
// push (arg0)
// call multiply::multiply
// pop (arg0)
// pop (arg1)
multiply:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // load op 2
ldw bpr, rg1, 12 // load op 1
lwi 0, rg2 // initialise rg2 to zero
_multiply_loop:
add rg2, rg0, rg2
dec rg1
cmp rg1, zero
jgt _multiply_loop
_multiply_end:
stw rg2, bpr, 8
mov bpr, spr
pop bpr
return
divmod:
push bpr
mov spr, bpr
ldw bpr, rg1, 8 // load op 2
ldw bpr, rg0, 12 // load op 1
lli 0, rg3
_divmod_loop:
cmp rg0, rg1
jlt _divmod_end
sub rg0, rg1, rg0
inc rg3
jmp _divmod_loop
_divmod_end:
// store div in first arg
// store mod in second arg
stw rg3, bpr, 8
stw rg0, bpr, 12
mov bpr, spr
pop bpr
return
// multiply.dsa - improved version
// Multiplies two 32-bit numbers using shift-and-add
//
// Usage:
// push operand2 (multiplier)
// push operand1 (multiplicand)
// call multiply::multiply
// pop result
// pop zero (discard second argument)
new_multiply:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // rg0 = multiplicand
ldw bpr, rg1, 12 // rg1 = multiplier
lli 0, rg2 // rg2 = result (accumulator)
lli 32, rg3 // rg3 = bit counter
mult_loop:
// Check if lowest bit of multiplier is 1
lli 1, acc
and rg1, acc, acc // acc = rg1 & 1
cmp acc, zero
jeq skip_add // if (rg1 & 1) == 0, skip addition
// Add multiplicand to result
add rg2, rg0, rg2
skip_add:
shl rg0, 1 // shift multiplicand left
shr rg1, 1 // shift multiplier right
dec rg3
cmp rg3, zero
jgt mult_loop
stw rg2, bpr, 8 // store result
mov bpr, spr
pop bpr
return
"#,
)
}
+15
View File
@@ -0,0 +1,15 @@
[package]
name = "dsx_common"
version.workspace = true
edition.workspace = true
authors.workspace = true
[dependencies]
compiler = { path = "../../core/compiler" }
assembler = { path = "../../core/assembler" }
common = { path = "../../core/dsa_common" }
chrono = "0.4.44"
serde = { version = "1.0.228", features = ["derive"] }
toml = "1.0.3"
walkdir = "2.5.0"
@@ -4,7 +4,7 @@ use std::{
process::Command, process::Command,
}; };
use crate::common::config::DsxConfig; use crate::config::DsxConfig;
use assembler::prelude::Assembler; use assembler::prelude::Assembler;
use common::build::{BuildError, Builder}; use common::build::{BuildError, Builder};
@@ -140,7 +140,7 @@ fn main() -> u32 {{
} }
pub fn create_print_lib() -> String { pub fn create_print_lib() -> String {
format!( String::from(
r#" r#"
// lib: // lib:
// print.dsa // print.dsa
@@ -473,12 +473,12 @@ _end:
mov bpr, spr mov bpr, spr
pop bpr pop bpr
return return
"# "#,
) )
} }
pub fn create_maths_lib() -> String { pub fn create_maths_lib() -> String {
format!( String::from(
r#" r#"
// multiply.dsa // multiply.dsa
// usage: // usage:
@@ -584,6 +584,6 @@ skip_add:
mov bpr, spr mov bpr, spr
pop bpr pop bpr
return return
"# "#,
) )
} }
@@ -1,4 +1,3 @@
use rocket::serde;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -1,3 +1,2 @@
pub mod builder; pub mod builder;
pub mod config; pub mod config;
pub mod templates;
@@ -1,23 +1,19 @@
[package] [package]
name = "dsx" name = "dsx_server"
version.workspace = true version.workspace = true
edition.workspace = true edition.workspace = true
authors.workspace = true authors.workspace = true
[[bin]] [[bin]]
name = "dsx_server" name = "dsx_server"
path = "src/server/server.rs" path = "src/main.rs"
[[bin]]
name = "dsx"
path = "src/client/client.rs"
[dependencies] [dependencies]
compiler = { path = "../compiler" } compiler = { path = "../../core/compiler" }
assembler = { path = "../assembler" } assembler = { path = "../../core/assembler" }
common = { path = "../common" } common = { path = "../../core/dsa_common" }
dsx_common = { path = "../dsx_common" }
anyhow = "1.0.102"
dotenv = "0.15.0" dotenv = "0.15.0"
rocket = { version = "0.5.1", features = ["json"] } rocket = { version = "0.5.1", features = ["json"] }
rocket_dyn_templates = { version = "0.2.0", features = ["tera"] } rocket_dyn_templates = { version = "0.2.0", features = ["tera"] }
@@ -1,5 +1,5 @@
use common::build::BuildError; use common::build::BuildError;
use rocket::{Response, http::Status, response::Responder}; use rocket::response::Responder;
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Serialize, Responder)] #[derive(Debug, Serialize, Responder)]
@@ -5,7 +5,6 @@ use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::LazyLock; use std::sync::LazyLock;
use anyhow::anyhow;
use rocket::Data; use rocket::Data;
use rocket::data::ToByteUnit; use rocket::data::ToByteUnit;
use rocket::serde::json::Json; use rocket::serde::json::Json;
@@ -15,11 +14,11 @@ use rocket_dyn_templates::{Template, context};
use dotenv::dotenv; use dotenv::dotenv;
use serde::Serialize; use serde::Serialize;
use tracing::{info, warn}; use tracing::warn;
use crate::error::ApiError; use crate::error::ApiError;
use crate::model::{Package, PackageMeta}; use crate::model::{Package, PackageMeta};
use dsx::common::config::DsxConfig; use dsx_common::config::DsxConfig;
mod error; mod error;
mod model; mod model;
@@ -1,7 +1,7 @@
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use dsx::common::config::DsxConfig; use dsx_common::config::DsxConfig;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{DATA_DIR, error::ApiError}; use crate::{DATA_DIR, error::ApiError};

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 201 KiB

-1
View File
@@ -1 +0,0 @@
pub mod common;
+5 -4
View File
@@ -14,10 +14,11 @@ name = "emulator"
required-features = ["config"] required-features = ["config"]
[dependencies] [dependencies]
common = { path = "../common" } common = { path = "../core/dsa_common" }
assembler = { path = "../assembler" } assembler = { path = "../core/assembler" }
compiler = { path = "../compiler" } compiler = { path = "../core/compiler" }
dsa_editor = { path = "../dsa_editor" } dsa_editor = { path = "./dsa_editor" }
egui = "0.31.1" egui = "0.31.1"
dirs = "6.0.0" dirs = "6.0.0"
discord-presence = { version = "2.0.0", optional = true } discord-presence = { version = "2.0.0", optional = true }
+6 -4
View File
@@ -1,10 +1,9 @@
use std::path::Path;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use std::{env, fs}; use std::{env, fs};
use crate::emulator::system::model::State;
use crate::emulator::system::model::{Command, Running}; use crate::emulator::system::model::{Command, Running};
use crate::emulator::{config::Config, system::model::State};
pub fn run_cli() -> Result<(), Box<dyn std::error::Error>> { pub fn run_cli() -> Result<(), Box<dyn std::error::Error>> {
// Initialize channels and read in configuration. // Initialize channels and read in configuration.
@@ -34,8 +33,11 @@ pub fn run_cli() -> Result<(), Box<dyn std::error::Error>> {
sleep(Duration::from_secs(1)); sleep(Duration::from_secs(1));
state.update().unwrap(); state.update().expect("state failed to update");
state.cmd_sender.send(Command::Start).unwrap(); state
.cmd_sender
.send(Command::Start)
.expect("state failed to update");
loop { loop {
sleep(Duration::from_millis(20)); sleep(Duration::from_millis(20));
state.send(Command::DisplayRequest); state.send(Command::DisplayRequest);
+1 -1
View File
@@ -114,7 +114,7 @@ pub fn run_emulator(
processor.memory.write_range(offset, data); processor.memory.write_range(offset, data);
} }
Command::Interrupt(_interrupt) => { Command::Interrupt(_interrupt) => {
update = true; // update = true;
todo!("implement interrupts") todo!("implement interrupts")
} }