Skip to content

Commit 182bea6

Browse files
committed
fix #10: add c, comma-separated, and logisim output formats; update rust syntax
1 parent 58f4f37 commit 182bea6

File tree

13 files changed

+183
-44
lines changed

13 files changed

+183
-44
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ Usage: customasm [options] <asm-file-1> ... <asm-file-N>
2828
Options:
2929
-f, --format FORMAT The format of the output file. Possible formats:
3030
binary, binstr, hexstr, bindump, hexdump,
31-
mif, intelhex
31+
mif, intelhex, deccomma, hexcomma, decc, hexc,
32+
logisim8, logisim16
3233
3334
-o, --output FILE The name of the output file.
3435
-p, --print Print output to stdout instead of writing to a file.

build_wasm.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build wasm binary
2-
cargo +nightly build --target wasm32-unknown-unknown --release
2+
cargo +nightly build --lib --target wasm32-unknown-unknown --release
33

44
# Reduce binary size
55
wasm-gc "./target/wasm32-unknown-unknown/release/customasm.wasm" -o "./target/wasm32-unknown-unknown/release/customasm.gc.wasm"

src/asm/assembler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl AssemblerState
7171
}
7272

7373

74-
pub fn process_file<S>(&mut self, report: RcReport, fileserver: &FileServer, filename: S) -> Result<(), ()>
74+
pub fn process_file<S>(&mut self, report: RcReport, fileserver: &dyn FileServer, filename: S) -> Result<(), ()>
7575
where S: Into<String>
7676
{
7777
AssemblerParser::parse_file(report.clone(), self, fileserver, filename, None)?;

src/asm/binary_output.rs

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ impl BinaryOutput
220220
let mut index = start_bit;
221221
while index < end_bit
222222
{
223+
result.push_str(&format!(" {:1$X}: ", index / 8, addr_max_width));
224+
223225
let mut byte: u8 = 0;
224226
for _ in 0..8
225227
{
@@ -228,7 +230,6 @@ impl BinaryOutput
228230
index += 1;
229231
}
230232

231-
result.push_str(&format!("{:1$X}: ", index / 8, addr_max_width));
232233
result.push_str(&format!("{:02X};\n", byte));
233234
}
234235

@@ -280,4 +281,110 @@ impl BinaryOutput
280281
result.push_str(":00000001FF");
281282
result
282283
}
284+
285+
286+
pub fn generate_comma(&self, start_bit: usize, end_bit: usize, radix: usize) -> String
287+
{
288+
let mut result = String::new();
289+
290+
let mut index = start_bit;
291+
while index < end_bit
292+
{
293+
let mut byte: u8 = 0;
294+
for _ in 0..8
295+
{
296+
byte <<= 1;
297+
byte |= if self.read(index) { 1 } else { 0 };
298+
index += 1;
299+
}
300+
301+
match radix
302+
{
303+
10 => result.push_str(&format!("{}", byte)),
304+
16 => result.push_str(&format!("0x{:02x}", byte)),
305+
_ => panic!("invalid radix")
306+
}
307+
308+
if index < end_bit
309+
{
310+
result.push_str(", ");
311+
312+
if (index / 8) % 16 == 0
313+
{ result.push('\n'); }
314+
}
315+
}
316+
317+
result
318+
}
319+
320+
321+
pub fn generate_c_array(&self, start_bit: usize, end_bit: usize, radix: usize) -> String
322+
{
323+
let mut result = String::new();
324+
325+
result.push_str("const unsigned char data[] = {\n");
326+
327+
let byte_num = (end_bit - start_bit) / 8 + if (end_bit - start_bit) % 8 != 0 { 1 } else { 0 };
328+
let addr_max_width = format!("{:x}", byte_num - 1).len();
329+
330+
let mut index = start_bit;
331+
result.push_str(&format!("\t/* 0x{:01$x} */ ", 0, addr_max_width));
332+
333+
while index < end_bit
334+
{
335+
let mut byte: u8 = 0;
336+
for _ in 0..8
337+
{
338+
byte <<= 1;
339+
byte |= if self.read(index) { 1 } else { 0 };
340+
index += 1;
341+
}
342+
343+
match radix
344+
{
345+
10 => result.push_str(&format!("{}", byte)),
346+
16 => result.push_str(&format!("0x{:02x}", byte)),
347+
_ => panic!("invalid radix")
348+
}
349+
350+
if index < end_bit
351+
{
352+
result.push_str(", ");
353+
354+
if (index / 8) % 16 == 0
355+
{
356+
result.push_str(&format!("\n\t/* 0x{:01$x} */ ", index / 8, addr_max_width));
357+
}
358+
}
359+
}
360+
361+
result.push_str("\n};");
362+
result
363+
}
364+
365+
366+
// From: https://github.com/milanvidakovic/customasm/blob/master/src/asm/binary_output.rs#L84
367+
pub fn generate_logisim(&self, start_bit: usize, end_bit: usize, bits_per_chunk: usize) -> String
368+
{
369+
let mut result = String::new();
370+
result.push_str("v2.0 raw\n");
371+
372+
let mut index = start_bit;
373+
while index < end_bit
374+
{
375+
let mut value: u16 = 0;
376+
for _ in 0..bits_per_chunk
377+
{
378+
value <<= 1;
379+
value |= if self.read(index) { 1 } else { 0 };
380+
index += 1;
381+
}
382+
383+
result.push_str(&format!("{:01$x} ", value, bits_per_chunk / 4));
384+
if (index / 8) % 16 == 0
385+
{ result.push('\n'); }
386+
}
387+
388+
result
389+
}
283390
}

src/asm/parser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use num_traits::ToPrimitive;
1414

1515
pub struct AssemblerParser<'a>
1616
{
17-
pub fileserver: &'a FileServer,
17+
pub fileserver: &'a dyn FileServer,
1818
pub state: &'a mut AssemblerState,
1919
pub cur_filename: String,
2020
pub parser: Parser
@@ -23,12 +23,12 @@ pub struct AssemblerParser<'a>
2323

2424
impl<'a> AssemblerParser<'a>
2525
{
26-
pub fn parse_file<S>(report: RcReport, state: &mut AssemblerState, fileserver: &FileServer, filename: S, filename_span: Option<&Span>) -> Result<(), ()>
26+
pub fn parse_file<S>(report: RcReport, state: &mut AssemblerState, fileserver: &dyn FileServer, filename: S, filename_span: Option<&Span>) -> Result<(), ()>
2727
where S: Into<String>
2828
{
2929
let filename_owned = filename.into();
3030
let chars = fileserver.get_chars(report.clone(), &filename_owned, filename_span)?;
31-
let tokens = tokenize(report.clone(), filename_owned.as_ref(), &chars)?;
31+
let tokens = tokenize(report.clone(), AsRef::<str>::as_ref(&filename_owned), &chars)?;
3232

3333
let mut parser = AssemblerParser
3434
{

src/diagn/report.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ impl Report
130130
}
131131

132132

133-
pub fn has_error_at(&self, fileserver: &FileServer, filename: &str, line: usize, error_excerpt: &str) -> bool
133+
pub fn has_error_at(&self, fileserver: &dyn FileServer, filename: &str, line: usize, error_excerpt: &str) -> bool
134134
{
135135
for msg in &self.messages
136136
{
@@ -142,7 +142,7 @@ impl Report
142142
}
143143

144144

145-
fn msg_has_error_at(&self, msg: &Message, fileserver: &FileServer, filename: &str, line: usize, error_excerpt: &str) -> bool
145+
fn msg_has_error_at(&self, msg: &Message, fileserver: &dyn FileServer, filename: &str, line: usize, error_excerpt: &str) -> bool
146146
{
147147
match msg.inner
148148
{
@@ -183,7 +183,7 @@ impl Report
183183
}
184184

185185

186-
pub fn print_all(&self, writer: &mut Write, fileserver: &FileServer)
186+
pub fn print_all(&self, writer: &mut dyn Write, fileserver: &dyn FileServer)
187187
{
188188
for msg in &self.messages
189189
{
@@ -193,7 +193,7 @@ impl Report
193193
}
194194

195195

196-
fn print_msg(&self, writer: &mut Write, fileserver: &FileServer, msg: &Message, indent: usize)
196+
fn print_msg(&self, writer: &mut dyn Write, fileserver: &dyn FileServer, msg: &Message, indent: usize)
197197
{
198198
let kind_label = msg.kind.get_label();
199199
let highlight_color = msg.kind.get_color();
@@ -259,14 +259,14 @@ impl Report
259259
}
260260

261261

262-
fn print_indent(&self, writer: &mut Write, indent: usize)
262+
fn print_indent(&self, writer: &mut dyn Write, indent: usize)
263263
{
264264
for _ in 0..indent
265265
{ write!(writer, " ").unwrap(); }
266266
}
267267

268268

269-
fn print_msg_src(&self, writer: &mut Write, counter: &CharCounter, highlight_color: &'static str, line1: usize, col1: usize, line2: usize, col2: usize, indent: usize)
269+
fn print_msg_src(&self, writer: &mut dyn Write, counter: &CharCounter, highlight_color: &'static str, line1: usize, col1: usize, line2: usize, col2: usize, indent: usize)
270270
{
271271
let first_line = if (line1 as isize - 2) < 0
272272
{ 0 }
@@ -409,13 +409,13 @@ impl RcReport
409409
}
410410

411411

412-
pub fn has_error_at(&self, fileserver: &FileServer, filename: &str, line: usize, error_excerpt: &str) -> bool
412+
pub fn has_error_at(&self, fileserver: &dyn FileServer, filename: &str, line: usize, error_excerpt: &str) -> bool
413413
{
414414
self.report.borrow_mut().has_error_at(fileserver, filename, line, error_excerpt)
415415
}
416416

417417

418-
pub fn print_all(&self, writer: &mut Write, fileserver: &FileServer)
418+
pub fn print_all(&self, writer: &mut dyn Write, fileserver: &dyn FileServer)
419419
{
420420
self.report.borrow_mut().print_all(writer, fileserver);
421421
}

src/driver.rs

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@ enum OutputFormat
1616
HexDump,
1717
Mif,
1818
IntelHex,
19+
DecComma,
20+
HexComma,
21+
DecC,
22+
HexC,
23+
LogiSim8,
24+
LogiSim16,
1925
}
2026

2127

22-
pub fn drive(args: &Vec<String>, fileserver: &mut FileServer) -> Result<(), ()>
28+
pub fn drive(args: &Vec<String>, fileserver: &mut dyn FileServer) -> Result<(), ()>
2329
{
2430
let opts = make_opts();
2531

@@ -43,7 +49,7 @@ pub fn drive(args: &Vec<String>, fileserver: &mut FileServer) -> Result<(), ()>
4349
}
4450

4551

46-
fn drive_inner(report: RcReport, opts: &getopts::Options, args: &Vec<String>, fileserver: &mut FileServer) -> Result<(), bool>
52+
fn drive_inner(report: RcReport, opts: &getopts::Options, args: &Vec<String>, fileserver: &mut dyn FileServer) -> Result<(), bool>
4753
{
4854
let matches = parse_opts(report.clone(), opts, args).map_err(|_| true)?;
4955

@@ -64,13 +70,20 @@ fn drive_inner(report: RcReport, opts: &getopts::Options, args: &Vec<String>, fi
6470

6571
let out_format = match matches.opt_str("f").as_ref().map(|s| s.as_ref())
6672
{
67-
Some("binstr") => OutputFormat::BinStr,
68-
Some("bindump") => OutputFormat::BinDump,
69-
Some("hexstr") => OutputFormat::HexStr,
70-
Some("hexdump") => OutputFormat::HexDump,
71-
Some("binary") => OutputFormat::Binary,
72-
Some("mif") => OutputFormat::Mif,
73-
Some("intelhex") => OutputFormat::IntelHex,
73+
Some("binstr") => OutputFormat::BinStr,
74+
Some("bindump") => OutputFormat::BinDump,
75+
Some("hexstr") => OutputFormat::HexStr,
76+
Some("hexdump") => OutputFormat::HexDump,
77+
Some("binary") => OutputFormat::Binary,
78+
Some("mif") => OutputFormat::Mif,
79+
Some("intelhex") => OutputFormat::IntelHex,
80+
Some("deccomma") => OutputFormat::DecComma,
81+
Some("hexcomma") => OutputFormat::HexComma,
82+
Some("decc") => OutputFormat::DecC,
83+
Some("hexc") => OutputFormat::HexC,
84+
Some("c") => OutputFormat::HexC,
85+
Some("logisim8") => OutputFormat::LogiSim8,
86+
Some("logisim16") => OutputFormat::LogiSim16,
7487

7588
None => if out_stdout
7689
{ OutputFormat::HexDump }
@@ -110,13 +123,19 @@ fn drive_inner(report: RcReport, opts: &getopts::Options, args: &Vec<String>, fi
110123

111124
let output_data = match out_format
112125
{
113-
OutputFormat::Binary => assembled.generate_binary (0, assembled.len()),
114-
OutputFormat::BinStr => assembled.generate_binstr (0, assembled.len()).bytes().collect::<Vec<u8>>(),
115-
OutputFormat::BinDump => assembled.generate_bindump (0, assembled.len()).bytes().collect::<Vec<u8>>(),
116-
OutputFormat::HexStr => assembled.generate_hexstr (0, assembled.len()).bytes().collect::<Vec<u8>>(),
117-
OutputFormat::HexDump => assembled.generate_hexdump (0, assembled.len()).bytes().collect::<Vec<u8>>(),
118-
OutputFormat::Mif => assembled.generate_mif (0, assembled.len()).bytes().collect::<Vec<u8>>(),
119-
OutputFormat::IntelHex => assembled.generate_intelhex(0, assembled.len()).bytes().collect::<Vec<u8>>(),
126+
OutputFormat::Binary => assembled.generate_binary (0, assembled.len()),
127+
OutputFormat::BinStr => assembled.generate_binstr (0, assembled.len()).bytes().collect::<Vec<u8>>(),
128+
OutputFormat::BinDump => assembled.generate_bindump (0, assembled.len()).bytes().collect::<Vec<u8>>(),
129+
OutputFormat::HexStr => assembled.generate_hexstr (0, assembled.len()).bytes().collect::<Vec<u8>>(),
130+
OutputFormat::HexDump => assembled.generate_hexdump (0, assembled.len()).bytes().collect::<Vec<u8>>(),
131+
OutputFormat::Mif => assembled.generate_mif (0, assembled.len()).bytes().collect::<Vec<u8>>(),
132+
OutputFormat::IntelHex => assembled.generate_intelhex(0, assembled.len()).bytes().collect::<Vec<u8>>(),
133+
OutputFormat::DecComma => assembled.generate_comma (0, assembled.len(), 10).bytes().collect::<Vec<u8>>(),
134+
OutputFormat::HexComma => assembled.generate_comma (0, assembled.len(), 16).bytes().collect::<Vec<u8>>(),
135+
OutputFormat::DecC => assembled.generate_c_array (0, assembled.len(), 10).bytes().collect::<Vec<u8>>(),
136+
OutputFormat::HexC => assembled.generate_c_array (0, assembled.len(), 16).bytes().collect::<Vec<u8>>(),
137+
OutputFormat::LogiSim8 => assembled.generate_logisim (0, assembled.len(), 8).bytes().collect::<Vec<u8>>(),
138+
OutputFormat::LogiSim16 => assembled.generate_logisim (0, assembled.len(), 16).bytes().collect::<Vec<u8>>(),
120139
};
121140

122141
if out_stdout
@@ -145,7 +164,7 @@ fn drive_inner(report: RcReport, opts: &getopts::Options, args: &Vec<String>, fi
145164
fn make_opts() -> getopts::Options
146165
{
147166
let mut opts = getopts::Options::new();
148-
opts.optopt("f", "format", "The format of the output file. Possible formats: binary, binstr, hexstr, bindump, hexdump, mif, intelhex", "FORMAT");
167+
opts.optopt("f", "format", "The format of the output file. Possible formats: binary, binstr, hexstr, bindump, hexdump, mif, intelhex, deccomma, hexcomma, decc, hexc, logisim8, logisim16", "FORMAT");
149168
opts.optmulti("i", "include", "Specifies an additional file for processing before the given <asm-files>. [deprecated]", "FILE");
150169
opts.optopt("o", "output", "The name of the output file.", "FILE");
151170
opts.optflag("p", "print", "Print output to stdout instead of writing to a file.");
@@ -201,7 +220,7 @@ fn get_default_output_filename(report: RcReport, input_filename: &str) -> Result
201220
}
202221

203222

204-
pub fn assemble(report: RcReport, fileserver: &FileServer, filenames: &[String], quiet: bool) -> Result<BinaryOutput, ()>
223+
pub fn assemble(report: RcReport, fileserver: &dyn FileServer, filenames: &[String], quiet: bool) -> Result<BinaryOutput, ()>
205224
{
206225
if !quiet
207226
{ print_header(); }

src/test/asm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ where S: Into<Vec<u8>>
3939
}
4040

4141

42-
fn test_fileserver<S>(fileserver: &FileServer, asm_filename: S, expected: ExpectedResult<(usize, &'static str)>)
42+
fn test_fileserver<S>(fileserver: &dyn FileServer, asm_filename: S, expected: ExpectedResult<(usize, &'static str)>)
4343
where S: Into<String>
4444
{
4545
let bits = if let Pass(expected) = expected
4646
{ expected.0 }
4747
else
4848
{ 4 };
4949

50-
let assemble = |report: RcReport, fileserver: &FileServer, filename: S| -> Result<(usize, String), ()>
50+
let assemble = |report: RcReport, fileserver: &dyn FileServer, filename: S| -> Result<(usize, String), ()>
5151
{
5252
let mut asm = AssemblerState::new();
5353
asm.process_file(report.clone(), fileserver, filename)?;

src/test/cpudef.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::{ExpectedResult, expect_result};
99
fn test<S>(src: S, expected: ExpectedResult<()>)
1010
where S: Into<Vec<u8>>
1111
{
12-
let compile = |report: RcReport, fileserver: &FileServer| -> Result<(), ()>
12+
let compile = |report: RcReport, fileserver: &dyn FileServer| -> Result<(), ()>
1313
{
1414
let chars = fileserver.get_chars(report.clone(), "test", None)?;
1515
let tokens = tokenize(report.clone(), "test", &chars)?;

src/test/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub enum ExpectedResult<T>
1919
}
2020

2121

22-
pub fn expect_result<T>(report: RcReport, fileserver: &FileServer, got: Option<T>, expected: ExpectedResult<T>)
22+
pub fn expect_result<T>(report: RcReport, fileserver: &dyn FileServer, got: Option<T>, expected: ExpectedResult<T>)
2323
where T: Debug + PartialEq
2424
{
2525
enable_windows_ansi_support();

0 commit comments

Comments
 (0)